amplify-swift/AmplifyTests/CategoryTests/API/RetryableGraphQLOperationTe...

157 lines
5.9 KiB
Swift

//
// 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<Payload>(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<Payload>(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<Payload>(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<Payload> {
GraphQLRequest<Payload>(apiName: testApiName,
document: "",
responseType: Payload.self)
}
private func makeTestOperation() -> GraphQLOperation<Payload> {
let requestOptions = GraphQLOperationRequest<Payload>.Options(pluginOptions: nil)
let operationRequest = GraphQLOperationRequest<Payload>(apiName: testApiName,
operationType: .subscription,
document: "",
responseType: Payload.self,
options: requestOptions)
return GraphQLOperation<Payload>(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<Payload>.OperationResultListener
private typealias RequestFactory = RetryableGraphQLOperation<Payload>.RequestFactory
}