// // Copyright Amazon.com Inc. or its affiliates. // All Rights Reserved. // // SPDX-License-Identifier: Apache-2.0 // import Foundation import XCTest @testable import Amplify @testable import AmplifyTestCommon class RetryableGraphQLOperationTests: XCTestCase { let testApiName = "apiName" /// Given: a RetryableGraphQLOperation with a maxRetries of 2 /// When: the request fails the first attempt with a .signedOut error /// Then: the request is re-tried and resultListener called func testShouldRetryOperation() { let maxRetries = 2 var attempt = 0 let requestFactoryExpectation = expectation(description: "Retry factory called \(maxRetries) times") requestFactoryExpectation.expectedFulfillmentCount = maxRetries let resultExpectation = expectation(description: "Result called") let resultListener: ResultListener = { _ in resultExpectation.fulfill() } let requestFactory: RequestFactory = { requestFactoryExpectation.fulfill() return self.makeTestRequest() } let operation = RetryableGraphQLOperation(requestFactory: requestFactory, maxRetries: maxRetries, resultListener: resultListener) { _, wrappedListener in // simulate an error at first attempt if attempt == 0 { wrappedListener( .failure(self.makeSignedOutAuthError()) ) } else { wrappedListener(.success(.success(""))) } attempt += 1 return self.makeTestOperation() } operation.main() wait(for: [requestFactoryExpectation, resultExpectation], timeout: 10) } /// Given: a RetryableGraphQLOperation with a maxRetries of 1 /// When: the request fails the first attempt with a .signedOut error /// Then: the request is not re-tried func testShouldNotRetryOperationWithMaxRetriesOne() { let maxRetries = 1 let requestFactoryExpectation = expectation(description: "Retry factory called \(maxRetries) times") requestFactoryExpectation.expectedFulfillmentCount = maxRetries let resultExpectation = expectation(description: "Result called") let resultListener: ResultListener = { _ in resultExpectation.fulfill() } let requestFactory: RequestFactory = { requestFactoryExpectation.fulfill() return self.makeTestRequest() } let operation = RetryableGraphQLOperation(requestFactory: requestFactory, maxRetries: maxRetries, resultListener: resultListener) { _, wrappedListener in wrappedListener( .failure(self.makeSignedOutAuthError()) ) return self.makeTestOperation() } operation.main() wait(for: [requestFactoryExpectation, resultExpectation], timeout: 10) } /// Given: a RetryableGraphQLOperation with a maxRetries of 2 /// When: the request fails both attempts /// Then: the request is re-tried only twice and resultListener called func testNotShouldRetryOperation() { let maxRetries = 2 let requestFactoryExpectation = expectation(description: "Retry factory called \(maxRetries) times") requestFactoryExpectation.expectedFulfillmentCount = maxRetries let resultExpectation = expectation(description: "Result called") let resultListener: ResultListener = { _ in resultExpectation.fulfill() } let requestFactory: RequestFactory = { requestFactoryExpectation.fulfill() return self.makeTestRequest() } let operation = RetryableGraphQLOperation(requestFactory: requestFactory, maxRetries: maxRetries, resultListener: resultListener) { _, wrappedListener in // simulate an error for both attempts wrappedListener( .failure(self.makeSignedOutAuthError()) ) return self.makeTestOperation() } operation.main() wait(for: [requestFactoryExpectation, resultExpectation], timeout: 10) } } // MARK: - Test helpers extension RetryableGraphQLOperationTests { private func makeTestRequest() -> GraphQLRequest { GraphQLRequest(apiName: testApiName, document: "", responseType: Payload.self) } private func makeTestOperation() -> GraphQLOperation { let requestOptions = GraphQLOperationRequest.Options(pluginOptions: nil) let operationRequest = GraphQLOperationRequest(apiName: testApiName, operationType: .subscription, document: "", responseType: Payload.self, options: requestOptions) return GraphQLOperation(categoryType: .dataStore, eventName: "eventName", request: operationRequest) } func makeSignedOutAuthError() -> APIError { return APIError.operationError("Error", "", AuthError.signedOut("AuthError", "")) } /// Convenience type alias private typealias Payload = String private typealias ResultListener = RetryableGraphQLOperation.OperationResultListener private typealias RequestFactory = RetryableGraphQLOperation.RequestFactory }