Add PromiseKit dependency
- Added PromiseKit dependency
This commit is contained in:
185
Carthage/Checkouts/PromiseKit/Tests/A+/0.0.0.swift
vendored
Normal file
185
Carthage/Checkouts/PromiseKit/Tests/A+/0.0.0.swift
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
import PromiseKit
|
||||
import Dispatch
|
||||
import XCTest
|
||||
|
||||
enum Error: Swift.Error {
|
||||
case dummy // we reject with this when we don't intend to test against it
|
||||
case sentinel(UInt32)
|
||||
}
|
||||
|
||||
private let timeout: TimeInterval = 10
|
||||
|
||||
extension XCTestCase {
|
||||
func describe(_ description: String, file: StaticString = #file, line: UInt = #line, body: () throws -> Void) {
|
||||
|
||||
PromiseKit.conf.Q.map = .main
|
||||
|
||||
do {
|
||||
try body()
|
||||
} catch {
|
||||
XCTFail(description, file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func specify(_ description: String, file: StaticString = #file, line: UInt = #line, body: ((promise: Promise<Void>, fulfill: () -> Void, reject: (Error) -> Void), XCTestExpectation) throws -> Void) {
|
||||
let expectation = self.expectation(description: description)
|
||||
let (pending, seal) = Promise<Void>.pending()
|
||||
|
||||
do {
|
||||
try body((pending, { seal.fulfill(()) }, seal.reject), expectation)
|
||||
waitForExpectations(timeout: timeout) { err in
|
||||
if let _ = err {
|
||||
XCTFail("wait failed: \(description)", file: file, line: line)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
XCTFail(description, file: file, line: line)
|
||||
}
|
||||
}
|
||||
|
||||
func testFulfilled(file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, XCTestExpectation, UInt32) -> Void) {
|
||||
testFulfilled(withExpectationCount: 1, file: file, line: line) {
|
||||
body($0, $1.first!, $2)
|
||||
}
|
||||
}
|
||||
|
||||
func testRejected(file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, XCTestExpectation, UInt32) -> Void) {
|
||||
testRejected(withExpectationCount: 1, file: file, line: line) {
|
||||
body($0, $1.first!, $2)
|
||||
}
|
||||
}
|
||||
|
||||
func testFulfilled(withExpectationCount: Int, file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) {
|
||||
|
||||
let specify = mkspecify(withExpectationCount, file: file, line: line, body: body)
|
||||
|
||||
specify("already-fulfilled") { value in
|
||||
return (.value(value), {})
|
||||
}
|
||||
specify("immediately-fulfilled") { value in
|
||||
let (promise, seal) = Promise<UInt32>.pending()
|
||||
return (promise, {
|
||||
seal.fulfill(value)
|
||||
})
|
||||
}
|
||||
specify("eventually-fulfilled") { value in
|
||||
let (promise, seal) = Promise<UInt32>.pending()
|
||||
return (promise, {
|
||||
after(ticks: 5) {
|
||||
seal.fulfill(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testRejected(withExpectationCount: Int, file: StaticString = #file, line: UInt = #line, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) {
|
||||
|
||||
let specify = mkspecify(withExpectationCount, file: file, line: line, body: body)
|
||||
|
||||
specify("already-rejected") { sentinel in
|
||||
return (Promise(error: Error.sentinel(sentinel)), {})
|
||||
}
|
||||
specify("immediately-rejected") { sentinel in
|
||||
let (promise, seal) = Promise<UInt32>.pending()
|
||||
return (promise, {
|
||||
seal.reject(Error.sentinel(sentinel))
|
||||
})
|
||||
}
|
||||
specify("eventually-rejected") { sentinel in
|
||||
let (promise, seal) = Promise<UInt32>.pending()
|
||||
return (promise, {
|
||||
after(ticks: 50) {
|
||||
seal.reject(Error.sentinel(sentinel))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private func mkspecify(_ numberOfExpectations: Int, file: StaticString, line: UInt, body: @escaping (Promise<UInt32>, [XCTestExpectation], UInt32) -> Void) -> (String, _ feed: (UInt32) -> (Promise<UInt32>, () -> Void)) -> Void {
|
||||
return { desc, feed in
|
||||
let value = arc4random()
|
||||
let (promise, executeAfter) = feed(value)
|
||||
let expectations = (1...numberOfExpectations).map {
|
||||
self.expectation(description: "\(desc) (\($0))")
|
||||
}
|
||||
body(promise, expectations, value)
|
||||
|
||||
executeAfter()
|
||||
|
||||
self.waitForExpectations(timeout: timeout) { err in
|
||||
if let _ = err {
|
||||
XCTFail("timed out: \(desc)", file: file, line: line)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mkex() -> XCTestExpectation {
|
||||
return expectation(description: "")
|
||||
}
|
||||
}
|
||||
|
||||
func after(ticks: Int, execute body: @escaping () -> Void) {
|
||||
precondition(ticks > 0)
|
||||
|
||||
var ticks = ticks
|
||||
func f() {
|
||||
DispatchQueue.main.async {
|
||||
ticks -= 1
|
||||
if ticks == 0 {
|
||||
body()
|
||||
} else {
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
f()
|
||||
}
|
||||
|
||||
extension Promise {
|
||||
func test(onFulfilled: @escaping () -> Void, onRejected: @escaping () -> Void) {
|
||||
tap { result in
|
||||
switch result {
|
||||
case .fulfilled:
|
||||
onFulfilled()
|
||||
case .rejected:
|
||||
onRejected()
|
||||
}
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
|
||||
prefix func ++(a: inout Int) -> Int {
|
||||
a += 1
|
||||
return a
|
||||
}
|
||||
|
||||
extension Promise {
|
||||
func silenceWarning() {}
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
import func Glibc.random
|
||||
|
||||
func arc4random() -> UInt32 {
|
||||
return UInt32(random())
|
||||
}
|
||||
|
||||
extension XCTestExpectation {
|
||||
func fulfill() {
|
||||
fulfill(#file, line: #line)
|
||||
}
|
||||
}
|
||||
|
||||
extension XCTestCase {
|
||||
func wait(for: [XCTestExpectation], timeout: TimeInterval, file: StaticString = #file, line: UInt = #line) {
|
||||
#if !(swift(>=4.0) && !swift(>=4.1))
|
||||
let line = Int(line)
|
||||
#endif
|
||||
waitForExpectations(timeout: timeout, file: file, line: line)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
26
Carthage/Checkouts/PromiseKit/Tests/A+/2.1.2.swift
vendored
Normal file
26
Carthage/Checkouts/PromiseKit/Tests/A+/2.1.2.swift
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test212: XCTestCase {
|
||||
func test() {
|
||||
describe("2.1.2.1: When fulfilled, a promise: must not transition to any other state.") {
|
||||
testFulfilled { promise, expectation, _ in
|
||||
promise.test(onFulfilled: expectation.fulfill, onRejected: { XCTFail() })
|
||||
}
|
||||
|
||||
specify("trying to fulfill then immediately reject") { d, expectation in
|
||||
d.promise.test(onFulfilled: expectation.fulfill, onRejected: { XCTFail() })
|
||||
d.fulfill()
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
|
||||
specify("trying to fulfill then reject, delayed") { d, expectation in
|
||||
d.promise.test(onFulfilled: expectation.fulfill, onRejected: { XCTFail() })
|
||||
after(ticks: 1) {
|
||||
d.fulfill()
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Carthage/Checkouts/PromiseKit/Tests/A+/2.1.3.swift
vendored
Normal file
34
Carthage/Checkouts/PromiseKit/Tests/A+/2.1.3.swift
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test213: XCTestCase {
|
||||
func test() {
|
||||
describe("2.1.3.1: When rejected, a promise: must not transition to any other state.") {
|
||||
testRejected { promise, expectation, _ in
|
||||
promise.test(onFulfilled: { XCTFail() }, onRejected: expectation.fulfill)
|
||||
}
|
||||
|
||||
specify("trying to reject then immediately fulfill") { d, expectation in
|
||||
d.promise.test(onFulfilled: { XCTFail() }, onRejected: expectation.fulfill)
|
||||
d.reject(Error.dummy)
|
||||
d.fulfill()
|
||||
}
|
||||
|
||||
specify("trying to reject then fulfill, delayed") { d, expectation in
|
||||
d.promise.test(onFulfilled: { XCTFail() }, onRejected: expectation.fulfill)
|
||||
after(ticks: 1) {
|
||||
d.reject(Error.dummy)
|
||||
d.fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
specify("trying to reject immediately then fulfill delayed") { d, expectation in
|
||||
d.promise.test(onFulfilled: { XCTFail() }, onRejected: expectation.fulfill)
|
||||
d.reject(Error.dummy)
|
||||
after(ticks: 1) {
|
||||
d.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
92
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.2.swift
vendored
Normal file
92
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.2.swift
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test222: XCTestCase {
|
||||
func test() {
|
||||
describe("2.2.2: If `onFulfilled` is a function,") {
|
||||
describe("2.2.2.1: it must be called after `promise` is fulfilled, with `promise`’s fulfillment value as its first argument.") {
|
||||
testFulfilled { promise, expectation, sentinel in
|
||||
promise.done {
|
||||
XCTAssertEqual(sentinel, $0)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
|
||||
describe("2.2.2.2: it must not be called before `promise` is fulfilled") {
|
||||
specify("fulfilled after a delay") { d, expectation in
|
||||
var called = false
|
||||
d.promise.done {
|
||||
called = true
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
after(ticks: 5) {
|
||||
XCTAssertFalse(called)
|
||||
d.fulfill()
|
||||
}
|
||||
}
|
||||
specify("never fulfilled") { d, expectation in
|
||||
d.promise.done{ XCTFail() }.silenceWarning()
|
||||
after(ticks: 1000, execute: expectation.fulfill)
|
||||
}
|
||||
}
|
||||
|
||||
describe("2.2.2.3: it must not be called more than once.") {
|
||||
specify("already-fulfilled") { _, expectation in
|
||||
let ex = (expectation, mkex())
|
||||
Promise().done {
|
||||
ex.0.fulfill()
|
||||
}.silenceWarning()
|
||||
after(ticks: 1000) {
|
||||
ex.1.fulfill()
|
||||
}
|
||||
}
|
||||
specify("trying to fulfill a pending promise more than once, immediately") { d, expectation in
|
||||
d.promise.done(expectation.fulfill).silenceWarning()
|
||||
d.fulfill()
|
||||
d.fulfill()
|
||||
}
|
||||
specify("trying to fulfill a pending promise more than once, delayed") { d, expectation in
|
||||
d.promise.done(expectation.fulfill).silenceWarning()
|
||||
after(ticks: 5) {
|
||||
d.fulfill()
|
||||
d.fulfill()
|
||||
}
|
||||
}
|
||||
specify("trying to fulfill a pending promise more than once, immediately then delayed") { d, expectation in
|
||||
let ex = (expectation, mkex())
|
||||
d.promise.done(ex.0.fulfill).silenceWarning()
|
||||
d.fulfill()
|
||||
after(ticks: 5) {
|
||||
d.fulfill()
|
||||
}
|
||||
after(ticks: 10, execute: ex.1.fulfill)
|
||||
}
|
||||
specify("when multiple `then` calls are made, spaced apart in time") { d, expectation in
|
||||
let ex = (expectation, self.expectation(description: ""), self.expectation(description: ""), self.expectation(description: ""))
|
||||
|
||||
do {
|
||||
d.promise.done(ex.0.fulfill).silenceWarning()
|
||||
}
|
||||
after(ticks: 5) {
|
||||
d.promise.done(ex.1.fulfill).silenceWarning()
|
||||
}
|
||||
after(ticks: 10) {
|
||||
d.promise.done(ex.2.fulfill).silenceWarning()
|
||||
}
|
||||
after(ticks: 15) {
|
||||
d.fulfill()
|
||||
ex.3.fulfill()
|
||||
}
|
||||
}
|
||||
specify("when `then` is interleaved with fulfillment") { d, expectation in
|
||||
let ex = (expectation, self.expectation(description: ""), self)
|
||||
|
||||
d.promise.done(ex.0.fulfill).silenceWarning()
|
||||
d.fulfill()
|
||||
d.promise.done(ex.1.fulfill).silenceWarning()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
93
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.3.swift
vendored
Normal file
93
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.3.swift
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test223: XCTestCase {
|
||||
func test() {
|
||||
describe("2.2.3: If `onRejected` is a function,") {
|
||||
describe("2.2.3.1: it must be called after `promise` is rejected, with `promise`’s rejection reason as its first argument.") {
|
||||
testRejected { promise, expectation, sentinel in
|
||||
promise.catch { error in
|
||||
if case Error.sentinel(let value) = error {
|
||||
XCTAssertEqual(value, sentinel)
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("2.2.3.2: it must not be called before `promise` is rejected") {
|
||||
specify("rejected after a delay") { d, expectation in
|
||||
var called = false
|
||||
d.promise.catch { _ in
|
||||
called = true
|
||||
expectation.fulfill()
|
||||
}
|
||||
after(ticks: 1) {
|
||||
XCTAssertFalse(called)
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
}
|
||||
specify("never rejected") { d, expectation in
|
||||
d.promise.catch { _ in XCTFail() }
|
||||
after(ticks: 1, execute: expectation.fulfill)
|
||||
}
|
||||
}
|
||||
describe("2.2.3.3: it must not be called more than once.") {
|
||||
specify("already-rejected") { d, expectation in
|
||||
var timesCalled = 0
|
||||
Promise<Int>(error: Error.dummy).catch { _ in
|
||||
XCTAssertEqual(++timesCalled, 1)
|
||||
}
|
||||
after(ticks: 2) {
|
||||
XCTAssertEqual(timesCalled, 1)
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
specify("trying to reject a pending promise more than once, immediately") { d, expectation in
|
||||
d.promise.catch{_ in expectation.fulfill() }
|
||||
d.reject(Error.dummy)
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
specify("trying to reject a pending promise more than once, delayed") { d, expectation in
|
||||
d.promise.catch{_ in expectation.fulfill() }
|
||||
after(ticks: 1) {
|
||||
d.reject(Error.dummy)
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
}
|
||||
specify("trying to reject a pending promise more than once, immediately then delayed") { d, expectation in
|
||||
d.promise.catch{_ in expectation.fulfill() }
|
||||
d.reject(Error.dummy)
|
||||
after(ticks: 1) {
|
||||
d.reject(Error.dummy)
|
||||
}
|
||||
}
|
||||
specify("when multiple `then` calls are made, spaced apart in time") { d, expectation in
|
||||
let mk = { self.expectation(description: "") }
|
||||
let ex = (expectation, mk(), mk(), mk())
|
||||
|
||||
do {
|
||||
d.promise.catch{ _ in ex.0.fulfill() }
|
||||
}
|
||||
after(ticks: 1) {
|
||||
d.promise.catch{ _ in ex.1.fulfill() }
|
||||
}
|
||||
after(ticks: 2) {
|
||||
d.promise.catch{ _ in ex.2.fulfill() }
|
||||
}
|
||||
after(ticks: 3) {
|
||||
d.reject(Error.dummy)
|
||||
ex.3.fulfill()
|
||||
}
|
||||
}
|
||||
specify("when `then` is interleaved with rejection") { d, expectation in
|
||||
let ex = (expectation, self.expectation(description: ""))
|
||||
d.promise.catch{ _ in ex.0.fulfill() }
|
||||
d.reject(Error.dummy)
|
||||
d.promise.catch{ _ in ex.1.fulfill() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
146
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.4.swift
vendored
Normal file
146
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.4.swift
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test224: XCTestCase {
|
||||
func test() {
|
||||
describe("2.2.4: `onFulfilled` or `onRejected` must not be called until the execution context stack contains only platform code.") {
|
||||
|
||||
describe("`then` returns before the promise becomes fulfilled or rejected") {
|
||||
testFulfilled { promise, expectation, dummy in
|
||||
var thenHasReturned = false
|
||||
promise.done { _ in
|
||||
XCTAssert(thenHasReturned)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
thenHasReturned = true
|
||||
}
|
||||
testRejected { promise, expectation, memo in
|
||||
var catchHasReturned = false
|
||||
promise.catch { _->() in
|
||||
XCTAssert(catchHasReturned)
|
||||
expectation.fulfill()
|
||||
}
|
||||
catchHasReturned = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
describe("Clean-stack execution ordering tests (fulfillment case)") {
|
||||
specify("when `onFulfilled` is added immediately before the promise is fulfilled") { d, expectation in
|
||||
var onFulfilledCalled = false
|
||||
d.promise.done {
|
||||
onFulfilledCalled = true
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
d.fulfill()
|
||||
XCTAssertFalse(onFulfilledCalled)
|
||||
}
|
||||
specify("when `onFulfilled` is added immediately after the promise is fulfilled") { d, expectation in
|
||||
var onFulfilledCalled = false
|
||||
d.fulfill()
|
||||
d.promise.done {
|
||||
onFulfilledCalled = true
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
XCTAssertFalse(onFulfilledCalled)
|
||||
}
|
||||
specify("when one `onFulfilled` is added inside another `onFulfilled`") { _, expectation in
|
||||
var firstOnFulfilledFinished = false
|
||||
let promise = Promise()
|
||||
promise.done {
|
||||
promise.done {
|
||||
XCTAssertTrue(firstOnFulfilledFinished)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
firstOnFulfilledFinished = true
|
||||
}.silenceWarning()
|
||||
}
|
||||
|
||||
specify("when `onFulfilled` is added inside an `onRejected`") { _, expectation in
|
||||
let promise1 = Promise<Void>(error: Error.dummy)
|
||||
let promise2 = Promise()
|
||||
var firstOnRejectedFinished = false
|
||||
|
||||
promise1.catch { _ in
|
||||
promise2.done {
|
||||
XCTAssertTrue(firstOnRejectedFinished)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
firstOnRejectedFinished = true
|
||||
}
|
||||
}
|
||||
|
||||
specify("when the promise is fulfilled asynchronously") { d, expectation in
|
||||
var firstStackFinished = false
|
||||
|
||||
after(ticks: 1) {
|
||||
d.fulfill()
|
||||
firstStackFinished = true
|
||||
}
|
||||
|
||||
d.promise.done {
|
||||
XCTAssertTrue(firstStackFinished)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
|
||||
describe("Clean-stack execution ordering tests (rejection case)") {
|
||||
specify("when `onRejected` is added immediately before the promise is rejected") { d, expectation in
|
||||
var onRejectedCalled = false
|
||||
d.promise.catch { _ in
|
||||
onRejectedCalled = true
|
||||
expectation.fulfill()
|
||||
}
|
||||
d.reject(Error.dummy)
|
||||
XCTAssertFalse(onRejectedCalled)
|
||||
}
|
||||
specify("when `onRejected` is added immediately after the promise is rejected") { d, expectation in
|
||||
var onRejectedCalled = false
|
||||
d.reject(Error.dummy)
|
||||
d.promise.catch { _ in
|
||||
onRejectedCalled = true
|
||||
expectation.fulfill()
|
||||
}
|
||||
XCTAssertFalse(onRejectedCalled)
|
||||
}
|
||||
specify("when `onRejected` is added inside an `onFulfilled`") { d, expectation in
|
||||
let promise1 = Promise()
|
||||
let promise2 = Promise<Void>(error: Error.dummy)
|
||||
var firstOnFulfilledFinished = false
|
||||
|
||||
promise1.done { _ in
|
||||
promise2.catch { _ in
|
||||
XCTAssertTrue(firstOnFulfilledFinished)
|
||||
expectation.fulfill()
|
||||
}
|
||||
firstOnFulfilledFinished = true
|
||||
}.silenceWarning()
|
||||
}
|
||||
specify("when one `onRejected` is added inside another `onRejected`") { d, expectation in
|
||||
let promise = Promise<Void>(error: Error.dummy)
|
||||
var firstOnRejectedFinished = false;
|
||||
|
||||
promise.catch { _ in
|
||||
promise.catch { _ in
|
||||
XCTAssertTrue(firstOnRejectedFinished)
|
||||
expectation.fulfill()
|
||||
}
|
||||
firstOnRejectedFinished = true
|
||||
}
|
||||
}
|
||||
specify("when the promise is rejected asynchronously") { d, expectation in
|
||||
var firstStackFinished = false
|
||||
after(ticks: 1) {
|
||||
d.reject(Error.dummy)
|
||||
firstStackFinished = true
|
||||
}
|
||||
d.promise.catch { _ in
|
||||
XCTAssertTrue(firstStackFinished)
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
275
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.6.swift
vendored
Normal file
275
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.6.swift
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test226: XCTestCase {
|
||||
func test() {
|
||||
describe("2.2.6: `then` may be called multiple times on the same promise.") {
|
||||
describe("2.2.6.1: If/when `promise` is fulfilled, all respective `onFulfilled` callbacks must execute in the order of their originating calls to `then`.") {
|
||||
describe("multiple boring fulfillment handlers") {
|
||||
testFulfilled(withExpectationCount: 4) { promise, exes, sentinel -> () in
|
||||
var orderValidator = 0
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 1)
|
||||
exes[0].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.catch { _ in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 2)
|
||||
exes[1].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.catch { _ in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 3)
|
||||
exes[2].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.catch { _ in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 4)
|
||||
exes[3].fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
describe("multiple fulfillment handlers, one of which throws") {
|
||||
testFulfilled(withExpectationCount: 4) { promise, exes, sentinel in
|
||||
var orderValidator = 0
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 1)
|
||||
exes[0].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.catch { _ in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 2)
|
||||
exes[1].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.catch { _ in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 3)
|
||||
exes[2].fulfill()
|
||||
throw Error.dummy
|
||||
}.silenceWarning()
|
||||
promise.catch { value in XCTFail() }
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
XCTAssertEqual(++orderValidator, 4)
|
||||
exes[3].fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
describe("results in multiple branching chains with their own fulfillment values") {
|
||||
testFulfilled(withExpectationCount: 3) { promise, exes, memo in
|
||||
let sentinel1 = 671
|
||||
let sentinel2: UInt32 = 672
|
||||
let sentinel3 = 673
|
||||
|
||||
promise.map { _ in
|
||||
return sentinel1
|
||||
}.done { value in
|
||||
XCTAssertEqual(sentinel1, value)
|
||||
exes[0].fulfill()
|
||||
}.silenceWarning()
|
||||
|
||||
promise.done { _ in
|
||||
throw Error.sentinel(sentinel2)
|
||||
}.catch { err in
|
||||
switch err {
|
||||
case Error.sentinel(let err) where err == sentinel2:
|
||||
break
|
||||
default:
|
||||
XCTFail()
|
||||
}
|
||||
exes[1].fulfill()
|
||||
}
|
||||
|
||||
promise.map { _ in
|
||||
sentinel3
|
||||
}.done {
|
||||
XCTAssertEqual($0, sentinel3)
|
||||
exes[2].fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
describe("`onFulfilled` handlers are called in the original order") {
|
||||
testFulfilled(withExpectationCount: 3) { promise, exes, memo in
|
||||
var orderValidator = 0
|
||||
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(++orderValidator, 1)
|
||||
exes[0].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(++orderValidator, 2)
|
||||
exes[1].fulfill()
|
||||
}.silenceWarning()
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(++orderValidator, 3)
|
||||
exes[2].fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
describe("even when one handler is added inside another handler") {
|
||||
testFulfilled(withExpectationCount: 3) { promise, exes, memo in
|
||||
var x = 0
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(x, 0)
|
||||
x += 1
|
||||
exes[0].fulfill()
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(x, 2)
|
||||
x += 1
|
||||
exes[1].fulfill()
|
||||
}.silenceWarning()
|
||||
}.silenceWarning()
|
||||
promise.done { _ in
|
||||
XCTAssertEqual(x, 1)
|
||||
x += 1
|
||||
exes[2].fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("2.2.6.2: If/when `promise` is rejected, all respective `onRejected` callbacks must execute in the order of their originating calls to `then`.") {
|
||||
describe("multiple boring rejection handlers") {
|
||||
testRejected(withExpectationCount: 4) { promise, exes, sentinel in
|
||||
var ticket = 0
|
||||
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++ticket, 1)
|
||||
exes[0].fulfill()
|
||||
}
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++ticket, 2)
|
||||
exes[1].fulfill()
|
||||
}
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++ticket, 3)
|
||||
exes[2].fulfill()
|
||||
}
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++ticket, 4)
|
||||
exes[3].fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("multiple rejection handlers, one of which throws") {
|
||||
testRejected(withExpectationCount: 4) { promise, exes, sentinel in
|
||||
var orderValidator = 0
|
||||
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++orderValidator, 1)
|
||||
exes[0].fulfill()
|
||||
}
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++orderValidator, 2)
|
||||
exes[1].fulfill()
|
||||
}
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.recover { err -> Promise<UInt32> in
|
||||
if case Error.sentinel(let x) = err {
|
||||
XCTAssertEqual(x, sentinel)
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
XCTAssertEqual(++orderValidator, 3)
|
||||
exes[2].fulfill()
|
||||
throw Error.dummy
|
||||
}.silenceWarning()
|
||||
promise.done { _ in XCTFail() }.silenceWarning()
|
||||
promise.catch { err in
|
||||
guard case Error.sentinel(let x) = err, x == sentinel else { return XCTFail() }
|
||||
XCTAssertEqual(++orderValidator, 4)
|
||||
exes[3].fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("results in multiple branching chains with their own fulfillment values") {
|
||||
testRejected(withExpectationCount: 3) { promise, exes, memo in
|
||||
let sentinel1 = arc4random()
|
||||
let sentinel2 = arc4random()
|
||||
let sentinel3 = arc4random()
|
||||
|
||||
promise.recover { _ in
|
||||
return .value(sentinel1)
|
||||
}.done { value in
|
||||
XCTAssertEqual(sentinel1, value)
|
||||
exes[0].fulfill()
|
||||
}
|
||||
|
||||
promise.recover { _ -> Promise<UInt32> in
|
||||
throw Error.sentinel(sentinel2)
|
||||
}.catch { err in
|
||||
if case Error.sentinel(let x) = err, x == sentinel2 {
|
||||
exes[1].fulfill()
|
||||
}
|
||||
}
|
||||
|
||||
promise.recover { _ in
|
||||
.value(sentinel3)
|
||||
}.done { value in
|
||||
XCTAssertEqual(value, sentinel3)
|
||||
exes[2].fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("`onRejected` handlers are called in the original order") {
|
||||
testRejected(withExpectationCount: 3) { promise, exes, memo in
|
||||
var x = 0
|
||||
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 0)
|
||||
x += 1
|
||||
exes[0].fulfill()
|
||||
}
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 1)
|
||||
x += 1
|
||||
exes[1].fulfill()
|
||||
}
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 2)
|
||||
x += 1
|
||||
exes[2].fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("even when one handler is added inside another handler") {
|
||||
testRejected(withExpectationCount: 3) { promise, exes, memo in
|
||||
var x = 0
|
||||
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 0)
|
||||
x += 1
|
||||
exes[0].fulfill()
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 2)
|
||||
x += 1
|
||||
exes[1].fulfill()
|
||||
}
|
||||
}
|
||||
promise.catch { _ in
|
||||
XCTAssertEqual(x, 1)
|
||||
x += 1
|
||||
exes[2].fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.7.swift
vendored
Normal file
33
Carthage/Checkouts/PromiseKit/Tests/A+/2.2.7.swift
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test227: XCTestCase {
|
||||
func test() {
|
||||
describe("2.2.7: `then` must return a promise: `promise2 = promise1.then(onFulfilled, onRejected)") {
|
||||
describe("2.2.7.2: If either `onFulfilled` or `onRejected` throws an exception `e`, `promise2` must be rejected with `e` as the reason.") {
|
||||
|
||||
testFulfilled { promise1, expectation, _ in
|
||||
let sentinel = arc4random()
|
||||
let promise2 = promise1.done { _ in throw Error.sentinel(sentinel) }
|
||||
|
||||
promise2.catch {
|
||||
if case Error.sentinel(let x) = $0, x == sentinel {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testRejected { promise1, expectation, _ in
|
||||
let sentinel = arc4random()
|
||||
let promise2 = promise1.recover { _ -> Promise<UInt32> in throw Error.sentinel(sentinel) }
|
||||
|
||||
promise2.catch { error in
|
||||
if case Error.sentinel(let x) = error, x == sentinel {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.1.swift
vendored
Normal file
31
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.1.swift
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test231: XCTestCase {
|
||||
func test() {
|
||||
describe("2.3.1: If `promise` and `x` refer to the same object, reject `promise` with a `TypeError' as the reason.") {
|
||||
specify("via return from a fulfilled promise") { d, expectation in
|
||||
var promise: Promise<Void>!
|
||||
promise = Promise().then { () -> Promise<Void> in
|
||||
return promise
|
||||
}
|
||||
promise.catch { err in
|
||||
if case PMKError.returnedSelf = err {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
specify("via return from a rejected promise") { d, expectation in
|
||||
var promise: Promise<Void>!
|
||||
promise = Promise<Void>(error: Error.dummy).recover { _ -> Promise<Void> in
|
||||
return promise
|
||||
}
|
||||
promise.catch { err in
|
||||
if case PMKError.returnedSelf = err {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.2.swift
vendored
Normal file
116
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.2.swift
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
class Test232: XCTestCase {
|
||||
func test() {
|
||||
describe("2.3.2: If `x` is a promise, adopt its state") {
|
||||
describe("2.3.2.1: If `x` is pending, `promise` must remain pending until `x` is fulfilled or rejected.") {
|
||||
|
||||
func xFactory() -> Promise<UInt32> {
|
||||
return Promise.pending().promise
|
||||
}
|
||||
|
||||
testPromiseResolution(factory: xFactory) { promise, expectation in
|
||||
var wasFulfilled = false;
|
||||
var wasRejected = false;
|
||||
|
||||
promise.test(onFulfilled: { wasFulfilled = true }, onRejected: { wasRejected = true })
|
||||
|
||||
after(ticks: 4) {
|
||||
XCTAssertFalse(wasFulfilled)
|
||||
XCTAssertFalse(wasRejected)
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("2.3.2.2: If/when `x` is fulfilled, fulfill `promise` with the same value.") {
|
||||
describe("`x` is already-fulfilled") {
|
||||
let sentinel = arc4random()
|
||||
|
||||
func xFactory() -> Promise<UInt32> {
|
||||
return .value(sentinel)
|
||||
}
|
||||
|
||||
testPromiseResolution(factory: xFactory) { promise, expectation in
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
describe("`x` is eventually-fulfilled") {
|
||||
let sentinel = arc4random()
|
||||
|
||||
func xFactory() -> Promise<UInt32> {
|
||||
return Promise { seal in
|
||||
after(ticks: 2) {
|
||||
seal.fulfill(sentinel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testPromiseResolution(factory: xFactory) { promise, expectation in
|
||||
promise.done {
|
||||
XCTAssertEqual($0, sentinel)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("2.3.2.3: If/when `x` is rejected, reject `promise` with the same reason.") {
|
||||
describe("`x` is already-rejected") {
|
||||
let sentinel = arc4random()
|
||||
|
||||
func xFactory() -> Promise<UInt32> {
|
||||
return Promise(error: Error.sentinel(sentinel))
|
||||
}
|
||||
|
||||
testPromiseResolution(factory: xFactory) { promise, expectation in
|
||||
promise.catch { err in
|
||||
if case Error.sentinel(let value) = err, value == sentinel {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
describe("`x` is eventually-rejected") {
|
||||
let sentinel = arc4random()
|
||||
|
||||
func xFactory() -> Promise<UInt32> {
|
||||
return Promise { seal in
|
||||
after(ticks: 2) {
|
||||
seal.reject(Error.sentinel(sentinel))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testPromiseResolution(factory: xFactory) { promise, expectation in
|
||||
promise.catch { err in
|
||||
if case Error.sentinel(let value) = err, value == sentinel {
|
||||
expectation.fulfill()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extension Test232 {
|
||||
fileprivate func testPromiseResolution(factory: @escaping () -> Promise<UInt32>, line: UInt = #line, test: (Promise<UInt32>, XCTestExpectation) -> Void) {
|
||||
specify("via return from a fulfilled promise", file: #file, line: line) { d, expectation in
|
||||
let promise = Promise.value(arc4random()).then { _ in factory() }
|
||||
test(promise, expectation)
|
||||
}
|
||||
specify("via return from a rejected promise", file: #file, line: line) { d, expectation in
|
||||
let promise: Promise<UInt32> = Promise(error: Error.dummy).recover { _ in factory() }
|
||||
test(promise, expectation)
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.4.swift
vendored
Normal file
26
Carthage/Checkouts/PromiseKit/Tests/A+/2.3.4.swift
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
import PromiseKit
|
||||
import XCTest
|
||||
|
||||
|
||||
class Test234: XCTestCase {
|
||||
func test() {
|
||||
describe("2.3.4: If `x` is not an object or function, fulfill `promise` with `x`") {
|
||||
testFulfilled { promise, exception, _ in
|
||||
promise.map { value -> UInt32 in
|
||||
return 1
|
||||
}.done { value in
|
||||
XCTAssertEqual(value, 1)
|
||||
exception.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
testRejected { promise, expectation, _ in
|
||||
promise.recover { _ -> Promise<UInt32> in
|
||||
return .value(UInt32(1))
|
||||
}.done { value in
|
||||
XCTAssertEqual(value, 1)
|
||||
expectation.fulfill()
|
||||
}.silenceWarning()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
Carthage/Checkouts/PromiseKit/Tests/A+/README.md
vendored
Normal file
13
Carthage/Checkouts/PromiseKit/Tests/A+/README.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
Resources
|
||||
=========
|
||||
* https://github.com/promises-aplus/promises-tests
|
||||
|
||||
|
||||
Skipped
|
||||
=======
|
||||
* 2.3.3: Otherwise, if x is an object or function.
|
||||
This spec is a NOOP for Swift:
|
||||
- We have decided not to interact with other Promises A+ implementations
|
||||
- functions cannot have properties
|
||||
* 2.3.3.4: If then is not a function, fulfill promise with x.
|
||||
- See: The 2.3.4 suite.
|
||||
Reference in New Issue
Block a user