diff --git a/.gitignore b/.gitignore index 6d14149ac..d09feee82 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ DerivedData /Extensions/Carthage /Tests/JS-A+/build +.swiftpm/ diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a62..000000000 --- a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/PromiseKit.xcodeproj/project.pbxproj b/PromiseKit.xcodeproj/project.pbxproj index 96dc451f3..24dcc0fee 100644 --- a/PromiseKit.xcodeproj/project.pbxproj +++ b/PromiseKit.xcodeproj/project.pbxproj @@ -83,6 +83,8 @@ 9E4170F9287D88C900A3B4B5 /* Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4170F8287D88C800A3B4B5 /* Async.swift */; }; 9E4170FC287D8DF900A3B4B5 /* AsyncTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4170FA287D8DBD00A3B4B5 /* AsyncTests.swift */; }; 9E66231626FE5A8C00FA25CB /* RaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E66231526FE5A8C00FA25CB /* RaceTests.m */; }; + 9EC774272991495C00803027 /* Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC774262991495C00803027 /* Combine.swift */; }; + 9EC7742A2991498200803027 /* CombineTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC774282991497900803027 /* CombineTests.swift */; }; C013F7382048E3B6006B57B1 /* MockNodeEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F7372048E3B6006B57B1 /* MockNodeEnvironment.swift */; }; C013F73A2049076A006B57B1 /* JSPromise.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F7392049076A006B57B1 /* JSPromise.swift */; }; C013F73C20494291006B57B1 /* JSAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C013F73B20494291006B57B1 /* JSAdapter.swift */; }; @@ -229,6 +231,8 @@ 9E4170F8287D88C800A3B4B5 /* Async.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Async.swift; path = Sources/Async.swift; sourceTree = ""; }; 9E4170FA287D8DBD00A3B4B5 /* AsyncTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncTests.swift; sourceTree = ""; }; 9E66231526FE5A8C00FA25CB /* RaceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RaceTests.m; sourceTree = ""; }; + 9EC774262991495C00803027 /* Combine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Combine.swift; path = Sources/Combine.swift; sourceTree = ""; }; + 9EC774282991497900803027 /* CombineTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineTests.swift; sourceTree = ""; }; C013F7372048E3B6006B57B1 /* MockNodeEnvironment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MockNodeEnvironment.swift; path = "Tests/JS-A+/MockNodeEnvironment.swift"; sourceTree = ""; }; C013F7392049076A006B57B1 /* JSPromise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = JSPromise.swift; path = "Tests/JS-A+/JSPromise.swift"; sourceTree = ""; }; C013F73B20494291006B57B1 /* JSAdapter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = JSAdapter.swift; path = "Tests/JS-A+/JSAdapter.swift"; sourceTree = ""; }; @@ -341,6 +345,7 @@ isa = PBXGroup; children = ( 9E4170FA287D8DBD00A3B4B5 /* AsyncTests.swift */, + 9EC774282991497900803027 /* CombineTests.swift */, 63CF6D7F203CD19200EC8927 /* ThenableTests.swift */, 632FBBE41F33B338008F8FBB /* CatchableTests.swift */, 635D64081D59635300BC0AF5 /* PromiseTests.swift */, @@ -440,6 +445,7 @@ isa = PBXGroup; children = ( 9E4170F8287D88C800A3B4B5 /* Async.swift */, + 9EC774262991495C00803027 /* Combine.swift */, 636A29191F1C156B001229C2 /* Promise.swift */, 636A29221F1C17A6001229C2 /* Guarantee.swift */, 636A29201F1C1716001229C2 /* Thenable.swift */, @@ -686,6 +692,7 @@ 630A8056203CEF6800D25F23 /* AnyPromiseTests.m in Sources */, 635D64221D59635300BC0AF5 /* ZalgoTests.swift in Sources */, 635D64271D59635300BC0AF5 /* RaceTests.swift in Sources */, + 9EC7742A2991498200803027 /* CombineTests.swift in Sources */, 632FBBE51F33B338008F8FBB /* CatchableTests.swift in Sources */, 63CF6D80203CD19200EC8927 /* ThenableTests.swift in Sources */, 635D642B1D59635300BC0AF5 /* StressTests.swift in Sources */, @@ -773,6 +780,7 @@ 63B0AC8B1D595E6300FA21D9 /* join.m in Sources */, 63B0AC891D595E6300FA21D9 /* hang.m in Sources */, 63B0AC831D595E6300FA21D9 /* AnyPromise.swift in Sources */, + 9EC774272991495C00803027 /* Combine.swift in Sources */, 63D9B2F120338D5D0075C00B /* Deprecations.swift in Sources */, 63B0AC871D595E6300FA21D9 /* Error.swift in Sources */, 0CC3AF2B1FCF84F7000E98C9 /* hang.swift in Sources */, diff --git a/Sources/Combine.swift b/Sources/Combine.swift new file mode 100644 index 000000000..901497eb7 --- /dev/null +++ b/Sources/Combine.swift @@ -0,0 +1,29 @@ +#if swift(>=4.1) +#if canImport(Combine) +import Combine + +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) +public extension Guarantee { + func future() -> Future { + .init { [weak self] promise in + self?.done { value in + promise(.success(value)) + } + } + } +} + +@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) +public extension Promise { + func future() -> Future { + .init { [weak self] promise in + self?.done { value in + promise(.success(value)) + }.catch { error in + promise(.failure(error)) + } + } + } +} +#endif +#endif diff --git a/Tests/CorePromise/AsyncTests.swift b/Tests/CorePromise/AsyncTests.swift index c075aef6b..fa1dd61ac 100644 --- a/Tests/CorePromise/AsyncTests.swift +++ b/Tests/CorePromise/AsyncTests.swift @@ -1,5 +1,4 @@ import PromiseKit -import Dispatch import XCTest private enum Error: Swift.Error { case dummy } diff --git a/Tests/CorePromise/CombineTests.swift b/Tests/CorePromise/CombineTests.swift new file mode 100644 index 000000000..ea27af45b --- /dev/null +++ b/Tests/CorePromise/CombineTests.swift @@ -0,0 +1,118 @@ +#if swift(>=4.1) +#if canImport(Combine) +import Combine +#endif +#endif +import PromiseKit +import XCTest + +private enum Error: Swift.Error { case dummy } + +class CombineTests: XCTestCase { + private var cancellable: Any? + + override func tearDown() { + #if swift(>=4.1) + #if canImport(Combine) + if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) { + (cancellable as? AnyCancellable)?.cancel() + } + #endif + #endif + } + + func testCombinePromiseValue() { + let ex = expectation(description: "") + #if swift(>=4.1) + #if canImport(Combine) + if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) { + let promise = after(.milliseconds(100)).then(on: nil){ Promise.value(1) } + cancellable = promise.future().sink(receiveCompletion: { result in + switch result { + case .failure: + XCTAssert(false) + default: + XCTAssert(true) + } + }, receiveValue: { + XCTAssertEqual($0, 1) + ex.fulfill() + }) + } else { + ex.fulfill() + } + #else + ex.fulfill() + #endif + #else + ex.fulfill() + #endif + + wait(for: [ex], timeout: 1) + } + + func testCombineGuaranteeValue() { + let ex = expectation(description: "") + #if swift(>=4.1) + #if canImport(Combine) + if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) { + let promise = after(.milliseconds(100)).then(on: nil){ Guarantee.value(1) } + cancellable = promise.future().sink(receiveCompletion: { result in + switch result { + case .failure: + XCTAssert(false) + default: + XCTAssert(true) + } + }, receiveValue: { + XCTAssertEqual($0, 1) + ex.fulfill() + }) + } else { + ex.fulfill() + } + #else + ex.fulfill() + #endif + #else + ex.fulfill() + #endif + + wait(for: [ex], timeout: 1) + } + + func testCombinePromiseThrow() { + let ex = expectation(description: "") + #if swift(>=4.1) + #if canImport(Combine) + if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *) { + let promise = after(.milliseconds(100)).then(on: nil){ Promise(error: Error.dummy) }.then(on: nil){ Promise.value(1) } + cancellable = promise.future().sink(receiveCompletion: { result in + switch result { + case .failure(let error): + switch error as? Error { + case .dummy: + XCTAssert(true) + default: + XCTAssert(false) + } + default: + XCTAssert(false) + } + ex.fulfill() + }, receiveValue: { _ in + XCTAssert(false) + }) + } else { + ex.fulfill() + } + #else + ex.fulfill() + #endif + #else + ex.fulfill() + #endif + + wait(for: [ex], timeout: 1) + } +} diff --git a/Tests/CorePromise/XCTestManifests.swift b/Tests/CorePromise/XCTestManifests.swift index c5e564f96..8785e2c41 100644 --- a/Tests/CorePromise/XCTestManifests.swift +++ b/Tests/CorePromise/XCTestManifests.swift @@ -66,6 +66,17 @@ extension CatchableTests { ] } +extension CombineTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__CombineTests = [ + ("testCombineGuaranteeValue", testCombineGuaranteeValue), + ("testCombinePromiseThrow", testCombinePromiseThrow), + ("testCombinePromiseValue", testCombinePromiseValue), + ] +} + extension GuaranteeTests { // DO NOT MODIFY: This is autogenerated, use: // `swift test --generate-linuxmain` @@ -313,6 +324,7 @@ public func __allTests() -> [XCTestCaseEntry] { testCase(AsyncTests.__allTests__AsyncTests), testCase(CancellationTests.__allTests__CancellationTests), testCase(CatchableTests.__allTests__CatchableTests), + testCase(CombineTests.__allTests__CombineTests), testCase(GuaranteeTests.__allTests__GuaranteeTests), testCase(HangTests.__allTests__HangTests), testCase(JoinTests.__allTests__JoinTests),