diff --git a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift b/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift index d25fedeb..78bd36b6 100644 --- a/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift +++ b/Tests/PubNubTests/EventEngine/Presence/DelayedHeartbeatEffectTests.swift @@ -28,9 +28,10 @@ class DelayedHeartbeatEffectTests: XCTestCase { } override func tearDown() { - mockUrlSession = nil delegate = nil + mockUrlSession = nil httpSession = nil + factory = nil super.tearDown() } @@ -43,7 +44,7 @@ class DelayedHeartbeatEffectTests: XCTestCase { let delayRange = 2.0...3.0 let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: delayRange.lowerBound), excluded: []) - let effect = configureEffect(attempt: 0, automaticRetry: automaticRetry, error: PubNubError(.unknown)) + let effect = configureEffectToTest(retryAttempt: 0, automaticRetry: automaticRetry, dueTo: PubNubError(.unknown)) let startDate = Date() effect.performTask { returnedEvents in @@ -65,7 +66,7 @@ class DelayedHeartbeatEffectTests: XCTestCase { let delayRange = 2.0...3.0 let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: delayRange.lowerBound), excluded: []) let error = PubNubError(.unknown) - let effect = configureEffect(attempt: 0, automaticRetry: automaticRetry, error: error) + let effect = configureEffectToTest(retryAttempt: 0, automaticRetry: automaticRetry, dueTo: error) effect.performTask { returnedEvents in let expectedError = PubNubError(.internalServiceError) @@ -84,7 +85,7 @@ class DelayedHeartbeatEffectTests: XCTestCase { let automaticRetry = AutomaticRetry(retryLimit: 3, policy: .linear(delay: 2.0), excluded: []) let error = PubNubError(.unknown) - let effect = configureEffect(attempt: 3, automaticRetry: automaticRetry, error: error) + let effect = configureEffectToTest(retryAttempt: 3, automaticRetry: automaticRetry, dueTo: error) mockResponse(GenericServicePayloadResponse(status: 200)) @@ -108,9 +109,10 @@ fileprivate extension DelayedHeartbeatEffectTests { } } - func configureEffect( - attempt: Int, automaticRetry: AutomaticRetry?, - error: PubNubError + func configureEffectToTest( + retryAttempt attempt: Int, + automaticRetry: AutomaticRetry?, + dueTo error: PubNubError ) -> any EffectHandler { factory.effect( for: .delayedHeartbeat( diff --git a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift index b66624a2..6a847a51 100644 --- a/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift +++ b/Tests/PubNubTests/EventEngine/Subscribe/SubscribeEffectsTests.swift @@ -23,10 +23,7 @@ class SubscribeEffectsTests: XCTestCase { publishKey: "pubKey", subscribeKey: "subKey", userId: "userId", - automaticRetry: AutomaticRetry( - retryLimit: 3, - policy: .linear(delay: 2.0) - ) + automaticRetry: AutomaticRetry(retryLimit: 3, policy: .linear(delay: 2.0)) ) private func configWithLinearPolicy(_ delay: Double = 2.0) -> PubNubConfiguration { @@ -47,9 +44,10 @@ class SubscribeEffectsTests: XCTestCase { } override func tearDown() { - mockUrlSession = nil delegate = nil + mockUrlSession = nil httpSession = nil + factory = nil super.tearDown() } } @@ -62,21 +60,28 @@ extension SubscribeEffectsTests { cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [] )) - runEffect( - configuration: config, - invocation: .handshakeRequest( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"] - ), - expectedOutput: [ - .handshakeSuccess( - cursor: SubscribeCursor( - timetoken: 12345, - region: 1 - ) - ) - ] + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeRequest( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"] + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies(configuration: config)) + ) + let expectedOutput: Subscribe.Event = .handshakeSuccess( + cursor: SubscribeCursor(timetoken: 12345, region: 1) ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } func test_HandshakingEffectWithFailedResponse() { @@ -84,17 +89,28 @@ extension SubscribeEffectsTests { errorIfAny: URLError(.cannotFindHost), httpResponse: HTTPURLResponse(statusCode: 404)! ) - runEffect( - configuration: config, - invocation: .handshakeRequest( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"] - ), expectedOutput: [ - .handshakeFailure( - error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) - ) - ] + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeRequest( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"] + ) + let expectedOutput: Subscribe.Event = .handshakeFailure( + error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies(configuration: config)) ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } } @@ -106,19 +122,30 @@ extension SubscribeEffectsTests { cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [firstMessage, secondMessage] )) - runEffect( - configuration: config, - invocation: .receiveMessages( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 111, region: 1) - ), expectedOutput: [ - .receiveSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - ) - ] + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .receiveMessages( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 111, region: 1) + ) + let expectedOutput: Subscribe.Event = .receiveSuccess( + cursor: SubscribeCursor(timetoken: 12345, region: 1), + messages: [firstMessage, secondMessage] ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies(configuration: config)) + ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } func test_ReceivingEffectWithFailedResponse() { @@ -126,17 +153,29 @@ extension SubscribeEffectsTests { errorIfAny: URLError(.cannotFindHost), httpResponse: HTTPURLResponse(statusCode: 404)! ) - runEffect( - configuration: config, - invocation: .receiveMessages( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 111, region: 1) - ), expectedOutput: [ - .receiveFailure( - error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) - ) - ]) + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .receiveMessages( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 111, region: 1) + ) + let expectedOutput: Subscribe.Event = .receiveFailure( + error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies(configuration: config)) + ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } } @@ -144,115 +183,141 @@ extension SubscribeEffectsTests { extension SubscribeEffectsTests { func test_HandshakeReconnectingSuccess() { - let delayRange = 2.0...3.0 - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) - mockResponse(subscribeResponse: SubscribeResponse( cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [] )) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2 * delayRange.upperBound, - expectedOutput: [ - .handshakeReconnectSuccess(cursor: SubscribeCursor( - timetoken: 12345, - region: 1 - )) - ] + + let delayRange = 2.0...3.0 + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + retryAttempt: 1, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) ) + let expectedOutput: Subscribe.Event = .handshakeReconnectSuccess( + cursor: SubscribeCursor(timetoken: 12345, region: 1) + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies( + configuration: configWithLinearPolicy(delayRange.lowerBound) + )) + ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } func test_HandshakeReconnectingFailed() { - let delayRange = 2.0...3.0 - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) - mockResponse( errorIfAny: URLError(.cannotFindHost), httpResponse: HTTPURLResponse(statusCode: 404)! ) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2 * delayRange.upperBound, - expectedOutput: [ - .handshakeReconnectFailure( - error: PubNubError( - .nameResolutionFailure, - underlying: URLError(.cannotFindHost) - ) - ) - ] + + let delayRange = 2.0...3.0 + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + retryAttempt: 1, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) + ) + let expectedOutput: Subscribe.Event = .handshakeReconnectFailure( + error: PubNubError(.nameResolutionFailure, underlying: URLError(.cannotFindHost)) + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies( + configuration: configWithLinearPolicy(delayRange.lowerBound) + )) ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } func test_HandshakeReconnectGiveUp() { let delayRange = 2.0...3.0 - let urlError = URLError(.badServerResponse) - - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 3, - reason: PubNubError(urlError.pubnubReason!, underlying: urlError) - ), - expectedOutput: [ - .handshakeReconnectGiveUp( - error: PubNubError(.badServerResponse) - ) - ] + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + retryAttempt: 3, + reason: PubNubError(URLError(.badServerResponse).pubnubReason!, underlying: URLError(.badServerResponse)) + ) + let expectedOutput: Subscribe.Event = .handshakeReconnectGiveUp( + error: PubNubError(.badServerResponse) + ) + let effect = factory.effect( + for: testedInvocation, + with: EventEngineDependencies(value: Subscribe.Dependencies( + configuration: configWithLinearPolicy(delayRange.lowerBound) + )) ) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } func test_HandshakeReconnectIsDelayed() { - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) - - let delayRange = 2.0...3.0 - let startDate = Date() - mockResponse(subscribeResponse: SubscribeResponse( cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [] )) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .handshakeReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2.5 * delayRange.upperBound, - expectedOutput: [ - .handshakeReconnectSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1) - ) - ], - additionalValidations: { - XCTAssertTrue( - Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound) - ) - } + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .handshakeReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + retryAttempt: 3, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) ) + + let delayRange = 2.0...3.0 + let startDate = Date() + let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) + let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) + + effect.performTask { _ in + XCTAssertTrue(Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound)) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } } @@ -260,121 +325,142 @@ extension SubscribeEffectsTests { extension SubscribeEffectsTests { func test_ReceiveReconnectingSuccess() { - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) - let delayRange = 2.0...3.0 - mockResponse(subscribeResponse: SubscribeResponse( cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [firstMessage, secondMessage] )) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2 * delayRange.upperBound, - expectedOutput: [ - .receiveReconnectSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - ) - ] + + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true + + let testedInvocation: Subscribe.Invocation = .receiveReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 1111, region: 1), + retryAttempt: 1, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) + ) + let expectedOutput: Subscribe.Event = .receiveReconnectSuccess( + cursor: SubscribeCursor(timetoken: 12345, region: 1), + messages: [firstMessage, secondMessage] ) + + let delayRange = 2.0...3.0 + let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) + let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } func test_ReceiveReconnectingFailure() { - let delayRange = 2.0...3.0 - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true mockResponse( errorIfAny: URLError(.cannotFindHost), httpResponse: HTTPURLResponse(statusCode: 404)! ) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2 * delayRange.upperBound, - expectedOutput: [ - .receiveReconnectFailure( - error: PubNubError(.nameResolutionFailure) - ) - ] + let testedInvocation: Subscribe.Invocation = .receiveReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 1111, region: 1), + retryAttempt: 1, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) ) + + let expectedOutput: Subscribe.Event = .receiveReconnectFailure(error: PubNubError(.nameResolutionFailure)) + let delayRange = 2.0...3.0 + let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) + let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } func test_ReceiveReconnectGiveUp() { - let urlError = URLError(.badServerResponse) - let delayRange = 2.0...3.0 + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true mockResponse( errorIfAny: URLError(.cannotFindHost), httpResponse: HTTPURLResponse(statusCode: 404)! ) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 3, - reason: PubNubError(urlError.pubnubReason!, underlying: urlError) - ), - expectedOutput: [ - .receiveReconnectGiveUp( - error: PubNubError(.badServerResponse) - ) - ] + + let testedInvocation: Subscribe.Invocation = .receiveReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 1111, region: 1), + retryAttempt: 3, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse) + ) ) + let expectedOutput: Subscribe.Event = .receiveReconnectGiveUp( + error: PubNubError(.badServerResponse) + ) + + let delayRange = 2.0...3.0 + let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) + let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) + + effect.performTask { + XCTAssertEqual([expectedOutput], $0) + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) } func test_ReceiveReconnectingIsDelayed() { - let urlError = URLError(.badServerResponse) - let httpUrlResponse = HTTPURLResponse(statusCode: 500)! - let pubNubError = PubNubError(urlError.pubnubReason!, underlying: urlError, affected: [.response(httpUrlResponse)]) - - let delayRange = 2.0...3.0 - let startDate = Date() + let expectation = XCTestExpectation(description: "Effect Completion") + expectation.expectedFulfillmentCount = 1 + expectation.assertForOverFulfill = true mockResponse(subscribeResponse: SubscribeResponse( cursor: SubscribeCursor(timetoken: 12345, region: 1), messages: [firstMessage, secondMessage] )) - runEffect( - configuration: configWithLinearPolicy(delayRange.lowerBound), - invocation: .receiveReconnect( - channels: ["channel1", "channel1-pnpres", "channel2"], - groups: ["g1", "g2", "g2-pnpres"], - cursor: SubscribeCursor(timetoken: 1111, region: 1), - retryAttempt: 1, - reason: pubNubError - ), - timeout: 2 * delayRange.upperBound, - expectedOutput: [ - .receiveReconnectSuccess( - cursor: SubscribeCursor(timetoken: 12345, region: 1), - messages: [firstMessage, secondMessage] - ) - ], - additionalValidations: { - XCTAssertTrue( - Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound) - ) - } + + let testedInvocation: Subscribe.Invocation = .receiveReconnect( + channels: ["channel1", "channel1-pnpres", "channel2"], + groups: ["g1", "g2", "g2-pnpres"], + cursor: SubscribeCursor(timetoken: 1111, region: 1), + retryAttempt: 1, + reason: PubNubError( + URLError(.badServerResponse).pubnubReason!, + underlying: URLError(.badServerResponse), + affected: [.response(HTTPURLResponse(statusCode: 500)!)] + ) ) + + let delayRange = 2.0...3.0 + let startDate = Date() + let depValue = Subscribe.Dependencies(configuration: configWithLinearPolicy(delayRange.lowerBound)) + let effect = factory.effect(for: testedInvocation, with: EventEngineDependencies(value: depValue)) + + effect.performTask { _ in + XCTAssertTrue(Int(Date().timeIntervalSince(startDate)) <= Int(delayRange.upperBound)) + expectation.fulfill() + } + wait(for: [expectation], timeout: 2 * delayRange.upperBound) } } @@ -393,29 +479,6 @@ fileprivate extension SubscribeEffectsTests { return task } } - - private func runEffect( - configuration: PubNubConfiguration, - invocation: Subscribe.Invocation, - timeout: TimeInterval = 0.5, - expectedOutput results: [Subscribe.Event] = [], - additionalValidations validations: @escaping () -> Void = {} - ) { - let expectation = XCTestExpectation(description: "Effect Completion") - expectation.expectedFulfillmentCount = 1 - expectation.assertForOverFulfill = true - - let effect = factory.effect( - for: invocation, - with: EventEngineDependencies(value: Subscribe.Dependencies(configuration: configuration)) - ) - effect.performTask { - XCTAssertEqual(results, $0) - validations() - expectation.fulfill() - } - wait(for: [expectation], timeout: timeout) - } } fileprivate let firstMessage = SubscribeMessagePayload(