From 63b4c1b1da9f4f668ecfbb12eb40fb705d3e4710 Mon Sep 17 00:00:00 2001 From: Tuan Pham <103537251+phantumcode@users.noreply.github.com> Date: Thu, 23 May 2024 12:33:48 -0500 Subject: [PATCH 1/2] chore: migrate unit test to use `await fulfillment` (#3703) --- ...ICategoryPlugin+GraphQLBehaviorTests.swift | 12 +- ...tegoryPlugin+RESTClientBehaviorTests.swift | 8 +- .../Operation/AWSRESTOperationTests.swift | 9 +- .../Operation/GraphQLMutateCombineTests.swift | 13 +- .../Operation/GraphQLQueryCombineTests.swift | 27 +++- .../Operation/GraphQLSubscribeTests.swift | 54 +++++++- .../Operation/RESTCombineTests.swift | 8 +- .../NetworkReachabilityNotifierTests.swift | 12 +- ...ntAnalyticsPluginClientBehaviorTests.swift | 48 +++---- .../AWSAuthHostedUISignInTests.swift | 4 +- .../Core/AWSDataStorePluginTests.swift | 82 ++++++----- .../Core/StateMachineTests.swift | 38 +++--- ...tialSyncOperationSyncExpressionTests.swift | 12 +- .../InitialSyncOperationTests.swift | 63 +++++---- .../InitialSyncOrchestratorTests.swift | 12 +- .../ModelSyncedEventEmitterTests.swift | 12 +- .../InitialSync/SyncEventEmitterTests.swift | 12 +- .../AWSMutationDatabaseAdapterTests.swift | 16 +-- ...tationQueueTestsWithMockStateMachine.swift | 12 +- .../ReconcileAndLocalSaveOperationTests.swift | 128 +++++++++--------- .../RemoteSyncReconcilerTests.swift | 4 +- .../ActivityTrackerTests.swift | 16 ++- ...ushNotificationsPluginConfigureTests.swift | 28 ++-- .../Dependency/AWSS3AdapterTests.swift | 62 ++++----- ...SS3StorageDownloadFileOperationTests.swift | 37 ++--- .../AWSS3StorageGetDataOperationTests.swift | 20 +-- .../AWSS3StoragePutDataOperationTests.swift | 40 +++--- .../AWSS3StorageRemoveOperationTests.swift | 4 +- ...AWSS3StorageUploadFileOperationTests.swift | 44 +++--- .../Storage/AWSS3StorageServiceTests.swift | 26 ++-- ...ultStorageMultipartUploadClientTests.swift | 36 ++--- .../DefaultStorageTransferDatabaseTests.swift | 8 +- .../StorageServiceSessionDelegateTests.swift | 22 +-- .../Internal/StorageTransferTaskTests.swift | 32 ++--- .../APICategoryClientInterceptorTests.swift | 4 +- .../API/APICategoryConfigurationTests.swift | 8 +- .../AnalyticsCategoryClientAPITests.swift | 40 +++--- .../AnalyticsCategoryConfigurationTests.swift | 16 +-- .../Auth/AuthCategoryConfigurationTests.swift | 8 +- .../DataStoreCategoryConfigurationTests.swift | 8 +- .../ModelFieldAssociationTests.swift | 2 +- .../Geo/GeoCategoryConfigurationTests.swift | 8 +- .../DefaultHubPluginTests.swift | 4 +- .../Hub/HubCategoryConfigurationTests.swift | 12 +- .../CategoryTests/Hub/HubClientAPITests.swift | 16 +-- .../CategoryTests/Hub/HubCombineTests.swift | 16 ++- .../Logging/DefaultLoggingPluginTests.swift | 28 ++-- .../LoggingCategoryClientAPITests.swift | 28 ++-- .../LoggingCategoryConfigurationTests.swift | 12 +- ...ificationsCategoryConfigurationTests.swift | 8 +- ...redictionsCategoryConfigurationTests.swift | 8 +- .../StorageCategoryConfigurationTests.swift | 4 +- ...rocessReportingOperationChainedTests.swift | 21 ++- ...rocessReportingOperationCombineTests.swift | 32 ++++- .../AmplifyOperationCombineTests.swift | 24 ++-- AmplifyTests/CoreTests/AtomicValueTests.swift | 4 +- 56 files changed, 687 insertions(+), 585 deletions(-) diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+GraphQLBehaviorTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+GraphQLBehaviorTests.swift index 16b4ff573c..74065cd3e5 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+GraphQLBehaviorTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+GraphQLBehaviorTests.swift @@ -14,7 +14,7 @@ class AWSAPICategoryPluginGraphQLBehaviorTests: AWSAPICategoryPluginTestBase { // MARK: Query API Tests - func testQuery() { + func testQuery() async { let operationFinished = expectation(description: "Operation should finish") let request = GraphQLRequest(apiName: apiName, document: testDocument, @@ -39,12 +39,12 @@ class AWSAPICategoryPluginGraphQLBehaviorTests: AWSAPICategoryPluginTestBase { XCTAssertEqual(operationRequest.operationType, GraphQLOperationType.query) XCTAssertNotNil(operationRequest.options) XCTAssertNil(operationRequest.variables) - waitForExpectations(timeout: 1) + await fulfillment(of: [operationFinished], timeout: 1) } // MARK: Mutate API Tests - func testMutate() { + func testMutate() async { let operationFinished = expectation(description: "Operation should finish") let request = GraphQLRequest(apiName: apiName, document: testDocument, @@ -68,12 +68,12 @@ class AWSAPICategoryPluginGraphQLBehaviorTests: AWSAPICategoryPluginTestBase { XCTAssertEqual(operationRequest.operationType, GraphQLOperationType.mutation) XCTAssertNotNil(operationRequest.options) XCTAssertNil(operationRequest.variables) - waitForExpectations(timeout: 1) + await fulfillment(of: [operationFinished], timeout: 1) } // MARK: Subscribe API Tests - func testSubscribe() { + func testSubscribe() async { let operationFinished = expectation(description: "Operation should finish") let request = GraphQLRequest(apiName: apiName, document: testDocument, @@ -97,6 +97,6 @@ class AWSAPICategoryPluginGraphQLBehaviorTests: AWSAPICategoryPluginTestBase { XCTAssertEqual(operationRequest.operationType, GraphQLOperationType.subscription) XCTAssertNotNil(operationRequest.options) XCTAssertNil(operationRequest.variables) - waitForExpectations(timeout: 1) + await fulfillment(of: [operationFinished], timeout: 1) } } diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+RESTClientBehaviorTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+RESTClientBehaviorTests.swift index b567419b03..84647ff9dd 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+RESTClientBehaviorTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AWSAPICategoryPlugin+RESTClientBehaviorTests.swift @@ -16,7 +16,7 @@ class AWSAPICategoryPluginRESTClientBehaviorTests: AWSAPICategoryPluginTestBase // MARK: Get API tests - func testGet() { + func testGet() async { let operationFinished = expectation(description: "Operation should finish") let request = RESTRequest(apiName: apiName, path: testPath) let operation = apiPlugin.get(request: request) { _ in @@ -38,12 +38,12 @@ class AWSAPICategoryPluginRESTClientBehaviorTests: AWSAPICategoryPluginTestBase XCTAssertEqual(operationRequest.operationType, RESTOperationType.get) XCTAssertNotNil(operationRequest.options) XCTAssertNotNil(operationRequest.path) - waitForExpectations(timeout: 1) + await fulfillment(of: [operationFinished], timeout: 1) } // MARK: Post API tests - func testPost() { + func testPost() async { let operationFinished = expectation(description: "Operation should finish") let request = RESTRequest(apiName: apiName, path: testPath, body: testBody) let operation = apiPlugin.post(request: request) { _ in @@ -65,7 +65,7 @@ class AWSAPICategoryPluginRESTClientBehaviorTests: AWSAPICategoryPluginTestBase XCTAssertEqual(operationRequest.operationType, RESTOperationType.post) XCTAssertNotNil(operationRequest.options) XCTAssertNotNil(operationRequest.path) - waitForExpectations(timeout: 1) + await fulfillment(of: [operationFinished], timeout: 1) } // MARK: Put API tests diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/AWSRESTOperationTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/AWSRESTOperationTests.swift index c65f1257ac..6f76a6aa72 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/AWSRESTOperationTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/AWSRESTOperationTests.swift @@ -33,7 +33,7 @@ class AWSRESTOperationTests: OperationTestBase { } // TODO: Fix this test - func testGetReturnsOperation() throws { + func testGetReturnsOperation() async throws { try setUpPlugin(endpointType: .rest) // Use this as a semaphore to ensure the task is cleaned up before proceeding to the next test @@ -49,11 +49,10 @@ class AWSRESTOperationTests: OperationTestBase { } XCTAssertNotNil(operation.request) - - waitForExpectations(timeout: 1.00) + await fulfillment(of: [listenerWasInvoked], timeout: 1) } - func testGetFailsWithBadAPIName() throws { + func testGetFailsWithBadAPIName() async throws { let sentData = Data([0x00, 0x01, 0x02, 0x03]) try setUpPluginForSingleResponse(sending: sentData, for: .rest) @@ -71,7 +70,7 @@ class AWSRESTOperationTests: OperationTestBase { } } - waitForExpectations(timeout: 1.00) + await fulfillment(of: [receivedFailure, receivedSuccess], timeout: 1) } /// - Given: A configured plugin diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLMutateCombineTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLMutateCombineTests.swift index 830cdacf3b..51a53fd429 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLMutateCombineTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLMutateCombineTests.swift @@ -14,7 +14,7 @@ import XCTest class GraphQLMutateCombineTests: OperationTestBase { let testDocument = "mutate { updateTodo { id name description }}" - func testMutateSucceeds() throws { + func testMutateSucceeds() async throws { let testJSONData: JSONValue = ["foo": true] let sentData = Data(#"{"data": {"foo": true}}"#.utf8) try setUpPluginForSingleResponse(sending: sentData, for: .graphQL) @@ -46,12 +46,11 @@ class GraphQLMutateCombineTests: OperationTestBase { receivedResponseError.fulfill() } }) - - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.05) sink.cancel() } - func testMutateHandlesResponseError() throws { + func testMutateHandlesResponseError() async throws { let sentData = Data(#"{"data": {"foo": true}, "errors": []}"#.utf8) try setUpPluginForSingleResponse(sending: sentData, for: .graphQL) @@ -82,12 +81,12 @@ class GraphQLMutateCombineTests: OperationTestBase { } }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 0.05) sink.cancel() } - func testMutateFails() throws { + func testMutateFails() async throws { try setUpPluginForSingleError(for: .graphQL) let request = GraphQLRequest(document: testDocument, variables: nil, responseType: JSONValue.self) @@ -118,7 +117,7 @@ class GraphQLMutateCombineTests: OperationTestBase { } }) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [receivedValue, receivedFinish, receivedFailure, receivedResponseError], timeout: 1) sink.cancel() } } diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLQueryCombineTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLQueryCombineTests.swift index 9109d093af..b25059ec02 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLQueryCombineTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLQueryCombineTests.swift @@ -14,7 +14,7 @@ import XCTest class GraphQLQueryCombineTests: OperationTestBase { let testDocument = "query { getTodo { id name description }}" - func testQuerySucceeds() throws { + func testQuerySucceeds() async throws { let testJSONData: JSONValue = ["foo": true] let sentData = Data(#"{"data": {"foo": true}}"#.utf8) try setUpPluginForSingleResponse(sending: sentData, for: .graphQL) @@ -47,11 +47,16 @@ class GraphQLQueryCombineTests: OperationTestBase { } }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFinish, + receivedFailure, + receivedResponseError + ], + timeout: 0.05) sink.cancel() } - func testQueryHandlesResponseError() throws { + func testQueryHandlesResponseError() async throws { let sentData = Data(#"{"data": {"foo": true}, "errors": []}"#.utf8) try setUpPluginForSingleResponse(sending: sentData, for: .graphQL) @@ -82,12 +87,17 @@ class GraphQLQueryCombineTests: OperationTestBase { } }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFinish, + receivedFailure, + receivedResponseError + ], + timeout: 0.05) sink.cancel() } - func testQueryFails() throws { + func testQueryFails() async throws { try setUpPluginForSingleError(for: .graphQL) let request = GraphQLRequest(document: testDocument, variables: nil, responseType: JSONValue.self) @@ -118,7 +128,12 @@ class GraphQLQueryCombineTests: OperationTestBase { } }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFinish, + receivedFailure, + receivedResponseError + ], + timeout: 0.05) sink.cancel() } } diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTests.swift index 4b28c62cc2..b052ca2384 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/GraphQLSubscribeTests.swift @@ -102,7 +102,14 @@ class GraphQLSubscribeTests: OperationTestBase { mockAppSyncRealTimeClient.triggerEvent(.data(testData)) mockAppSyncRealTimeClient.triggerEvent(.unsubscribed) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } /// Lifecycle test @@ -131,7 +138,14 @@ class GraphQLSubscribeTests: OperationTestBase { try await MockAppSyncRealTimeClient.waitForSubscirbed() mockAppSyncRealTimeClient.triggerEvent(.unsubscribed) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } /// Lifecycle test @@ -158,7 +172,14 @@ class GraphQLSubscribeTests: OperationTestBase { try await MockAppSyncRealTimeClient.waitForSubscirbing() mockAppSyncRealTimeClient.triggerEvent(.error(["Error"])) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } /// Lifecycle test @@ -193,7 +214,14 @@ class GraphQLSubscribeTests: OperationTestBase { mockAppSyncRealTimeClient.triggerEvent(.data(testData)) mockAppSyncRealTimeClient.triggerEvent(.unsubscribed) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } func testMultipleSuccessValues() async throws { @@ -220,7 +248,14 @@ class GraphQLSubscribeTests: OperationTestBase { mockAppSyncRealTimeClient.triggerEvent(.data(testData)) mockAppSyncRealTimeClient.triggerEvent(.unsubscribed) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } func testMixedSuccessAndErrorValues() async throws { @@ -253,7 +288,14 @@ class GraphQLSubscribeTests: OperationTestBase { mockAppSyncRealTimeClient.triggerEvent(.data(successfulTestData)) mockAppSyncRealTimeClient.triggerEvent(.unsubscribed) - await waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedCompletionFinish, + receivedCompletionFailure, + receivedConnected, + receivedDisconnected, + receivedSubscriptionEventData, + receivedSubscriptionEventError + ], + timeout: 0.05) } // MARK: - Utilities diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/RESTCombineTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/RESTCombineTests.swift index 7713e35489..e2c91d45c2 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/RESTCombineTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Operation/RESTCombineTests.swift @@ -13,7 +13,7 @@ import XCTest class RESTCombineTests: OperationTestBase { - func testGetSucceeds() throws { + func testGetSucceeds() async throws { let sentData = Data([0x00, 0x01, 0x02, 0x03]) try setUpPluginForSingleResponse(sending: sentData, for: .graphQL) @@ -38,11 +38,11 @@ class RESTCombineTests: OperationTestBase { receivedValue.fulfill() }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.05) sink.cancel() } - func testGetFails() throws { + func testGetFails() async throws { let sentData = Data([0x00, 0x01, 0x02, 0x03]) try setUpPluginForSingleError(for: .graphQL) @@ -68,7 +68,7 @@ class RESTCombineTests: OperationTestBase { receivedValue.fulfill() }) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFinish, receivedFailure], timeout: 0.05) sink.cancel() } } diff --git a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Reachability/NetworkReachabilityNotifierTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Reachability/NetworkReachabilityNotifierTests.swift index 48f6886616..cce395ccd3 100644 --- a/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Reachability/NetworkReachabilityNotifierTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/Reachability/NetworkReachabilityNotifierTests.swift @@ -28,7 +28,7 @@ class NetworkReachabilityNotifierTests: XCTestCase { MockReachability.iConnection = .wifi } - func testWifiConnectivity() { + func testWifiConnectivity() async { MockReachability.iConnection = .wifi let expect = expectation(description: ".sink receives values") var values = [Bool]() @@ -45,11 +45,11 @@ class NetworkReachabilityNotifierTests: XCTestCase { notification = Notification.init(name: .reachabilityChanged) NotificationCenter.default.post(notification) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [expect], timeout: 1) cancellable.cancel() } - func testCellularConnectivity() { + func testCellularConnectivity() async { MockReachability.iConnection = .wifi let expect = expectation(description: ".sink receives values") var values = [Bool]() @@ -67,11 +67,11 @@ class NetworkReachabilityNotifierTests: XCTestCase { notification = Notification.init(name: .reachabilityChanged) NotificationCenter.default.post(notification) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [expect], timeout: 1) cancellable.cancel() } - func testNoConnectivity() { + func testNoConnectivity() async { MockReachability.iConnection = .unavailable let expect = expectation(description: ".sink receives values") var values = [Bool]() @@ -89,7 +89,7 @@ class NetworkReachabilityNotifierTests: XCTestCase { notification = Notification.init(name: .reachabilityChanged) NotificationCenter.default.post(notification) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [expect], timeout: 1) cancellable.cancel() } diff --git a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift index 0c7bad83fb..92c4636fd3 100644 --- a/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift +++ b/AmplifyPlugins/Analytics/Tests/AWSPinpointAnalyticsPluginUnitTests/AWSPinpointAnalyticsPluginClientBehaviorTests.swift @@ -35,7 +35,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.identifyUser is invoked with the user profile /// Then: AWSPinpoint.currentEndpoint and updateEndpoint methods are called /// and Hub Analytics.identifyUser event is dispatched with the input data - func testIdentifyUser() throws { + func testIdentifyUser() async throws { let analyticsEventReceived = expectation(description: "Analytics event was received on the hub plugin") _ = plugin.listen(to: .analytics, isIncluded: nil) { payload in @@ -64,7 +64,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.identifyUser(userId: testIdentityId, userProfile: userProfile) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCurrentEndpointProfile() mockPinpoint.verifyUpdate(expectedEndpointProfile) } @@ -85,7 +85,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.identifyUser is invoked with the user profile /// Then: AWSPinpoint.currentEndpoint and updateEndpoint methods are called /// and Hub Analytics.identifyUser event is dispatched with an error - func testIdentifyUserDispatchesErrorForPinpointError() throws { + func testIdentifyUserDispatchesErrorForPinpointError() async throws { mockPinpoint.updateEndpointProfileResult = .failure(NSError(domain: "domain", code: 1)) let analyticsEventReceived = expectation(description: "Analytics event was received on the hub plugin") @@ -115,7 +115,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.identifyUser(userId: testIdentityId, userProfile: userProfile) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCurrentEndpointProfile() mockPinpoint.verifyUpdate(expectedEndpointProfile) } @@ -126,7 +126,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.record is invoked with the basic event /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with the input data - func testRecordEvent() { + func testRecordEvent() async { let expectedPinpointEvent = PinpointEvent(eventType: testName, session: PinpointSession(appId: "", uniqueId: "")) mockPinpoint.createEventResult = expectedPinpointEvent expectedPinpointEvent.addProperties(testProperties) @@ -148,7 +148,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.record(event: event) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCreateEvent(withEventType: testName) mockPinpoint.verifyRecord(expectedPinpointEvent) } @@ -169,7 +169,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.record is invoked with the basic event /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with a error - func testRecordEventDispatchesErrorForPinpointError() { + func testRecordEventDispatchesErrorForPinpointError() async { mockPinpoint.recordResult = .failure(NSError(domain: "domain", code: 1, userInfo: nil)) @@ -194,7 +194,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.record(event: event) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCreateEvent(withEventType: testName) mockPinpoint.verifyRecord(expectedPinpointEvent) } @@ -205,7 +205,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.record is invoked with the event name /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with the input data - func testRecordEventWithName() { + func testRecordEventWithName() async { let expectedPinpointEvent = PinpointEvent(eventType: testName, session: PinpointSession(appId: "", uniqueId: "")) mockPinpoint.createEventResult = expectedPinpointEvent @@ -225,7 +225,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.record(eventWithName: testName) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCreateEvent(withEventType: testName) mockPinpoint.verifyRecord(expectedPinpointEvent) } @@ -245,7 +245,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.record is invoked with the event name /// Then: AWSPinpoint.createEvent and record methods are called /// and Hub Analytics.record event is dispatched with a error - func testRecordEventWithNameDispatchesErrorForPinpointError() { + func testRecordEventWithNameDispatchesErrorForPinpointError() async { mockPinpoint.recordResult = .failure(NSError(domain: "domain", code: 1, userInfo: nil)) @@ -268,7 +268,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT analyticsPlugin.record(eventWithName: testName) - waitForExpectations(timeout: 1) + await fulfillment(of: [analyticsEventReceived], timeout: 1) mockPinpoint.verifyCreateEvent(withEventType: testName) mockPinpoint.verifyRecord(expectedPinpointEvent) } @@ -278,13 +278,13 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Given: A dictionary of properties with different AnalyticsPropertyValue subclasses /// When: AnalyticsPlugin.registerGlobalProperties is invoked with the properties /// Then: The properties are set on the AnalyticsPlugin.globalProperties - func testRegisterGlobalProperties() { + func testRegisterGlobalProperties() async { mockPinpoint.addGlobalPropertyExpectation = expectation(description: "Add global property called") mockPinpoint.addGlobalPropertyExpectation?.expectedFulfillmentCount = testProperties.count analyticsPlugin.registerGlobalProperties(testProperties) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockPinpoint.addGlobalPropertyExpectation!], timeout: 1) XCTAssertEqual(analyticsPlugin.globalProperties.count, testProperties.count) XCTAssertTrue(mockPinpoint.addGlobalMetricCalled > 0) XCTAssertTrue(mockPinpoint.addGlobalAttributeCalled > 0) @@ -307,14 +307,14 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Given: A dictionary of properties with different AnalyticsPropertyValue subclasses /// When: AnalyticsPlugin.unregisterGlobalProperties is invoked with some property keys /// Then: The corresponding property keys are removed from the AnalyticsPlugin.globalProperties - func testUnregisterGlobalProperties() { + func testUnregisterGlobalProperties() async { mockPinpoint.removeGlobalPropertyExpectation = expectation(description: "Remove global property called") mockPinpoint.removeGlobalPropertyExpectation?.expectedFulfillmentCount = testProperties.count analyticsPlugin.globalProperties = AtomicDictionary(initialValue: testProperties) analyticsPlugin.unregisterGlobalProperties(Set(testProperties.keys)) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockPinpoint.removeGlobalPropertyExpectation!], timeout: 1) XCTAssertEqual(analyticsPlugin.globalProperties.count, 0) XCTAssertTrue(mockPinpoint.removeGlobalMetricCalled > 0) XCTAssertTrue(mockPinpoint.removeGlobalAttributeCalled > 0) @@ -323,14 +323,14 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// Given: globalProperties set on the AnalyticsPlugin /// When: AnalyticsPlugin.unregisterGlobalProperties is invoked with no properties /// Then: All of the global properties are removed - func testAllUnregisterGlobalProperties() { + func testAllUnregisterGlobalProperties() async { mockPinpoint.removeGlobalPropertyExpectation = expectation(description: "Remove global property called") mockPinpoint.removeGlobalPropertyExpectation?.expectedFulfillmentCount = testProperties.count analyticsPlugin.globalProperties = AtomicDictionary(initialValue: testProperties) analyticsPlugin.unregisterGlobalProperties(nil) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockPinpoint.removeGlobalPropertyExpectation!], timeout: 1) XCTAssertEqual(analyticsPlugin.globalProperties.count, 0) XCTAssertTrue(mockPinpoint.removeGlobalMetricCalled > 0) XCTAssertTrue(mockPinpoint.removeGlobalAttributeCalled > 0) @@ -342,7 +342,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.flushEvents is invoked /// Then: AWSPinpoint.submitEvents is invoked /// and Hub Analytics.flushEvents event is dispatched with submitted events - func testFlushEvents_isOnline() { + func testFlushEvents_isOnline() async { let result = [PinpointEvent(eventType: "1", session: PinpointSession(appId: "", uniqueId: "")), PinpointEvent(eventType: "2", session: PinpointSession(appId: "", uniqueId: ""))] mockNetworkMonitor.isOnline = true @@ -362,7 +362,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT } analyticsPlugin.flushEvents() - waitForExpectations(timeout: 1) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 1) mockPinpoint.verifySubmitEvents() } @@ -370,7 +370,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.flushEvents is invoked /// Then: AWSPinpoint.submitEvents is invoked /// and Hub Analytics.flushEvents event is dispatched with submitted events - func testFlushEvents_isOffline() { + func testFlushEvents_isOffline() async { let result = [PinpointEvent(eventType: "1", session: PinpointSession(appId: "", uniqueId: ""))] mockNetworkMonitor.isOnline = false mockPinpoint.submitEventsResult = .success(result) @@ -387,7 +387,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT } analyticsPlugin.flushEvents() - waitForExpectations(timeout: 1) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 1) XCTAssertEqual(mockPinpoint.submitEventsCalled, 0) } @@ -406,7 +406,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT /// When: AnalyticsPlugin.flushEvents is invoked /// Then: AWSPinpoint.submitEvents is invoked /// and Hub Analytics.flushEvents event is dispatched with error - func testFlushEventsDispatchesErrorForPinpointError() { + func testFlushEventsDispatchesErrorForPinpointError() async { mockPinpoint.submitEventsResult = .failure(NSError(domain: "domain", code: 1, userInfo: nil)) @@ -425,7 +425,7 @@ class AWSPinpointAnalyticsPluginClientBehaviorTests: AWSPinpointAnalyticsPluginT } analyticsPlugin.flushEvents() - waitForExpectations(timeout: 1) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 1) mockPinpoint.verifySubmitEvents() } diff --git a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift index 7bb9e254bd..420d8f5abd 100644 --- a/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift +++ b/AmplifyPlugins/Auth/Tests/AWSCognitoAuthPluginUnitTests/TaskTests/HostedUITests/AWSAuthHostedUISignInTests.swift @@ -176,7 +176,7 @@ class AWSAuthHostedUISignInTests: XCTestCase { errorExpectation.fulfill() } - waitForExpectations(timeout: networkTimeout) + await fulfillment(of: [errorExpectation], timeout: networkTimeout) mockHostedUIResult = .success([ .init(name: "state", value: mockState), .init(name: "code", value: mockProof) @@ -189,7 +189,7 @@ class AWSAuthHostedUISignInTests: XCTestCase { } catch { XCTFail("Should not fail with error = \(error)") } - waitForExpectations(timeout: networkTimeout) + await fulfillment(of: [signInExpectation], timeout: networkTimeout) } @MainActor diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/AWSDataStorePluginTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/AWSDataStorePluginTests.swift index de910896fe..869b62d24d 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/AWSDataStorePluginTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/AWSDataStorePluginTests.swift @@ -32,7 +32,7 @@ class AWSDataStorePluginTests: XCTestCase { } } - func testStorageEngineDoesNotStartsOnConfigure() throws { + func testStorageEngineDoesNotStartsOnConfigure() async throws { let startExpectation = expectation(description: "Start Sync should not be called") startExpectation.isInverted = true let storageEngine = MockStorageEngineBehavior() @@ -53,10 +53,10 @@ class AWSDataStorePluginTests: XCTestCase { } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [startExpectation], timeout: 1.0) } - func testStorageEngineStartsOnPluginStart() throws { + func testStorageEngineStartsOnPluginStart() async throws { let startExpectation = expectation(description: "Start Sync should be called") let storageEngine = MockStorageEngineBehavior() storageEngine.responders[.startSync] = StartSyncResponder { _ in @@ -77,8 +77,7 @@ class AWSDataStorePluginTests: XCTestCase { } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } - waitForExpectations(timeout: 1.0) - } + await fulfillment(of: [startExpectation], timeout: 1.0) } func testStorageEngineStartsOnQuery() async throws { let startExpectation = expectation(description: "Start Sync should be called with Query") @@ -113,7 +112,7 @@ class AWSDataStorePluginTests: XCTestCase { ) } - func testStorageEngineStartsOnPluginStopStart() throws { + func testStorageEngineStartsOnPluginStopStart() async throws { let stopExpectation = expectation(description: "Stop plugin should be called") stopExpectation.isInverted = true let startExpectation = expectation(description: "Start Sync should be called") @@ -148,10 +147,10 @@ class AWSDataStorePluginTests: XCTestCase { } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [startExpectation, stopExpectation], timeout: 1.0) } - func testStorageEngineStartsOnPluginClearStart() throws { + func testStorageEngineStartsOnPluginClearStart() async throws { let clearExpectation = expectation(description: "Clear should be called") let startExpectation = expectation(description: "Start Sync should be called") var currCount = 0 @@ -185,10 +184,10 @@ class AWSDataStorePluginTests: XCTestCase { } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [startExpectation, clearExpectation], timeout: 1.0) } - func testStorageEngineStartStopStart() throws { + func testStorageEngineStartStopStart() async throws { let startExpectation = expectation(description: "Start Sync should be called with start") let stopExpectation = expectation(description: "stop should be called") let startExpectationOnSecondStart = expectation(description: "Start Sync should be called again") @@ -234,7 +233,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1.0) let stopCompleted = expectation(description: "stop completed") plugin.stop(completion: { _ in @@ -242,7 +241,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) stopCompleted.fulfill() }) - wait(for: [stopCompleted], timeout: 1.0) + await fulfillment(of: [stopCompleted], timeout: 1.0) storageEngine.responders[.startSync] = StartSyncResponder { _ in startExpectationOnSecondStart.fulfill() @@ -252,19 +251,18 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.storageEngine) XCTAssertNotNil(plugin.dataStorePublisher) }) - wait( - for: [startExpectation, stopExpectation, startExpectationOnSecondStart], + await fulfillment(of: [startExpectation, stopExpectation, startExpectationOnSecondStart], timeout: 1, enforceOrder: true ) - wait(for: [finishNotReceived], timeout: 1) + await fulfillment(of: [finishNotReceived], timeout: 1) sink.cancel() } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } } - func testStorageEngineStartClearStart() throws { + func testStorageEngineStartClearStart() async throws { let startExpectation = expectation(description: "Start Sync should be called with start") let clearExpectation = expectation(description: "Clear should be called") let startExpectationOnSecondStart = expectation(description: "Start Sync should be called again") @@ -309,7 +307,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1.0) let clearCompleted = expectation(description: "clear completed") plugin.clear(completion: { _ in @@ -317,7 +315,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) clearCompleted.fulfill() }) - wait(for: [clearCompleted], timeout: 1.0) + await fulfillment(of: [clearCompleted], timeout: 1.0) storageEngine.responders[.startSync] = StartSyncResponder {_ in startExpectationOnSecondStart.fulfill() @@ -328,19 +326,18 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) }) - wait( - for: [startExpectation, clearExpectation, startExpectationOnSecondStart], + await fulfillment(of: [startExpectation, clearExpectation, startExpectationOnSecondStart], timeout: 1, enforceOrder: true ) - wait(for: [finishNotReceived], timeout: 1) + await fulfillment(of: [finishNotReceived], timeout: 1) sink.cancel() } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") } } - func testStorageEngineQueryClearQuery() throws { + func testStorageEngineQueryClearQuery() async throws { let startExpectation = expectation(description: "Start Sync should be called with Query") let clearExpectation = expectation(description: "Clear should be called") let startExpectationOnQuery = expectation(description: "Start Sync should be called again with Query") @@ -387,7 +384,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) queryCompleted.fulfill() }) - wait(for: [queryCompleted], timeout: 1.0) + await fulfillment(of: [queryCompleted], timeout: 1.0) let clearCompleted = expectation(description: "clear completed") plugin.clear(completion: { _ in @@ -395,7 +392,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) clearCompleted.fulfill() }) - wait(for: [clearCompleted], timeout: 1.0) + await fulfillment(of: [clearCompleted], timeout: 1.0) storageEngine.responders[.query] = QueryResponder {_ in count = self.expect(startExpectationOnQuery, count, 3) return .success([]) @@ -405,7 +402,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.storageEngine) XCTAssertNotNil(plugin.dataStorePublisher) }) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [startExpectation, clearExpectation, startExpectationOnQuery, finishNotReceived], timeout: 1.0) sink.cancel() } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") @@ -427,7 +424,7 @@ class AWSDataStorePluginTests: XCTestCase { /// - a mutation event is sent /// - Then: The subscriber to plugin's publisher should receive the mutation - func testStorageEngineStartClearSend() { + func testStorageEngineStartClearSend() async { let startExpectation = expectation(description: "Start Sync should be called with start") let clearExpectation = expectation(description: "Clear should be called") @@ -479,7 +476,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1.0) let clearCompleted = expectation(description: "clear completed") plugin.clear(completion: { _ in @@ -487,14 +484,14 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) clearCompleted.fulfill() }) - wait(for: [clearCompleted], timeout: 1.0) + await fulfillment(of: [clearCompleted], timeout: 1.0) let mockModel = MockSynced(id: "12345") try plugin.dataStorePublisher?.send(input: MutationEvent(model: mockModel, modelSchema: mockModel.schema, mutationType: .create)) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [startExpectation, clearExpectation, publisherReceivedValue, finishNotReceived], timeout: 1) sink.cancel() } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") @@ -507,7 +504,7 @@ class AWSDataStorePluginTests: XCTestCase { /// - plugin.stop() is called /// - a mutation event is sent /// - Then: The subscriber to plugin's publisher should receive the mutation - func testStorageEngineStartStopSend() { + func testStorageEngineStartStopSend() async { let startExpectation = expectation(description: "Start Sync should be called with start") let stopExpectation = expectation(description: "Stop should be called") @@ -558,7 +555,7 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1.0) let stopCompleted = expectation(description: "stop completed") plugin.stop(completion: { _ in @@ -566,10 +563,9 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) stopCompleted.fulfill() }) - wait(for: [stopCompleted], timeout: 1.0) + await fulfillment(of: [stopCompleted], timeout: 1.0) - wait( - for: [startExpectation, stopExpectation], + await fulfillment(of: [startExpectation, stopExpectation], timeout: 1, enforceOrder: true ) @@ -578,7 +574,7 @@ class AWSDataStorePluginTests: XCTestCase { modelSchema: mockModel.schema, mutationType: .create)) - wait(for: [publisherReceivedValue, finishNotReceived], timeout: 1) + await fulfillment(of: [publisherReceivedValue, finishNotReceived], timeout: 1) sink.cancel() } catch { XCTFail("DataStore configuration should not fail with nil configuration. \(error)") @@ -589,7 +585,7 @@ class AWSDataStorePluginTests: XCTestCase { /// - When: /// - plugin.clear() is called /// - Then: StorageEngine.clear is called - func testClearStorageWhenEngineIsNotStarted() { + func testClearStorageWhenEngineIsNotStarted() async { let storageEngine = MockStorageEngineBehavior() let pluginClearExpectation = expectation(description: "DataStore plugin .clear should called") let storageClearExpectation = expectation(description: "StorageEngine .clear should be called") @@ -611,10 +607,10 @@ class AWSDataStorePluginTests: XCTestCase { pluginClearExpectation.fulfill() } } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [pluginClearExpectation, storageClearExpectation], timeout: 1) } - func testStopStorageEngineOnTerminalEvent() { + func testStopStorageEngineOnTerminalEvent() async { let storageEngine = MockStorageEngineBehavior() let stopExpectation = expectation(description: "stop should be called") @@ -637,14 +633,14 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1) storageEngine.mockSyncEnginePublisher.send(completion: .finished) - wait(for: [stopExpectation], timeout: 1) + await fulfillment(of: [stopExpectation], timeout: 1) } - func testStopStorageEngineOnTerminalFailureEvent() { + func testStopStorageEngineOnTerminalFailureEvent() async { let storageEngine = MockStorageEngineBehavior() let stopExpectation = expectation(description: "stop should be called") var count = 0 @@ -667,10 +663,10 @@ class AWSDataStorePluginTests: XCTestCase { XCTAssertNotNil(plugin.dataStorePublisher) startCompleted.fulfill() }) - wait(for: [startCompleted], timeout: 1.0) + await fulfillment(of: [startCompleted], timeout: 1) storageEngine.mockSyncEnginePublisher.send(completion: .failure(.internalOperation("", "", nil))) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [stopExpectation], timeout: 1) } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/StateMachineTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/StateMachineTests.swift index 3f23198981..5d36c0ca33 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/StateMachineTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Core/StateMachineTests.swift @@ -18,14 +18,14 @@ class StateMachineTests: XCTestCase { /// - I `notify` the state machine /// - Then: /// - My reducer is executed - func testExecutesResolver() { + func testExecutesResolver() async { let resolverInvoked = expectation(description: "Resolver was invoked") let resolver = makeResolver { resolverInvoked.fulfill() } let stateMachine = StateMachine(initialState: .one, resolver: resolver) stateMachine.notify(action: .increment) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [resolverInvoked], timeout: 1) } /// - Given: A state machine @@ -33,7 +33,7 @@ class StateMachineTests: XCTestCase { /// - A caller connects a subscriber to the $state publisher /// - Then: /// - The caller receives the current state - func testNotifiesListenerOnSubscribe() { + func testNotifiesListenerOnSubscribe() async { let listenerInvoked = expectation(description: "Listener invoked") let resolver = makeResolver() let stateMachine = StateMachine(initialState: .one, resolver: resolver) @@ -43,7 +43,7 @@ class StateMachineTests: XCTestCase { XCTAssertEqual(currentState, .two) } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [listenerInvoked], timeout: 1) listener.cancel() } @@ -52,7 +52,7 @@ class StateMachineTests: XCTestCase { /// - A caller invokes `notify` on the state machine /// - Then: /// - The subscriber receives the new state - func testNotifiesListenerOnChange() { + func testNotifiesListenerOnChange() async { let listenerInvoked = expectation(description: "Listener invoked") listenerInvoked.expectedFulfillmentCount = 2 let resolver = makeResolver() @@ -63,7 +63,7 @@ class StateMachineTests: XCTestCase { stateMachine.notify(action: .increment) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [listenerInvoked], timeout: 1) listener.cancel() } @@ -72,7 +72,7 @@ class StateMachineTests: XCTestCase { /// - A caller notifies the state machine multiple times /// - Then: /// - The subscribe receives the new state in order - func testNotifiesListenerInOrder() { + func testNotifiesListenerInOrder() async { let receivedOneOnSubscribe = expectation(description: "Received .one on subscribe") let receivedTwoAfterSubscribe = expectation(description: "Received .two after subscribe") let receivedThreeAfterSubscribe = expectation(description: "Received .three after subscribe") @@ -106,16 +106,12 @@ class StateMachineTests: XCTestCase { } } - wait( - for: [ - receivedOneOnSubscribe, - receivedTwoAfterSubscribe, - receivedThreeAfterSubscribe, - receivedOneAfterSubscribe - ], - timeout: 1.0, - enforceOrder: true - ) + await fulfillment(of: [receivedOneOnSubscribe, + receivedTwoAfterSubscribe, + receivedThreeAfterSubscribe, + receivedOneAfterSubscribe], + timeout: 1, + enforceOrder: true) listener.cancel() } @@ -125,7 +121,7 @@ class StateMachineTests: XCTestCase { /// - I `notify` the state machine /// - Then: /// - The reducer is invoked on a queue other than the main thread - func testResolverNotInvokedOnMainThread() { + func testResolverNotInvokedOnMainThread() async { let resolverInvoked = expectation(description: "Resolver was invoked") let testQueue = DispatchQueue(label: "testQueue") @@ -140,7 +136,7 @@ class StateMachineTests: XCTestCase { stateMachine.notify(action: .increment) } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [resolverInvoked], timeout: 1) } /// - Given: A state machine @@ -148,7 +144,7 @@ class StateMachineTests: XCTestCase { /// - I `notify` the state machine /// - Then: /// - The reducer is invoked on a queue other than the one I am running on - func testResolverInvokedOnDifferentQueue() { + func testResolverInvokedOnDifferentQueue() async { let resolverInvoked = expectation(description: "Resolver was invoked") let key = DispatchSpecificKey() let testQueue = DispatchQueue(label: "testQueue") @@ -165,7 +161,7 @@ class StateMachineTests: XCTestCase { stateMachine.notify(action: .increment) } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [resolverInvoked], timeout: 1) } /// Returns a state reducer that executes `block` before resolving the state diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationSyncExpressionTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationSyncExpressionTests.swift index d2e0d60242..298fcdb8b9 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationSyncExpressionTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationSyncExpressionTests.swift @@ -54,7 +54,7 @@ class InitialSyncOperationSyncExpressionTests: XCTestCase { authModeStrategy: AWSDefaultAuthModeStrategy()) } - func testBaseQueryWithBasicSyncExpression() throws { + func testBaseQueryWithBasicSyncExpression() async throws { let responder = APIPluginQueryResponder { request, listener in XCTAssertEqual(request.document, """ query SyncMockSynceds($filter: ModelMockSyncedFilterInput, $limit: Int) { @@ -122,11 +122,11 @@ class InitialSyncOperationSyncExpressionTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } - func testBaseQueryWithFilterSyncExpression() throws { + func testBaseQueryWithFilterSyncExpression() async throws { let responder = APIPluginQueryResponder { request, listener in XCTAssertEqual(request.document, """ query SyncMockSynceds($filter: ModelMockSyncedFilterInput, $limit: Int) { @@ -194,11 +194,11 @@ class InitialSyncOperationSyncExpressionTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, finishedReceived, apiWasQueried, syncCompletionReceived], timeout: 1) sink.cancel() } - func testBaseQueryWithSyncExpressionConstantAll() throws { + func testBaseQueryWithSyncExpressionConstantAll() async throws { let responder = APIPluginQueryResponder { request, listener in XCTAssertEqual(request.document, """ query SyncMockSynceds($limit: Int) { @@ -249,7 +249,7 @@ class InitialSyncOperationSyncExpressionTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationTests.swift index d1a8a464aa..bea2d03aeb 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOperationTests.swift @@ -24,7 +24,7 @@ class InitialSyncOperationTests: XCTestCase { // MARK: - GetLastSyncTime - func testFullSyncWhenLastSyncPredicateNilAndCurrentSyncPredicateNonNil() { + func testFullSyncWhenLastSyncPredicateNilAndCurrentSyncPredicateNonNil() async { let lastSyncTime: Int64 = 123456 let lastSyncPredicate: String? = nil let currentSyncPredicate: DataStoreConfiguration @@ -79,11 +79,11 @@ class InitialSyncOperationTests: XCTestCase { syncPredicate: lastSyncPredicate) XCTAssertEqual(operation.getLastSyncTime(lastSyncMetadataLastSyncNil), expectedLastSync) - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived], timeout: 1) sink.cancel() } - func testFullSyncWhenLastSyncPredicateNonNilAndCurrentSyncPredicateNil() { + func testFullSyncWhenLastSyncPredicateNonNilAndCurrentSyncPredicateNil() async { let lastSyncTime: Int64 = 123456 let lastSyncPredicate: String? = "non nil" let expectedSyncType = SyncType.fullSync @@ -116,11 +116,11 @@ class InitialSyncOperationTests: XCTestCase { syncPredicate: lastSyncPredicate) XCTAssertEqual(operation.getLastSyncTime(lastSyncMetadataLastSyncNil), expectedLastSync) - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived], timeout: 1) sink.cancel() } - func testFullSyncWhenLastSyncPredicateDifferentFromCurrentSyncPredicate() { + func testFullSyncWhenLastSyncPredicateDifferentFromCurrentSyncPredicate() async { let lastSyncTime: Int64 = 123456 let lastSyncPredicate: String? = "non nil different from current predicate" let currentSyncPredicate: DataStoreConfiguration @@ -175,11 +175,11 @@ class InitialSyncOperationTests: XCTestCase { syncPredicate: lastSyncPredicate) XCTAssertEqual(operation.getLastSyncTime(lastSyncMetadataLastSyncNil), expectedLastSync) - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived], timeout: 1) sink.cancel() } - func testDeltaSyncWhenLastSyncPredicateSameAsCurrentSyncPredicate() { + func testDeltaSyncWhenLastSyncPredicateSameAsCurrentSyncPredicate() async { let startDateSeconds = (Int64(Date().timeIntervalSince1970) - 100) let lastSyncTime: Int64 = startDateSeconds * 1_000 let lastSyncPredicate: String? = "{\"field\":\"id\",\"operator\":{\"type\":\"equals\",\"value\":\"123\"}}" @@ -235,7 +235,7 @@ class InitialSyncOperationTests: XCTestCase { syncPredicate: lastSyncPredicate) XCTAssertEqual(operation.getLastSyncTime(lastSyncMetadataLastSyncNil), expectedLastSync) - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived], timeout: 1) sink.cancel() } @@ -246,7 +246,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() /// - Then: /// - It reads sync metadata from storage - func testReadsMetadata() { + func testReadsMetadata() async { let responder = QueryRequestListenerResponder> { _, listener in let startDateMilliseconds = Int64(Date().timeIntervalSince1970) * 1_000 let list = PaginatedList(items: [], nextToken: nil, startedAt: startDateMilliseconds) @@ -297,7 +297,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, metadataQueryReceived], timeout: 1) sink.cancel() } @@ -306,7 +306,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() /// - Then: /// - It performs a sync query against the API category - func testQueriesAPI() { + func testQueriesAPI() async { let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel") let responder = QueryRequestListenerResponder> { _, listener in let startDateMilliseconds = Int64(Date().timeIntervalSince1970) * 1_000 @@ -356,7 +356,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } @@ -365,7 +365,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() /// - Then: /// - The method invokes a completion callback when complete - func testInvokesPublisherCompletion() { + func testInvokesPublisherCompletion() async { let responder = QueryRequestListenerResponder> { _, listener in let startDateMilliseconds = Int64(Date().timeIntervalSince1970) * 1_000 let list = PaginatedList(items: [], nextToken: nil, startedAt: startDateMilliseconds) @@ -406,7 +406,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - wait(for: [syncCompletionReceived, finishedReceived], timeout: 1.0) + await fulfillment(of: [syncCompletionReceived, finishedReceived], timeout: 1) sink.cancel() } @@ -415,7 +415,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() against an API that returns paginated data /// - Then: /// - The method invokes a completion callback - func testRetrievesPaginatedData() { + func testRetrievesPaginatedData() async { let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel") apiWasQueried.expectedFulfillmentCount = 3 @@ -463,7 +463,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } @@ -472,7 +472,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() against an API that returns data /// - Then: /// - The method submits the returned data to the reconciliation queue - func testSubmitsToReconciliationQueue() { + func testSubmitsToReconciliationQueue() async { let startedAtMilliseconds = Int64(Date().timeIntervalSince1970) * 1_000 let model = MockSynced(id: "1") let anyModel = AnyModel(model) @@ -540,7 +540,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, itemSubmitted, offeredValueReceived], timeout: 1) sink.cancel() } @@ -549,7 +549,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() against an API that returns data /// - Then: /// - The method submits the returned data to the reconciliation queue - func testUpdatesSyncMetadata() throws { + func testUpdatesSyncMetadata() async throws { let startDateMilliseconds = Int64(Date().timeIntervalSince1970) * 1_000 let responder = QueryRequestListenerResponder> { _, listener in let startedAt = startDateMilliseconds @@ -598,7 +598,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived], timeout: 1) sink.cancel() guard let syncMetadata = try storageAdapter.queryModelSyncMetadata(for: MockSynced.schema) else { @@ -614,7 +614,7 @@ class InitialSyncOperationTests: XCTestCase { /// - I invoke main() against an API that returns .signedOut error /// - Then: /// - The method completes with a failure result, error handler is called. - func testQueriesAPIReturnSignedOutError() throws { + func testQueriesAPIReturnSignedOutError() async throws { let responder = QueryRequestListenerResponder> { _, listener in let authError = AuthError.signedOut("", "", nil) let apiError = APIError.operationError("", "", authError) @@ -704,7 +704,7 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, expectErrorHandlerCalled], timeout: 1) sink.cancel() } @@ -715,7 +715,7 @@ class InitialSyncOperationTests: XCTestCase { /// - Then: /// - It performs a sync query against the API category with a "lastSync" time from the last start time of /// the stored metadata - func testQueriesFromLastSync() throws { + func testQueriesFromLastSync() async throws { let startDateMilliseconds = (Int64(Date().timeIntervalSince1970) - 100) * 1_000 let storageAdapter = try SQLiteStorageEngineAdapter(connection: Connection(.inMemory)) @@ -731,7 +731,7 @@ class InitialSyncOperationTests: XCTestCase { syncMetadataSaved.fulfill() } } - wait(for: [syncMetadataSaved], timeout: 1.0) + await fulfillment(of: [syncMetadataSaved], timeout: 1) let apiWasQueried = expectation(description: "API was queried for a PaginatedList of AnyModel") let responder = QueryRequestListenerResponder> { request, listener in @@ -781,11 +781,11 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } - func testBaseQueryWhenExpiredLastSync() throws { + func testBaseQueryWhenExpiredLastSync() async throws { // Set start date to 100 seconds in the past let startDateMilliSeconds = (Int64(Date().timeIntervalSince1970) - 100) * 1_000 @@ -857,11 +857,11 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, syncCompletionReceived, finishedReceived, apiWasQueried], timeout: 1) sink.cancel() } - func testBaseQueryWithCustomSyncPageSize() throws { + func testBaseQueryWithCustomSyncPageSize() async throws { let storageAdapter = try SQLiteStorageEngineAdapter(connection: Connection(.inMemory)) try storageAdapter.setUp(modelSchemas: StorageEngine.systemModelSchemas + [MockSynced.schema]) @@ -921,7 +921,12 @@ class InitialSyncOperationTests: XCTestCase { operation.main() - waitForExpectations(timeout: 1) + await fulfillment(of: [ + syncStartedReceived, + syncCompletionReceived, + finishedReceived, + apiWasQueried], + timeout: 1) sink.cancel() } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOrchestratorTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOrchestratorTests.swift index fbe3f5b6af..7e62bb0743 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOrchestratorTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/InitialSyncOrchestratorTests.swift @@ -225,7 +225,7 @@ class InitialSyncOrchestratorTests: XCTestCase { /// - The orchestrator starts up /// - Then: /// - It performs a sync query for each registered model with concurrency set to count of models - func testInvokesCompletionCallback_ModelWithNoAssociations() throws { + func testInvokesCompletionCallback_ModelWithNoAssociations() async throws { ModelRegistry.reset() struct TestModelsWithNoAssociations: AmplifyModelRegistration { func registerModels(registry: ModelRegistry.Type) { @@ -282,7 +282,7 @@ class InitialSyncOrchestratorTests: XCTestCase { syncCallbackReceived.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, finishedReceived, syncCallbackReceived], timeout: 1) XCTAssertEqual(orchestrator.syncOperationQueue.maxConcurrentOperationCount, 2) sink.cancel() } @@ -292,7 +292,7 @@ class InitialSyncOrchestratorTests: XCTestCase { /// - The orchestrator starts up /// - Then: /// - It queries models in dependency order, from "parent" to "child" - func testShouldQueryModelsInDependencyOrder() { + func testShouldQueryModelsInDependencyOrder() async { ModelRegistry.reset() PostCommentModelRegistration().registerModels(registry: ModelRegistry.self) let postWasQueried = expectation(description: "Post was queried") @@ -348,7 +348,7 @@ class InitialSyncOrchestratorTests: XCTestCase { orchestrator.sync { _ in } - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, finishedReceived, postWasQueried, commentWasQueried], timeout: 1) XCTAssertEqual(orchestrator.syncOperationQueue.maxConcurrentOperationCount, 1) sink.cancel() } @@ -359,7 +359,7 @@ class InitialSyncOrchestratorTests: XCTestCase { /// - Then: /// - It queries models in dependency order, from "parent" to "child", even if parent data is returned in /// multiple pages - func testShouldQueryModelsInDependencyOrderWithPaginatedResults() { + func testShouldQueryModelsInDependencyOrderWithPaginatedResults() async { ModelRegistry.reset() PostCommentModelRegistration().registerModels(registry: ModelRegistry.self) let pageCount = 50 @@ -423,7 +423,7 @@ class InitialSyncOrchestratorTests: XCTestCase { orchestrator.sync { _ in } - waitForExpectations(timeout: 1) + await fulfillment(of: [syncStartedReceived, finishedReceived, postWasQueried, commentWasQueried], timeout: 1) XCTAssertEqual(orchestrator.syncOperationQueue.maxConcurrentOperationCount, 1) sink.cancel() } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/ModelSyncedEventEmitterTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/ModelSyncedEventEmitterTests.swift index f241dc20f8..d3ee5e1a1b 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/ModelSyncedEventEmitterTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/ModelSyncedEventEmitterTests.swift @@ -40,7 +40,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { /// - Then: /// - the order of the events received should be all the mutation events followed by the modelSyncedEvent. /// - func testReceiveLastMutationEventBeforeModelSyncedEvent() throws { + func testReceiveLastMutationEventBeforeModelSyncedEvent() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let mutationEventAppliedReceived = expectation(description: "mutationEventApplied received") mutationEventAppliedReceived.expectedFulfillmentCount = 3 @@ -106,7 +106,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { reconciliationQueue?.incomingEventSubject.send(.mutationEventApplied(postMutationEvent)) reconciliationQueue?.incomingEventSubject.send(.mutationEventDropped(modelName: Post.modelName)) reconciliationQueue?.incomingEventSubject.send(.mutationEventApplied(postMutationEvent)) - waitForExpectations(timeout: 1) + await fulfillment(of: [modelSyncedReceived, mutationEventAppliedReceived, mutationEventDroppedReceived], timeout: 1) XCTAssertTrue(modelSyncedEventReceivedLast) emitterSink?.cancel() } @@ -120,7 +120,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { /// - Then: /// - Hub event "ModelSyncedEvent" is sent out and subscriber receives all reconciled events. /// - func testSuccess() throws { + func testSuccess() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let mutationEventAppliedReceived = expectation(description: "mutationEventApplied received") mutationEventAppliedReceived.expectedFulfillmentCount = 5 @@ -176,7 +176,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { reconciliationQueue?.incomingEventSubject.send(.mutationEventDropped(modelName: Post.modelName)) reconciliationQueue?.incomingEventSubject.send(.mutationEventDropped(modelName: Post.modelName)) - waitForExpectations(timeout: 1) + await fulfillment(of: [modelSyncedReceived, mutationEventAppliedReceived, mutationEventDroppedReceived], timeout: 1) emitterSink?.cancel() } @@ -193,7 +193,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { /// - Then: /// - `modelSyncedEvent` received and emitter continues to send mutation events /// - func testConcurrent() throws { + func testConcurrent() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let mutationEventAppliedReceived = expectation(description: "mutationEventApplied received") mutationEventAppliedReceived.assertForOverFulfill = false @@ -253,7 +253,7 @@ class ModelSyncedEventEmitterTests: XCTestCase { _ = emitter.dispatchedModelSyncedEvent } - waitForExpectations(timeout: 10) + await fulfillment(of: [modelSyncedReceived, mutationEventAppliedReceived, mutationEventDroppedReceived], timeout: 10) emitterSink?.cancel() } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/SyncEventEmitterTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/SyncEventEmitterTests.swift index b74eed4313..09b3177891 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/SyncEventEmitterTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/InitialSync/SyncEventEmitterTests.swift @@ -35,7 +35,7 @@ class SyncEventEmitterTests: XCTestCase { /// - Then: /// - One modelSynced event should be received /// - One syncQueriesReady event should be received - func testModelSyncedAndSyncQueriesReadyWithOneModelRegistered() throws { + func testModelSyncedAndSyncQueriesReadyWithOneModelRegistered() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let syncQueriesReadyReceived = expectation(description: "syncQueriesReady received") @@ -91,7 +91,7 @@ class SyncEventEmitterTests: XCTestCase { reconciliationQueue?.incomingEventSubject.send(.mutationEventApplied(postMutationEvent)) - waitForExpectations(timeout: 1) + await fulfillment(of: [modelSyncedReceived, syncQueriesReadyReceived], timeout: 1) syncEventEmitter = nil syncEventEmitterSink?.cancel() } @@ -107,7 +107,7 @@ class SyncEventEmitterTests: XCTestCase { /// - Then: /// - Two modelSynced event should be received /// - One syncQueriesReady event should be received - func testModelSyncedAndSyncQueriesReadyWithTwoModelsRegisteredAndNoSyncQueriesComingBack() throws { + func testModelSyncedAndSyncQueriesReadyWithTwoModelsRegisteredAndNoSyncQueriesComingBack() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let syncQueriesReadyReceived = expectation(description: "syncQueriesReady received") @@ -169,7 +169,7 @@ class SyncEventEmitterTests: XCTestCase { initialSyncOrchestrator?.initialSyncOrchestratorTopic.send(.started(modelName: Comment.modelName, syncType: .fullSync)) initialSyncOrchestrator?.initialSyncOrchestratorTopic.send(.finished(modelName: Comment.modelName)) - waitForExpectations(timeout: 1) + await fulfillment(of: [modelSyncedReceived, syncQueriesReadyReceived], timeout: 1) syncEventEmitter = nil syncEventEmitterSink?.cancel() } @@ -185,7 +185,7 @@ class SyncEventEmitterTests: XCTestCase { /// - Then: /// - Two modelSynced event should be received /// - One syncQueriesReady event should be received - func testModelSyncedAndSyncQueriesReadyWithTwoModelsRegisteredAndSyncQueriesComingBack() throws { + func testModelSyncedAndSyncQueriesReadyWithTwoModelsRegisteredAndSyncQueriesComingBack() async throws { let modelSyncedReceived = expectation(description: "modelSynced received") let syncQueriesReadyReceived = expectation(description: "syncQueriesReady received") @@ -277,7 +277,7 @@ class SyncEventEmitterTests: XCTestCase { reconciliationQueue?.incomingEventSubject.send(.mutationEventApplied(postMutationEvent)) reconciliationQueue?.incomingEventSubject.send(.mutationEventApplied(commentMutationEvent)) - waitForExpectations(timeout: 1) + await fulfillment(of: [modelSyncedReceived, syncQueriesReadyReceived], timeout: 1) syncEventEmitter = nil syncEventEmitterSink?.cancel() } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/AWSMutationDatabaseAdapterTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/AWSMutationDatabaseAdapterTests.swift index a8d8829f3c..ff87ba4b70 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/AWSMutationDatabaseAdapterTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/AWSMutationDatabaseAdapterTests.swift @@ -151,7 +151,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { } /// Retrieve the first MutationEvent - func test_getNextMutationEvent_AlreadyInProcess() { + func test_getNextMutationEvent_AlreadyInProcess() async { let queryExpectation = expectation(description: "query called") let getMutationEventCompleted = expectation(description: "getNextMutationEvent completed") var mutationEvent1 = MutationEvent(modelId: "1111-22", @@ -178,11 +178,11 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { getMutationEventCompleted.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [getMutationEventCompleted, queryExpectation], timeout: 1) } /// Retrieve the first MutationEvent - func test_getNextMutationEvent_MarkInProcess() { + func test_getNextMutationEvent_MarkInProcess() async { let queryExpectation = expectation(description: "query called") let getMutationEventCompleted = expectation(description: "getNextMutationEvent completed") let mutationEvent1 = MutationEvent(modelId: "1111-22", @@ -210,7 +210,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { getMutationEventCompleted.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [getMutationEventCompleted, queryExpectation], timeout: 1) } /// This tests uses an in-memory SQLite connection to save and query mutation events. @@ -219,7 +219,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { /// 2. The second query will also return `m2` since `inProcess` does not impact the results /// 3. Delete `m2` from the storage /// 4. The third query will return `m1` since `m2` was dequeued - func testGetNextMutationEvent_WithInMemoryStorage() throws { + func testGetNextMutationEvent_WithInMemoryStorage() async throws { let connection = try Connection(.inMemory) let storageAdapter = try SQLiteStorageEngineAdapter(connection: connection) try storageAdapter.setUp(modelSchemas: StorageEngine.systemModelSchemas) @@ -263,7 +263,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { firstQueryCompleted.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [firstQueryCompleted], timeout: 1) // (2) let secondQueryCompleted = expectation(description: "getNextMutationEvent completed") @@ -279,7 +279,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { secondQueryCompleted.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [secondQueryCompleted], timeout: 1) // (3) storageAdapter.delete(MutationEvent.self, @@ -307,7 +307,7 @@ class AWSMutationDatabaseAdapterTests: XCTestCase { thirdQueryCompleted.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [thirdQueryCompleted], timeout: 1) } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/OutgoingMutationQueueTestsWithMockStateMachine.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/OutgoingMutationQueueTestsWithMockStateMachine.swift index d8442e9b96..0699e41032 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/OutgoingMutationQueueTestsWithMockStateMachine.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/MutationQueue/OutgoingMutationQueueTestsWithMockStateMachine.swift @@ -42,7 +42,7 @@ class OutgoingMutationQueueMockStateTest: XCTestCase { reconciliationQueue = MockReconciliationQueue() } - func testInitialState() { + func testInitialState() async { let expect = expectation(description: "state initialized") stateMachine.pushExpectActionCriteria { action in XCTAssertEqual(action, OutgoingMutationQueue.Action.initialized) @@ -53,12 +53,12 @@ class OutgoingMutationQueueMockStateTest: XCTestCase { storageAdapter: storageAdapter, dataStoreConfiguration: .testDefault(), authModeStrategy: AWSDefaultAuthModeStrategy()) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) XCTAssertEqual(stateMachine.state, OutgoingMutationQueue.State.notInitialized) } - func testStartingState() { + func testStartingState() async { let expect = expectation(description: "state receivedSubscription") stateMachine.pushExpectActionCriteria { action in XCTAssertEqual(action, OutgoingMutationQueue.Action.receivedSubscription) @@ -66,7 +66,7 @@ class OutgoingMutationQueueMockStateTest: XCTestCase { } stateMachine.state = .starting(apiBehavior, publisher, reconciliationQueue) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } func testRequestingEvent_subscriptionSetup() throws { @@ -123,7 +123,7 @@ class OutgoingMutationQueueMockStateTest: XCTestCase { wait(for: [processEvent], timeout: 1) } - func testRequestingEvent_nosubscription() { + func testRequestingEvent_nosubscription() async { let expect = expectation(description: "state requestingEvent, no subscription") stateMachine.pushExpectActionCriteria { action in let error = DataStoreError.unknown("_", "", nil) @@ -132,7 +132,7 @@ class OutgoingMutationQueueMockStateTest: XCTestCase { } stateMachine.state = .requestingEvent - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } func testReceivedStartActionWhileExpectingEventProcessedAction() throws { diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/ReconcileAndLocalSaveOperationTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/ReconcileAndLocalSaveOperationTests.swift index 610c58ba31..52447a2ff4 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/ReconcileAndLocalSaveOperationTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/ReconcileAndLocalSaveOperationTests.swift @@ -75,7 +75,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { // MARK: - State tests - func testReconcile() { + func testReconcile() async { let expect = expectation(description: "action .reconciled") storageAdapter.returnOnSave(dataStoreResult: .success(anyPostMutationSync.model)) @@ -86,10 +86,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([anyPostMutationSync]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testReconcile_nilStorageAdapter() { + func testReconcile_nilStorageAdapter() async { let expect = expectation(description: "action .errored") let expectedDropped = expectation(description: "mutationEventDropped received") storageAdapter = nil @@ -110,10 +110,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([anyPostMutationSync]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } - func testReconcile_emptyRemoteModels() { + func testReconcile_emptyRemoteModels() async { let expect = expectation(description: "action .reconciled") stateMachine.pushExpectActionCriteria { action in @@ -123,10 +123,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testReconcile_failedQueryPendingMutations() { + func testReconcile_failedQueryPendingMutations() async { let expect = expectation(description: "action .reconciled") let expectedDropped = expectation(description: "mutationEventDropped received") @@ -151,10 +151,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([anyPostMutationSync]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } - func testReconcile_transactionDataStoreError() { + func testReconcile_transactionDataStoreError() async { let expect = expectation(description: "action .errored") let error = DataStoreError.internalOperation("Transaction failed", "") @@ -166,10 +166,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([anyPostMutationSync]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testReconcile_transactionError() { + func testReconcile_transactionError() async { let expect = expectation(description: "action .errored") enum UnknownError: Error { @@ -184,10 +184,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { stateMachine.state = .reconciling([anyPostMutationSync]) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testInError() { + func testInError() async { let expect = expectation(description: "publisher should finish") operation.publisher.sink { completion in switch completion { @@ -198,10 +198,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { } } receiveValue: { _ in }.store(in: &cancellables) stateMachine.state = .inError(DataStoreError.unknown("InError State", "")) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testFinished() { + func testFinished() async { let expect = expectation(description: "publisher should finish") operation.publisher.sink { completion in switch completion { @@ -213,12 +213,12 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { } receiveValue: { _ in }.store(in: &cancellables) stateMachine.state = .finished - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } // MARK: - queryPendingMutations - func testQueryPendingMutations_nilStorageAdapter() { + func testQueryPendingMutations_nilStorageAdapter() async { let expect = expectation(description: "storage adapter error") storageAdapter = nil @@ -235,10 +235,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTFail("Unexpected \(mutationEvents)") }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testQueryPendingMutations_emptyModels() { + func testQueryPendingMutations_emptyModels() async { let expect = expectation(description: "should complete successfully for empty input") expect.expectedFulfillmentCount = 2 @@ -255,10 +255,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testQueryPendingMutations_querySuccess() { + func testQueryPendingMutations_querySuccess() async { let expect = expectation(description: "queried pending mutations success") expect.expectedFulfillmentCount = 2 @@ -279,10 +279,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testQueryPendingMutations_queryFailure() { + func testQueryPendingMutations_queryFailure() async { let expect = expectation(description: "queried pending mutations failed") let expectedDropped = expectation(description: "mutationEventDropped received") let queryResponder = QueryModelTypePredicateResponder { _, _ in @@ -309,7 +309,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTFail("Should not return a value") }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } // MARK: - reconcile(remoteModels:pendingMutations) @@ -392,7 +392,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { // MARK: - queryLocalMetadata - func testQueryLocalMetadata_nilStorageAdapter() { + func testQueryLocalMetadata_nilStorageAdapter() async { let expect = expectation(description: "storage adapter error") let expectedDropped = expectation(description: "mutationEventDropped received") storageAdapter = nil @@ -417,10 +417,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTFail("Unexpected \(result)") }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } - func testQueryLocalMetadata_emptyModels() { + func testQueryLocalMetadata_emptyModels() async { let expect = expectation(description: "should complete successfully for empty input") expect.expectedFulfillmentCount = 2 @@ -438,10 +438,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testQueryLocalMetadata_querySuccess() { + func testQueryLocalMetadata_querySuccess() async { let expect = expectation(description: "queried local metadata success") expect.expectedFulfillmentCount = 2 @@ -468,7 +468,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } // MARK: - reconcile(remoteModels:localMetadata) @@ -479,7 +479,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTAssertTrue(result.isEmpty) } - func testReconcileLocalMetadata_emptyLocalMetadatas() { + func testReconcileLocalMetadata_emptyLocalMetadatas() async { let result = operation.getDispositions(for: [anyPostMutationSync], localMetadatas: []) guard let remoteModelDisposition = result.first else { @@ -489,7 +489,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTAssertEqual(remoteModelDisposition, .create(anyPostMutationSync)) } - func testReconcileLocalMetadata_success() { + func testReconcileLocalMetadata_success() async { let expect = expectation(description: "notify dropped twice") expect.expectedFulfillmentCount = 2 let model1 = AnyModel(Post(title: "post1", content: "content", createdAt: .now())) @@ -540,12 +540,12 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { localMetadatas: [localMetadata1, localMetadata2]) XCTAssertTrue(result.isEmpty) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } // MARK: - applyRemoteModels - func testApplyRemoteModels_nilStorageAdapter() { + func testApplyRemoteModels_nilStorageAdapter() async { let expect = expectation(description: "storage adapter error") let expectedDropped = expectation(description: "mutationEventDropped received") operation.publisher.sink { _ in } receiveValue: { event in @@ -571,10 +571,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { XCTFail("Unexpected \(result)") }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } - func testApplyRemoteModels_emptyDisposition() { + func testApplyRemoteModels_emptyDisposition() async { let expect = expectation(description: "should complete successfully") expect.expectedFulfillmentCount = 2 @@ -589,18 +589,18 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect], timeout: 1) } - func testApplyRemoteModels_createDisposition() { + func testApplyRemoteModels_createDisposition() async { let expect = expectation(description: "operation should send value and complete successfully") expect.expectedFulfillmentCount = 2 - let stoargeExpect = expectation(description: "storage save should be called") + let storageExpect = expectation(description: "storage save should be called") let storageMetadataExpect = expectation(description: "storage save metadata should be called") let notifyExpect = expectation(description: "mutation event should be emitted") let hubExpect = expectation(description: "Hub is notified") let saveResponder = SaveUntypedModelResponder { model, completion in - stoargeExpect.fulfill() + storageExpect.fulfill() completion(.success(model)) } @@ -646,19 +646,19 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, storageExpect, storageMetadataExpect, notifyExpect, hubExpect], timeout: 1) Amplify.Hub.removeListener(hubListener) } - func testApplyRemoteModels_updateDisposition() { + func testApplyRemoteModels_updateDisposition() async { let expect = expectation(description: "operation should send value and complete successfully") expect.expectedFulfillmentCount = 2 - let stoargeExpect = expectation(description: "storage save should be called") + let storageExpect = expectation(description: "storage save should be called") let storageMetadataExpect = expectation(description: "storage save metadata should be called") let notifyExpect = expectation(description: "mutation event should be emitted") let hubExpect = expectation(description: "Hub is notified") let saveResponder = SaveUntypedModelResponder { _, completion in - stoargeExpect.fulfill() + storageExpect.fulfill() completion(.success(self.anyPostMutationSync.model)) } storageAdapter.responders[.saveUntypedModel] = saveResponder @@ -702,19 +702,19 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, storageExpect, storageMetadataExpect, notifyExpect, hubExpect], timeout: 1) } - func testApplyRemoteModels_deleteDisposition() { + func testApplyRemoteModels_deleteDisposition() async { let expect = expectation(description: "operation should send value and complete successfully") expect.expectedFulfillmentCount = 2 - let stoargeExpect = expectation(description: "storage delete should be called") + let storageExpect = expectation(description: "storage delete should be called") let storageMetadataExpect = expectation(description: "storage save metadata should be called") let notifyExpect = expectation(description: "mutation event should be emitted") let hubExpect = expectation(description: "Hub is notified") let deleteResponder = DeleteUntypedModelCompletionResponder { _, id in XCTAssertEqual(id, self.anyPostMutationSync.model.id) - stoargeExpect.fulfill() + storageExpect.fulfill() return .emptyResult } storageAdapter.responders[.deleteUntypedModel] = deleteResponder @@ -758,11 +758,11 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) - + await fulfillment(of: [expect, storageExpect, storageMetadataExpect, notifyExpect, hubExpect], timeout: 1) + } - func testApplyRemoteModels_multipleDispositions() { + func testApplyRemoteModels_multipleDispositions() async { let dispositions: [RemoteSyncReconciler.Disposition] = [.create(anyPostMutationSync), .create(anyPostMutationSync), .update(anyPostMutationSync), @@ -774,8 +774,8 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { .delete(anyPostMutationSync)] let expect = expectation(description: "should complete successfully") expect.expectedFulfillmentCount = 2 - let stoargeExpect = expectation(description: "storage save/delete should be called") - stoargeExpect.expectedFulfillmentCount = dispositions.count + let storageExpect = expectation(description: "storage save/delete should be called") + storageExpect.expectedFulfillmentCount = dispositions.count let storageMetadataExpect = expectation(description: "storage save metadata should be called") storageMetadataExpect.expectedFulfillmentCount = dispositions.count let notifyExpect = expectation(description: "mutation event should be emitted") @@ -784,14 +784,14 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { hubExpect.expectedFulfillmentCount = dispositions.count let saveResponder = SaveUntypedModelResponder { _, completion in - stoargeExpect.fulfill() + storageExpect.fulfill() completion(.success(self.anyPostMutationSync.model)) } storageAdapter.responders[.saveUntypedModel] = saveResponder let deleteResponder = DeleteUntypedModelCompletionResponder { _, id in XCTAssertEqual(id, self.anyPostMutationSync.model.id) - stoargeExpect.fulfill() + storageExpect.fulfill() return .emptyResult } storageAdapter.responders[.deleteUntypedModel] = deleteResponder @@ -835,10 +835,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, storageExpect, notifyExpect, storageMetadataExpect, hubExpect], timeout: 1) } - func testApplyRemoteModels_skipFailedOperations() throws { + func testApplyRemoteModels_skipFailedOperations() async throws { let dispositions: [RemoteSyncReconciler.Disposition] = [.create(anyPostMutationSync), .create(anyPostMutationSync), .update(anyPostMutationSync), @@ -890,10 +890,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped, expectedDeleteSuccess], timeout: 1) } - func testApplyRemoteModels_failWithConstraintViolationShouldBeSuccessful() { + func testApplyRemoteModels_failWithConstraintViolationShouldBeSuccessful() async { let expect = expectation(description: "should complete successfully") expect.expectedFulfillmentCount = 2 let dispositions: [RemoteSyncReconciler.Disposition] = [.create(anyPostMutationSync), @@ -947,10 +947,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in expect.fulfill() }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectDropped], timeout: 1) } - func testApplyRemoteModels_deleteFail() throws { + func testApplyRemoteModels_deleteFail() async throws { let dispositions: [RemoteSyncReconciler.Disposition] = [ .create(anyPostMutationSync), .create(anyPostMutationSync), @@ -1004,10 +1004,10 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped, expectedCreateAndUpdateSuccess], timeout: 1) } - func testApplyRemoteModels_saveMetadataFail() throws { + func testApplyRemoteModels_saveMetadataFail() async throws { let dispositions: [RemoteSyncReconciler.Disposition] = [ .create(anyPostMutationSync), .create(anyPostMutationSync), @@ -1058,7 +1058,7 @@ class ReconcileAndLocalSaveOperationTests: XCTestCase { }, receiveValue: { _ in }).store(in: &cancellables) - waitForExpectations(timeout: 1) + await fulfillment(of: [expect, expectedDropped], timeout: 1) } } diff --git a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/RemoteSyncReconcilerTests.swift b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/RemoteSyncReconcilerTests.swift index 1584ed3897..3cac3f153d 100644 --- a/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/RemoteSyncReconcilerTests.swift +++ b/AmplifyPlugins/DataStore/Tests/AWSDataStorePluginTests/Sync/SubscriptionSync/RemoteSyncReconcilerTests.swift @@ -134,7 +134,7 @@ class RemoteSyncReconcilerTests: XCTestCase { XCTAssertTrue(dispositions.isEmpty) } - func testReconcileLocalMetadatas_multiple() { + func testReconcileLocalMetadatas_multiple() async { // no corresponding local metadata, not deleted remote, should be create let createModel = makeRemoteModel(deleted: false, version: 1) @@ -177,7 +177,7 @@ class RemoteSyncReconcilerTests: XCTestCase { delete.fulfill() } } - waitForExpectations(timeout: 1) + await fulfillment(of: [create, update, delete], timeout: 1) } func testGetDispositions_emptyLocal_singleModelAddedAndDeleted() { diff --git a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift index ee1c0a8736..6016643f73 100644 --- a/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift +++ b/AmplifyPlugins/Internal/Tests/InternalAWSPinpointUnitTests/ActivityTrackerTests.swift @@ -64,16 +64,16 @@ class ActivityTrackerTests: XCTestCase { stateMachine = nil } - func testBeginTracking() { + func testBeginTracking() async { let expectation = expectation(description: "Initial state") tracker.beginActivityTracking { newState in XCTAssertEqual(newState, .initializing) expectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } - func testApplicationStateChanged_shouldReportProperEvent() { + func testApplicationStateChanged_shouldReportProperEvent() async { stateMachine.processExpectation = expectation(description: "Application state changed") stateMachine.processExpectation?.expectedFulfillmentCount = 3 @@ -81,21 +81,23 @@ class ActivityTrackerTests: XCTestCase { NotificationCenter.default.post(Notification(name: Self.applicationWillMoveToForegoundNotification)) NotificationCenter.default.post(Notification(name: Self.applicationWillTerminateNotification)) - waitForExpectations(timeout: 1) + await fulfillment(of: [stateMachine.processExpectation!], timeout: 1) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationDidMoveToBackground)) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationWillMoveToForeground)) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationWillTerminate)) } - func testBackgroundTracking_afterTimeout_shouldReportBackgroundTimeout() { + @MainActor + func testBackgroundTracking_afterTimeout_shouldReportBackgroundTimeout() async { stateMachine.processExpectation = expectation(description: "Background tracking timeout") stateMachine.processExpectation?.expectedFulfillmentCount = 2 NotificationCenter.default.post(Notification(name: Self.applicationDidMoveToBackgroundNotification)) - - waitForExpectations(timeout: 2) + + await fulfillment(of: [stateMachine.processExpectation!], timeout: 2) XCTAssertTrue(stateMachine.processedEvents.contains(.applicationDidMoveToBackground)) XCTAssertTrue(stateMachine.processedEvents.contains(.backgroundTrackingDidTimeout)) + } } diff --git a/AmplifyPlugins/Notifications/Push/Tests/AWSPinpointPushNotificationsPluginUnitTests/AWSPinpointPushNotificationsPluginConfigureTests.swift b/AmplifyPlugins/Notifications/Push/Tests/AWSPinpointPushNotificationsPluginUnitTests/AWSPinpointPushNotificationsPluginConfigureTests.swift index 46b97b950b..2c3ce8461c 100644 --- a/AmplifyPlugins/Notifications/Push/Tests/AWSPinpointPushNotificationsPluginUnitTests/AWSPinpointPushNotificationsPluginConfigureTests.swift +++ b/AmplifyPlugins/Notifications/Push/Tests/AWSPinpointPushNotificationsPluginUnitTests/AWSPinpointPushNotificationsPluginConfigureTests.swift @@ -57,29 +57,29 @@ class AWSPinpointPushNotificationsPluginConfigureTests: AWSPinpointPushNotificat } } - func testConfigure_withNotificationsPermissionsGranted_shouldRegisterForRemoteNotifications() throws { + func testConfigure_withNotificationsPermissionsGranted_shouldRegisterForRemoteNotifications() async throws { mockRemoteNotifications.mockedRequestAuthorizationResult = true mockRemoteNotifications.registerForRemoteNotificationsExpectation = expectation(description: "Permissions Granted") try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockRemoteNotifications.registerForRemoteNotificationsExpectation!], timeout: 1) } - func testConfigure_withNotificationsPermissionsDenied_shouldRegisterForRemoteNotifications() throws { + func testConfigure_withNotificationsPermissionsDenied_shouldRegisterForRemoteNotifications() async throws { mockRemoteNotifications.mockedRequestAuthorizationResult = false mockRemoteNotifications.registerForRemoteNotificationsExpectation = expectation(description: "Permissions Denied") try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockRemoteNotifications.registerForRemoteNotificationsExpectation!], timeout: 1) } - func testConfigure_withNotificationsPermissionsFailed_shouldRegisterForRemoteNotifications() throws { + func testConfigure_withNotificationsPermissionsFailed_shouldRegisterForRemoteNotifications() async throws { let error = PushNotificationsError.service("Description", "Recovery", nil) mockRemoteNotifications.requestAuthorizationError = error mockRemoteNotifications.registerForRemoteNotificationsExpectation = expectation(description: "Permissions Failed") try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [mockRemoteNotifications.registerForRemoteNotificationsExpectation!], timeout: 1) } - func testConfigure_withEmptyOptions_shouldNotReportToHub() throws { + func testConfigure_withEmptyOptions_shouldNotReportToHub() async throws { plugin = AWSPinpointPushNotificationsPlugin(options: []) try plugin.configure(using: createPushNotificationsPluginConfig()) let eventWasReported = expectation(description: "Event was reported to Hub") @@ -89,10 +89,10 @@ class AWSPinpointPushNotificationsPluginConfigureTests: AWSPinpointPushNotificat } } eventWasReported.isInverted = true - waitForExpectations(timeout: 1) + await fulfillment(of: [eventWasReported], timeout: 1) } - func testConfigure_withNotificationsPermissionsGranted_shouldReportSuccessToHub() throws { + func testConfigure_withNotificationsPermissionsGranted_shouldReportSuccessToHub() async throws { mockRemoteNotifications.mockedRequestAuthorizationResult = true let eventWasReported = expectation(description: "Event was reported to Hub") @@ -109,10 +109,10 @@ class AWSPinpointPushNotificationsPluginConfigureTests: AWSPinpointPushNotificat } try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [eventWasReported], timeout: 1) } - func testConfigure_withNotificationsPermissionsDenied_shouldReportFailureToHub() throws { + func testConfigure_withNotificationsPermissionsDenied_shouldReportFailureToHub() async throws { mockRemoteNotifications.mockedRequestAuthorizationResult = false let eventWasReported = expectation(description: "Event was reported to Hub") @@ -129,10 +129,10 @@ class AWSPinpointPushNotificationsPluginConfigureTests: AWSPinpointPushNotificat } try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [eventWasReported], timeout: 1) } - func testConfigure_withNotificationsPermissionsFailed_shouldReportErrorToHub() throws { + func testConfigure_withNotificationsPermissionsFailed_shouldReportErrorToHub() async throws { let error = PushNotificationsError.service("Description", "Recovery", nil) mockRemoteNotifications.requestAuthorizationError = error @@ -151,7 +151,7 @@ class AWSPinpointPushNotificationsPluginConfigureTests: AWSPinpointPushNotificat } try plugin.configure(using: createPushNotificationsPluginConfig()) - waitForExpectations(timeout: 1) + await fulfillment(of: [eventWasReported], timeout: 1) } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Dependency/AWSS3AdapterTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Dependency/AWSS3AdapterTests.swift index e0f621fb40..937c59fedb 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Dependency/AWSS3AdapterTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Dependency/AWSS3AdapterTests.swift @@ -32,7 +32,7 @@ class AWSS3AdapterTests: XCTestCase { /// Given: An AWSS3Adapter /// When: deleteObject is invoked and the s3 client returns success /// Then: A .success result is returned - func testDeleteObject_withSuccess_shouldSucceed() { + func testDeleteObject_withSuccess_shouldSucceed() async { let deleteExpectation = expectation(description: "Delete Object") adapter.deleteObject(.init(bucket: "bucket", key: "key")) { result in XCTAssertEqual(self.awsS3.deleteObjectCount, 1) @@ -43,13 +43,13 @@ class AWSS3AdapterTests: XCTestCase { deleteExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [deleteExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: deleteObject is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testDeleteObject_withError_shouldFail() { + func testDeleteObject_withError_shouldFail() async { let deleteExpectation = expectation(description: "Delete Object") awsS3.deleteObjectResult = .failure(StorageError.keyNotFound("InvalidKey", "", "", nil)) adapter.deleteObject(.init(bucket: "bucket", key: "key")) { result in @@ -62,13 +62,14 @@ class AWSS3AdapterTests: XCTestCase { XCTAssertEqual(key, "InvalidKey") deleteExpectation.fulfill() } - waitForExpectations(timeout: 1) + + await fulfillment(of: [deleteExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: listObjectsV2 is invoked and the s3 client returns a list of objects /// Then: A .success result is returned containing the corresponding list items - func testListObjectsV2_withSuccess_shouldSucceed() { + func testListObjectsV2_withSuccess_shouldSucceed() async { let listExpectation = expectation(description: "List Objects") awsS3.listObjectsV2Result = .success(ListObjectsV2Output( contents: [ @@ -91,13 +92,13 @@ class AWSS3AdapterTests: XCTestCase { listExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [listExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: listObjectsV2 is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testListObjectsV2_withError_shouldFail() { + func testListObjectsV2_withError_shouldFail() async { let listExpectation = expectation(description: "List Objects") awsS3.listObjectsV2Result = .failure(StorageError.accessDenied("AccessDenied", "", nil)) adapter.listObjectsV2(.init( @@ -114,13 +115,13 @@ class AWSS3AdapterTests: XCTestCase { listExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [listExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: createMultipartUpload is invoked and the s3 client returns a valid response /// Then: A .success result is returned containing the corresponding parsed response - func testCreateMultipartUpload_withSuccess_shouldSucceed() { + func testCreateMultipartUpload_withSuccess_shouldSucceed() async { let createMultipartUploadExpectation = expectation(description: "Create Multipart Upload") awsS3.createMultipartUploadResult = .success(.init( bucket: "bucket", @@ -139,13 +140,13 @@ class AWSS3AdapterTests: XCTestCase { createMultipartUploadExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [createMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: createMultipartUpload is invoked and the s3 client returns an invalid response /// Then: A .failure result is returned with an .uknown error - func testCreateMultipartUpload_withWrongResponse_shouldFail() { + func testCreateMultipartUpload_withWrongResponse_shouldFail() async { let createMultipartUploadExpectation = expectation(description: "Create Multipart Upload") adapter.createMultipartUpload(.init(bucket: "bucket", key: "key")) { result in XCTAssertEqual(self.awsS3.createMultipartUploadCount, 1) @@ -158,13 +159,13 @@ class AWSS3AdapterTests: XCTestCase { createMultipartUploadExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [createMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: createMultipartUpload is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testCreateMultipartUpload_withError_shouldFail() { + func testCreateMultipartUpload_withError_shouldFail() async { let createMultipartUploadExpectation = expectation(description: "Create Multipart Upload") awsS3.createMultipartUploadResult = .failure(StorageError.accessDenied("AccessDenied", "", nil)) adapter.createMultipartUpload(.init(bucket: "bucket", key: "key")) { result in @@ -177,14 +178,13 @@ class AWSS3AdapterTests: XCTestCase { XCTAssertEqual(description, "AccessDenied") createMultipartUploadExpectation.fulfill() } - - waitForExpectations(timeout: 1) + await fulfillment(of: [createMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: listParts is invoked and the s3 client returns a valid response /// Then: A .success result is returned containing the corresponding parsed response - func testListParts_withSuccess_shouldSucceed() { + func testListParts_withSuccess_shouldSucceed() async { let listPartsExpectation = expectation(description: "List Parts") awsS3.listPartsResult = .success(.init( bucket: "bucket", @@ -208,13 +208,13 @@ class AWSS3AdapterTests: XCTestCase { listPartsExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [listPartsExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: listParts is invoked and the s3 client returns an invalid response /// Then: A .failure result is returned with an .unknown error - func testListParts_withWrongResponse_shouldFail() { + func testListParts_withWrongResponse_shouldFail() async { let listPartsExpectation = expectation(description: "List Parts") adapter.listParts(bucket: "bucket", key: "key", uploadId: "uploadId") { result in XCTAssertEqual(self.awsS3.listPartsCount, 1) @@ -227,13 +227,13 @@ class AWSS3AdapterTests: XCTestCase { listPartsExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [listPartsExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: listParts is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testListParts_withError_shouldFail() { + func testListParts_withError_shouldFail() async { let listPartsExpectation = expectation(description: "List Parts") awsS3.listPartsResult = .failure(StorageError.authError("AuthError", "", nil)) adapter.listParts(bucket: "bucket", key: "key", uploadId: "uploadId") { result in @@ -247,13 +247,13 @@ class AWSS3AdapterTests: XCTestCase { listPartsExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [listPartsExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: completeMultipartUpload is invoked and the s3 client returns a valid response /// Then: A .success result is returned containing the corresponding parsed response - func testCompleteMultipartUpload_withSuccess_shouldSucceed() { + func testCompleteMultipartUpload_withSuccess_shouldSucceed() async { let completeMultipartUploadExpectation = expectation(description: "Complete Multipart Upload") awsS3.completeMultipartUploadResult = .success(.init( eTag: "eTag" @@ -275,13 +275,13 @@ class AWSS3AdapterTests: XCTestCase { completeMultipartUploadExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [completeMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: completeMultipartUpload is invoked and the s3 client returns an invalid response /// Then: A .failure result is returned with .unknown error - func testCompleteMultipartUpload_withWrongResponse_shouldFail() { + func testCompleteMultipartUpload_withWrongResponse_shouldFail() async { let completeMultipartUploadExpectation = expectation(description: "Complete Multipart Upload") adapter.completeMultipartUpload(.init(bucket: "bucket", key: "key", uploadId: "uploadId", parts: [])) { result in XCTAssertEqual(self.awsS3.completeMultipartUploadCount, 1) @@ -294,13 +294,13 @@ class AWSS3AdapterTests: XCTestCase { completeMultipartUploadExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [completeMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: completeMultipartUpload is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testCompleteMultipartUpload_withError_shouldFail() { + func testCompleteMultipartUpload_withError_shouldFail() async { let completeMultipartUploadExpectation = expectation(description: "Complete Multipart Upload") awsS3.completeMultipartUploadResult = .failure(StorageError.authError("AuthError", "", nil)) adapter.completeMultipartUpload(.init(bucket: "bucket", key: "key", uploadId: "uploadId", parts: [])) { result in @@ -314,13 +314,13 @@ class AWSS3AdapterTests: XCTestCase { completeMultipartUploadExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [completeMultipartUploadExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: abortMultipartUpload is invoked and the s3 client returns a valid response /// Then: A .success result is returned - func testAbortMultipartUpload_withSuccess_shouldSucceed() { + func testAbortMultipartUpload_withSuccess_shouldSucceed() async { let abortExpectation = expectation(description: "Abort Multipart Upload") adapter.abortMultipartUpload(.init(bucket: "bucket", key: "key", uploadId: "uploadId")) { result in XCTAssertEqual(self.awsS3.abortMultipartUploadCount, 1) @@ -331,13 +331,13 @@ class AWSS3AdapterTests: XCTestCase { abortExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [abortExpectation], timeout: 1) } /// Given: An AWSS3Adapter /// When: abortMultipartUpload is invoked and the s3 client returns an error /// Then: A .failure result is returned - func testAbortMultipartUpload_withError_shouldFail() { + func testAbortMultipartUpload_withError_shouldFail() async { let abortExpectation = expectation(description: "Abort Multipart Upload") awsS3.abortMultipartUploadResult = .failure(StorageError.keyNotFound("InvalidKey", "", "", nil)) adapter.abortMultipartUpload(.init(bucket: "bucket", key: "key", uploadId: "uploadId")) { result in @@ -350,7 +350,7 @@ class AWSS3AdapterTests: XCTestCase { XCTAssertEqual(key, "InvalidKey") abortExpectation.fulfill() } - waitForExpectations(timeout: 1) + await fulfillment(of: [abortExpectation], timeout: 1) } /// Given: An AWSS3Adapter diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageDownloadFileOperationTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageDownloadFileOperationTests.swift index 9b1b6b6d65..ca5bfec81c 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageDownloadFileOperationTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageDownloadFileOperationTests.swift @@ -16,7 +16,12 @@ import AWSS3 class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { - func testDownloadFileOperationValidationError() { + private let livenessServiceDispatchQueue = DispatchQueue( + label: "com.amazon.aws.amplify.liveness.service", + target: .global() + ) + + func testDownloadFileOperationValidationError() async { let request = StorageDownloadFileRequest(key: "", local: testURL, options: StorageDownloadFileRequest.Options()) @@ -39,7 +44,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } @@ -72,7 +77,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { XCTAssertTrue(operation.isFinished) } - func testDownloadFileOperationDownloadLocal() { + func testDownloadFileOperationDownloadLocal() async { let task = StorageTransferTask(transferType: .download(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceDownloadEvents = [ StorageEvent.initiated(StorageTaskReference(task)), @@ -103,12 +108,12 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) mockStorageService.verifyDownload(serviceKey: expectedServiceKey, fileURL: url) } - func testDownloadFileOperationDownloadLocalFailed() { + func testDownloadFileOperationDownloadLocalFailed() async { let task = StorageTransferTask(transferType: .download(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceDownloadEvents = [ StorageEvent.initiated(StorageTaskReference(task)), @@ -139,7 +144,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) mockStorageService.verifyDownload(serviceKey: expectedServiceKey, fileURL: url) } @@ -185,7 +190,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { /// Given: Storage Download File Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testDownloadFileOperationStringStoragePathValidationError() { + func testDownloadFileOperationStringStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return "/my/path" }) let request = StorageDownloadFileRequest(path: path, local: testURL, @@ -210,14 +215,14 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download File Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testDownloadFileOperationEmptyStoragePathValidationError() { + func testDownloadFileOperationEmptyStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return " " }) let request = StorageDownloadFileRequest(path: path, local: testURL, @@ -242,14 +247,14 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download File Operation /// When: The operation is executed with a request that has an invalid IdentityIDStoragePath /// Then: The operation will fail with a validation error - func testDownloadFileOperationIdentityIDStoragePathValidationError() { + func testDownloadFileOperationIdentityIDStoragePathValidationError() async { let path = IdentityIDStoragePath(resolve: { _ in return "/my/path" }) let request = StorageDownloadFileRequest(path: path, local: testURL, @@ -274,14 +279,14 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download File Operation /// When: The operation is executed with a request that has an a custom implementation of StoragePath /// Then: The operation will fail with a validation error - func testDownloadFileOperationCustomStoragePathValidationError() { + func testDownloadFileOperationCustomStoragePathValidationError() async { let path = InvalidCustomStoragePath(resolve: { _ in return "my/path" }) let request = StorageDownloadFileRequest(path: path, local: testURL, @@ -306,7 +311,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } @@ -344,7 +349,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) mockStorageService.verifyDownload(serviceKey: "public/\(self.testKey)", fileURL: url) } @@ -384,7 +389,7 @@ class AWSS3StorageDownloadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) mockStorageService.verifyDownload(serviceKey: "public/\(testIdentityId)/\(self.testKey)", fileURL: url) } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageGetDataOperationTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageGetDataOperationTests.swift index 6a7c7a5485..3a687b774f 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageGetDataOperationTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageGetDataOperationTests.swift @@ -16,7 +16,7 @@ import AWSS3 class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { - func testDownloadDataOperationValidationError() { + func testDownloadDataOperationValidationError() async { let request = StorageDownloadDataRequest(key: "", options: StorageDownloadDataRequest.Options()) let failedInvoked = expectation(description: "failed was invoked on operation") let operation = AWSS3StorageDownloadDataOperation(request, @@ -37,7 +37,7 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } @@ -177,7 +177,7 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { /// Given: Storage Download Data Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testDownloadDataOperationStringStoragePathValidationError() { + func testDownloadDataOperationStringStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return "/my/path" }) let request = StorageDownloadDataRequest(path: path, options: StorageDownloadDataRequest.Options()) let failedInvoked = expectation(description: "failed was invoked on operation") @@ -200,14 +200,14 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download Data Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testDownloadDataOperationEmptyStoragePathValidationError() { + func testDownloadDataOperationEmptyStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return " " }) let request = StorageDownloadDataRequest(path: path, options: StorageDownloadDataRequest.Options()) let failedInvoked = expectation(description: "failed was invoked on operation") @@ -230,14 +230,14 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download Data Operation /// When: The operation is executed with a request that has an invalid IdentityIDStoragePath /// Then: The operation will fail with a validation error - func testDownloadDataOperationIdentityIdStoragePathValidationError() { + func testDownloadDataOperationIdentityIdStoragePathValidationError() async { let path = IdentityIDStoragePath(resolve: { _ in return "/my/path" }) let request = StorageDownloadDataRequest(path: path, options: StorageDownloadDataRequest.Options()) let failedInvoked = expectation(description: "failed was invoked on operation") @@ -259,14 +259,14 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download Data Operation /// When: The operation is executed with a request that has an a custom implementation of StoragePath /// Then: The operation will fail with a validation error - func testDownloadDataOperationCustomStoragePathValidationError() { + func testDownloadDataOperationCustomStoragePathValidationError() async { let path = InvalidCustomStoragePath(resolve: { _ in return "my/path" }) let request = StorageDownloadDataRequest(path: path, options: StorageDownloadDataRequest.Options()) let failedInvoked = expectation(description: "failed was invoked on operation") @@ -288,7 +288,7 @@ class AWSS3StorageDownloadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StoragePutDataOperationTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StoragePutDataOperationTests.swift index 5934e419d3..44eb8e29f1 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StoragePutDataOperationTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StoragePutDataOperationTests.swift @@ -16,7 +16,7 @@ import AWSS3 class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { - func testUploadDataOperationValidationError() { + func testUploadDataOperationValidationError() async { let options = StorageUploadDataRequest.Options(accessLevel: .protected) let request = StorageUploadDataRequest(key: "", data: testData, options: options) @@ -40,11 +40,11 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } - func testUploadDataOperationGetIdentityIdError() { + func testUploadDataOperationGetIdentityIdError() async { mockAuthService.getIdentityIdError = AuthError.service("", "", "") let options = StorageUploadDataRequest.Options(accessLevel: .protected) @@ -70,11 +70,11 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } - func testUploadDataOperationUploadSuccess() { + func testUploadDataOperationUploadSuccess() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceUploadEvents = [ @@ -111,7 +111,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: expectedServiceKey, @@ -121,7 +121,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { metadata: metadata) } - func testUploadDataOperationUploadFail() { + func testUploadDataOperationUploadFail() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceUploadEvents = [ @@ -155,7 +155,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: expectedServiceKey, @@ -165,7 +165,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { metadata: nil) } - func testUploadDataOperationMultiPartUploadSuccess() { + func testUploadDataOperationMultiPartUploadSuccess() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .multiPartUpload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceMultiPartUploadEvents = [ @@ -209,7 +209,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.multiPartUploadCalled, 1) mockStorageService.verifyMultiPartUpload(serviceKey: expectedServiceKey, @@ -222,7 +222,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { /// Given: Storage Upload Data Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testUploadDataOperationStringStoragePathValidationError() { + func testUploadDataOperationStringStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return "/my/path" }) let failedInvoked = expectation(description: "failed was invoked on operation") let options = StorageUploadDataRequest.Options(accessLevel: .protected) @@ -246,14 +246,14 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Upload Data Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testUploadDataOperationEmptyStoragePathValidationError() { + func testUploadDataOperationEmptyStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return " " }) let failedInvoked = expectation(description: "failed was invoked on operation") let options = StorageUploadDataRequest.Options(accessLevel: .protected) @@ -277,14 +277,14 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Upload Data Operation /// When: The operation is executed with a request that has an invalid IdentityIDStoragePath /// Then: The operation will fail with a validation error - func testUploadDataOperationIdentityIDStoragePathValidationError() { + func testUploadDataOperationIdentityIDStoragePathValidationError() async { let path = IdentityIDStoragePath(resolve: { _ in return "/my/path" }) let failedInvoked = expectation(description: "failed was invoked on operation") let options = StorageUploadDataRequest.Options(accessLevel: .protected) @@ -308,14 +308,14 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Upload Data Operation /// When: The operation is executed with a request that has an a custom implementation of StoragePath /// Then: The operation will fail with a validation error - func testUploadDataOperationCustomStoragePathValidationError() { + func testUploadDataOperationCustomStoragePathValidationError() async { let path = InvalidCustomStoragePath(resolve: { _ in return "my/path" }) let failedInvoked = expectation(description: "failed was invoked on operation") let options = StorageUploadDataRequest.Options(accessLevel: .protected) @@ -339,7 +339,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } @@ -382,7 +382,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: "public/\(self.testKey)", @@ -431,7 +431,7 @@ class AWSS3StorageUploadDataOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: "public/\(testIdentityId)/\(testKey)", diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageRemoveOperationTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageRemoveOperationTests.swift index 5369bc68d4..c36e1b0710 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageRemoveOperationTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageRemoveOperationTests.swift @@ -14,7 +14,7 @@ import XCTest class AWSS3StorageRemoveOperationTests: AWSS3StorageOperationTestBase { - func testRemoveOperationValidationError() { + func testRemoveOperationValidationError() async { let options = StorageRemoveRequest.Options() let request = StorageRemoveRequest(key: "", options: options) @@ -38,7 +38,7 @@ class AWSS3StorageRemoveOperationTests: AWSS3StorageOperationTestBase { operation.start() XCTAssertTrue(operation.isFinished) - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) } func testRemoveOperationGetIdentityIdError() async throws { diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageUploadFileOperationTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageUploadFileOperationTests.swift index 12374173bb..971ad72d80 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageUploadFileOperationTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Operation/AWSS3StorageUploadFileOperationTests.swift @@ -16,7 +16,7 @@ import AWSS3 class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { - func testUploadFileOperationValidationError() { + func testUploadFileOperationValidationError() async { let options = StorageUploadFileRequest.Options(accessLevel: .protected) let request = StorageUploadFileRequest(key: "", local: testURL, options: options) @@ -40,11 +40,11 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } - func testUploadFileOperationGetIdentityIdError() { + func testUploadFileOperationGetIdentityIdError() async { mockAuthService.getIdentityIdError = AuthError.service("", "", "") let filePath = NSTemporaryDirectory() + UUID().uuidString + ".tmp" let fileURL = URL(fileURLWithPath: filePath) @@ -72,11 +72,11 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } - func testvOperationGetSizeForMissingFileError() { + func testvOperationGetSizeForMissingFileError() async { let url = URL(fileURLWithPath: "missingFile") let options = StorageUploadFileRequest.Options(accessLevel: .protected) let request = StorageUploadFileRequest(key: testKey, local: url, options: options) @@ -101,11 +101,11 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } - func testUploadFileOperationUploadSuccess() { + func testUploadFileOperationUploadSuccess() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceUploadEvents = [ @@ -145,7 +145,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: expectedServiceKey, @@ -155,7 +155,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { metadata: metadata) } - func testUploadFileOperationUploadFail() { + func testUploadFileOperationUploadFail() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceUploadEvents = [ @@ -192,7 +192,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: expectedServiceKey, @@ -202,7 +202,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { metadata: nil) } - func testUploadFileOperationMultiPartUploadSuccess() { + func testUploadFileOperationMultiPartUploadSuccess() async { mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .multiPartUpload(onEvent: { _ in }), bucket: "bucket", key: "key") mockStorageService.storageServiceMultiPartUploadEvents = [ @@ -245,7 +245,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.multiPartUploadCalled, 1) mockStorageService.verifyMultiPartUpload(serviceKey: expectedServiceKey, @@ -258,7 +258,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { /// Given: Storage Upload File Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testUploadFileOperationStringStoragePathValidationError() { + func testUploadFileOperationStringStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return "/my/path" }) mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") @@ -297,14 +297,14 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Upload File Operation /// When: The operation is executed with a request that has an invalid StringStoragePath /// Then: The operation will fail with a validation error - func testUploadFileOperationEmptyStoragePathValidationError() { + func testUploadFileOperationEmptyStoragePathValidationError() async { let path = StringStoragePath(resolve: { _ in return " " }) mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") @@ -343,14 +343,14 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Upload File Operation /// When: The operation is executed with a request that has an invalid IdentityIDStoragePath /// Then: The operation will fail with a validation error - func testUploadFileOperationIdentityIDStoragePathValidationError() { + func testUploadFileOperationIdentityIDStoragePathValidationError() async { let path = IdentityIDStoragePath(resolve: { _ in return "/my/path" }) mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") @@ -389,14 +389,14 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } /// Given: Storage Download File Operation /// When: The operation is executed with a request that has an a custom implementation of StoragePath /// Then: The operation will fail with a validation error - func testUploadFileOperationCustomStoragePathValidationError() { + func testUploadFileOperationCustomStoragePathValidationError() async { let path = InvalidCustomStoragePath(resolve: { _ in return "my/path" }) mockAuthService.identityId = testIdentityId let task = StorageTransferTask(transferType: .upload(onEvent: { _ in }), bucket: "bucket", key: "key") @@ -435,7 +435,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { } operation.start() - waitForExpectations(timeout: 1) + await fulfillment(of: [failedInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) } @@ -482,7 +482,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: "public/\(testKey)", @@ -534,7 +534,7 @@ class AWSS3StorageUploadFileOperationTests: AWSS3StorageOperationTestBase { operation.start() - await waitForExpectations(timeout: 1) + await fulfillment(of: [completeInvoked, inProcessInvoked], timeout: 1) XCTAssertTrue(operation.isFinished) XCTAssertEqual(mockStorageService.uploadCalled, 1) mockStorageService.verifyUpload(serviceKey: "public/\(testIdentityId)/\(testKey)", diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Service/Storage/AWSS3StorageServiceTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Service/Storage/AWSS3StorageServiceTests.swift index 470ab13c7c..a829dce219 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Service/Storage/AWSS3StorageServiceTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Service/Storage/AWSS3StorageServiceTests.swift @@ -88,7 +88,7 @@ class AWSS3StorageServiceTests: XCTestCase { /// Given: An AWSS3StorageService /// When: attachEventHandlers is invoked and a .completed event is sent /// Then: A .completed event is dispatched to the event handler - func testAttachEventHandlers() { + func testAttachEventHandlers() async { let expectation = self.expectation(description: "Attach Event Handlers") service.attachEventHandlers( onUpload: { event in @@ -101,7 +101,7 @@ class AWSS3StorageServiceTests: XCTestCase { ) XCTAssertNotNil(database.onUploadHandler) database.onUploadHandler?(.completed(())) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: An AWSS3StorageService @@ -221,7 +221,7 @@ class AWSS3StorageServiceTests: XCTestCase { /// Given: An AWSS3StorageService with a non-completed download task /// When: completeDownload is invoked for the identifier matching the task /// Then: The task is marked as completed and a .completed event is dispatched - func testCompleteDownload_shouldReturnData() { + func testCompleteDownload_shouldReturnData() async { let expectation = self.expectation(description: "Complete Download") let downloadTask = StorageTransferTask( @@ -247,7 +247,7 @@ class AWSS3StorageServiceTests: XCTestCase { service.completeDownload(taskIdentifier: 1, sourceURL: sourceUrl) XCTAssertEqual(downloadTask.status, .completed) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: An AWSS3StorageService with a non-completed download task that sets a location @@ -308,7 +308,7 @@ class AWSS3StorageServiceTests: XCTestCase { /// Given: An AWSS3StorageService with a non-completed upload task that sets a location /// When: completeDownload is invoked for the identifier matching the task /// Then: The task status is not updated and an .upload event is not dispatched - func testCompleteDownload_withNoDownload_shouldDoNothing() { + func testCompleteDownload_withNoDownload_shouldDoNothing() async { let expectation = self.expectation(description: "Complete Download") expectation.isInverted = true @@ -331,13 +331,13 @@ class AWSS3StorageServiceTests: XCTestCase { service.completeDownload(taskIdentifier: 1, sourceURL: sourceUrl) XCTAssertNotEqual(uploadTask.status, .completed) XCTAssertNotEqual(uploadTask.status, .error) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: An AWSS3StorageService that cannot create a pre signed url /// When: upload is invoked /// Then: A .failed event is dispatched with an .unknown error - func testUpload_withoutPreSignedURL_shouldSendFailEvent() { + func testUpload_withoutPreSignedURL_shouldSendFailEvent() async { let data = Data("someData".utf8) let expectation = self.expectation(description: "Upload") service.upload( @@ -357,13 +357,13 @@ class AWSS3StorageServiceTests: XCTestCase { } ) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: An AWSS3StorageService that can create a pre signed url /// When: upload is invoked /// Then: An .initiated event is dispatched - func testUpload_withPreSignedURL_shouldSendInitiatedEvent() { + func testUpload_withPreSignedURL_shouldSendInitiatedEvent() async { let data = Data("someData".utf8) let expectation = self.expectation(description: "Upload") service.preSignedURLBuilder = MockAWSS3PreSignedURLBuilder() @@ -374,15 +374,13 @@ class AWSS3StorageServiceTests: XCTestCase { metadata: [:], accelerate: true, onEvent: { event in - guard case .initiated(_) = event else { - XCTFail("Expected .initiated event, got \(event)") - return + if case .initiated(_) = event { + expectation.fulfill() } - expectation.fulfill() } ) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageMultipartUploadClientTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageMultipartUploadClientTests.swift index 561543f57d..e1d31fcbea 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageMultipartUploadClientTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageMultipartUploadClientTests.swift @@ -62,7 +62,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: createMultipartUpload is invoked and AWSS3Behavior returns .success /// Then: A .created event is reported to the session and the session is registered - func testCreateMultipartUpload_withSuccess_shouldSucceed() throws { + func testCreateMultipartUpload_withSuccess_shouldSucceed() async throws { awss3Behavior.createMultipartUploadExpectation = expectation(description: "Create Multipart Upload") awss3Behavior.createMultipartUploadResult = .success(.init( bucket: "bucket", @@ -71,7 +71,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { )) try client.createMultipartUpload() - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.createMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.createMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 2) XCTAssertEqual(session.failCount, 0) @@ -85,12 +85,12 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: createMultipartUpload is invoked and AWSS3Behavior returns .failure /// Then: An .unknown error is reported to the session and the session is not registered - func testCreateMultipartUpload_withError_shouldFail() throws { + func testCreateMultipartUpload_withError_shouldFail() async throws { awss3Behavior.createMultipartUploadExpectation = expectation(description: "Create Multipart Upload") awss3Behavior.createMultipartUploadResult = .failure(.unknown("Unknown Error", nil)) try client.createMultipartUpload() - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.createMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.createMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 1) XCTAssertEqual(session.failCount, 1) @@ -113,7 +113,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: uploadPart is invoked with valid parts /// Then: A .started event is reported to the session - func testUploadPart_withParts_shouldSucceed() throws { + func testUploadPart_withParts_shouldSucceed() async throws { session.handleUploadPartExpectation = expectation(description: "Upload Part with parts") try client.uploadPart( @@ -134,7 +134,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { ) ) - waitForExpectations(timeout: 1) + await fulfillment(of: [session.handleUploadPartExpectation!], timeout: 1) XCTAssertEqual(session.handleUploadPartCount, 1) XCTAssertEqual(session.failCount, 0) if case .started(let partNumber, _) = try XCTUnwrap(session.lastUploadEvent) { @@ -145,7 +145,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: uploadPart is invoked with a non-existing file /// Then: An error is reported to the session - func testUploadPart_withInvalidFile_shouldFail() throws { + func testUploadPart_withInvalidFile_shouldFail() async throws { session.failExpectation = expectation(description: "Upload Part with invalid file") try client.uploadPart( @@ -169,7 +169,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { ) ) - waitForExpectations(timeout: 1) + await fulfillment(of: [session.failExpectation!], timeout: 1) XCTAssertEqual(session.handleUploadPartCount, 0) XCTAssertEqual(session.failCount, 1) XCTAssertNil(session.lastUploadEvent) @@ -225,7 +225,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: completeMultipartUpload is invoked and AWSS3Behaviour returns succees /// Then: A .completed event is reported to the session and the session is unregistered - func testCompleteMultipartUpload_withSuccess_shouldSucceed() throws { + func testCompleteMultipartUpload_withSuccess_shouldSucceed() async throws { awss3Behavior.completeMultipartUploadExpectation = expectation(description: "Complete Multipart Upload") awss3Behavior.completeMultipartUploadResult = .success(.init( bucket: "bucket", @@ -234,7 +234,7 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { )) try client.completeMultipartUpload(uploadId: "uploadId") - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.completeMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.completeMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 1) XCTAssertEqual(session.failCount, 0) @@ -247,12 +247,12 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: completeMultipartUpload is invoked and AWSS3Behaviour returns failure /// Then: A .unknown error is reported to the session and the session is not unregistered - func testCompleteMultipartUpload_withError_shouldFail() throws { + func testCompleteMultipartUpload_withError_shouldFail() async throws { awss3Behavior.completeMultipartUploadExpectation = expectation(description: "Complete Multipart Upload") awss3Behavior.completeMultipartUploadResult = .failure(.unknown("Unknown Error", nil)) try client.completeMultipartUpload(uploadId: "uploadId") - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.completeMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.completeMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 0) XCTAssertEqual(session.failCount, 1) @@ -275,12 +275,12 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: abortMultipartUpload is invoked and AWSS3Behaviour returns success /// Then: An .aborted event is reported to the session and the session is unregistered - func testAbortMultipartUpload_withSuccess_shouldSucceed() throws { + func testAbortMultipartUpload_withSuccess_shouldSucceed() async throws { awss3Behavior.abortMultipartUploadExpectation = expectation(description: "Abort Multipart Upload") awss3Behavior.abortMultipartUploadResult = .success(()) try client.abortMultipartUpload(uploadId: "uploadId", error: CancellationError()) - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.abortMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.abortMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 1) XCTAssertEqual(session.failCount, 0) @@ -294,12 +294,12 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: abortMultipartUpload is invoked and AWSS3Behaviour returns failure /// Then: A .unknown error is reported to the session and the session is not unregistered - func testAbortMultipartUpload_withError_shouldFail() throws { + func testAbortMultipartUpload_withError_shouldFail() async throws { awss3Behavior.abortMultipartUploadExpectation = expectation(description: "Abort Multipart Upload") awss3Behavior.abortMultipartUploadResult = .failure(.unknown("Unknown Error", nil)) try client.abortMultipartUpload(uploadId: "uploadId") - waitForExpectations(timeout: 1) + await fulfillment(of: [awss3Behavior.abortMultipartUploadExpectation!], timeout: 1) XCTAssertEqual(awss3Behavior.abortMultipartUploadCount, 1) XCTAssertEqual(session.handleMultipartUploadCount, 0) XCTAssertEqual(session.failCount, 1) @@ -322,13 +322,13 @@ class DefaultStorageMultipartUploadClientTests: XCTestCase { /// Given: a DefaultStorageMultipartUploadClient /// When: cancelUploadTasks is invoked with identifiers /// Then: The tasks are unregistered - func testCancelUploadTasks_shouldSucceed() throws { + func testCancelUploadTasks_shouldSucceed() async throws { let cancelExpectation = expectation(description: "Cancel Upload Tasks") client.cancelUploadTasks(taskIdentifiers: [0, 1,2], done: { cancelExpectation.fulfill() }) - waitForExpectations(timeout: 1) + await fulfillment(of: [cancelExpectation], timeout: 1) XCTAssertEqual(serviceProxy.unregisterTaskIdentifiersCount, 1) } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageTransferDatabaseTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageTransferDatabaseTests.swift index 1a3722c373..cce7df5f2a 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageTransferDatabaseTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/DefaultStorageTransferDatabaseTests.swift @@ -204,7 +204,7 @@ class DefaultStorageTransferDatabaseTests: XCTestCase { /// Given: A DefaultStorageTransferDatabase /// When: recover is invoked with a StorageURLSession that returns a session /// Then: A .success is returned - func testLoadPersistableTasks() { + func testLoadPersistableTasks() async { let urlSession = MockStorageURLSession( sessionTasks: [ session @@ -217,18 +217,18 @@ class DefaultStorageTransferDatabaseTests: XCTestCase { } expectation.fulfill() } - waitForExpectations(timeout: 5) + await fulfillment(of: [expectation], timeout: 5) } /// Given: A DefaultStorageTransferDatabase /// When: prepareForBackground is invoked /// Then: A callback is invoked - func testPrepareForBackground() { + func testPrepareForBackground() async { let expectation = self.expectation(description: "Prepare for Background") database.prepareForBackground() { expectation.fulfill() } - waitForExpectations(timeout: 5) + await fulfillment(of: [expectation], timeout: 5) } /// Given: The StorageTransferDatabase Type diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageServiceSessionDelegateTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageServiceSessionDelegateTests.swift index ad4ffbd8d2..700ffb8f98 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageServiceSessionDelegateTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageServiceSessionDelegateTests.swift @@ -135,7 +135,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { /// Given: A StorageServiceSessionDelegate and a StorageTransferTask with a NSError with a NSURLErrorCancelled reason /// When: didComplete is invoked /// Then: The task is not unregistered - func testDidComplete_withNSURLErrorCancelled_shouldNotCompleteTask() { + func testDidComplete_withNSURLErrorCancelled_shouldNotCompleteTask() async { let task = URLSession.shared.dataTask(with: FileManager.default.temporaryDirectory) let reasons = [ NSURLErrorCancelledReasonBackgroundUpdatesDisabled, @@ -164,7 +164,9 @@ class StorageServiceSessionDelegateTests: XCTestCase { ) delegate.urlSession(.shared, task: task, didCompleteWithError: error) - waitForExpectations(timeout: 5) + + await fulfillment(of: [expectation], timeout: 5) + XCTAssertEqual(storageTask.status, .unknown) XCTAssertEqual(service.unregisterCount, 0) } @@ -173,7 +175,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { /// Given: A StorageServiceSessionDelegate and a StorageTransferTask with a StorageError /// When: didComplete is invoked /// Then: The task status is set to error and it's unregistered - func testDidComplete_withError_shouldFailTask() { + func testDidComplete_withError_shouldFailTask() async { let task = URLSession.shared.dataTask(with: FileManager.default.temporaryDirectory) let expectation = self.expectation(description: "Did Complete With Error") let storageTask = StorageTransferTask( @@ -186,7 +188,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { service.mockedTask = storageTask delegate.urlSession(.shared, task: task, didCompleteWithError: StorageError.accessDenied("", "", nil)) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) XCTAssertEqual(storageTask.status, .error) XCTAssertEqual(service.unregisterCount, 1) } @@ -194,7 +196,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { /// Given: A StorageServiceSessionDelegate and a StorageTransferTask of type .upload /// When: didSendBodyData is invoked /// Then: An .inProcess event is reported, with the corresponding values - func testDidSendBodyData_upload_shouldSendInProcessEvent() { + func testDidSendBodyData_upload_shouldSendInProcessEvent() async { let task = URLSession.shared.dataTask(with: FileManager.default.temporaryDirectory) let expectation = self.expectation(description: "Did Send Body Data") let storageTask = StorageTransferTask( @@ -220,7 +222,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { totalBytesExpectedToSend: 120 ) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: A StorageServiceSessionDelegate and a StorageTransferTask of type .multiPartUploadPart @@ -266,7 +268,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { /// Given: A StorageServiceSessionDelegate and a StorageTransferTask of type .download /// When: didWriteData is invoked /// Then: An .inProcess event is reported, with the corresponding values - func testDidWriteData_shouldNotifyProgress() { + func testDidWriteData_shouldNotifyProgress() async { let task = URLSession.shared.downloadTask(with: FileManager.default.temporaryDirectory) let expectation = self.expectation(description: "Did Write Data") let storageTask = StorageTransferTask( @@ -292,13 +294,13 @@ class StorageServiceSessionDelegateTests: XCTestCase { totalBytesExpectedToWrite: 300 ) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) } /// Given: A StorageServiceSessionDelegate and a URLSessionDownloadTask without a httpResponse /// When: didFinishDownloadingTo is invoked /// Then: No event is reported and the task is not completed - func testDiFinishDownloading_withError_shouldNotCompleteDownload() { + func testDiFinishDownloading_withError_shouldNotCompleteDownload() async { let task = URLSession.shared.downloadTask(with: FileManager.default.temporaryDirectory) let expectation = self.expectation(description: "Did Finish Downloading") expectation.isInverted = true @@ -317,7 +319,7 @@ class StorageServiceSessionDelegateTests: XCTestCase { didFinishDownloadingTo: FileManager.default.temporaryDirectory ) - waitForExpectations(timeout: 1) + await fulfillment(of: [expectation], timeout: 1) XCTAssertEqual(service.completeDownloadCount, 0) } } diff --git a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageTransferTaskTests.swift b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageTransferTaskTests.swift index 0f47e20249..45529f59a0 100644 --- a/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageTransferTaskTests.swift +++ b/AmplifyPlugins/Storage/Tests/AWSS3StoragePluginTests/Support/Internal/StorageTransferTaskTests.swift @@ -15,7 +15,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask with a sessionTask /// When: resume is invoked /// Then: an .initiated event is reported and the task set to .inProgress - func testResume_withSessionTask_shouldCallResume_andReportInitiatedEvent() { + func testResume_withSessionTask_shouldCallResume_andReportInitiatedEvent() async { let expectation = expectation(description: ".initiated event received on resume with only sessionTask") let sessionTask = MockSessionTask() let task = createTask( @@ -32,8 +32,8 @@ class StorageTransferTaskTests: XCTestCase { XCTAssertEqual(task.status, .paused) task.resume() - waitForExpectations(timeout: 0.5) - + await fulfillment(of: [expectation], timeout: 0.5) + XCTAssertEqual(sessionTask.resumeCount, 1) XCTAssertEqual(task.status, .inProgress) } @@ -41,7 +41,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask with a proxyStorageTask /// When: resume is invoked /// Then: an .initiated event is reported and the task set to .inProgress - func testResume_withProxyStorageTask_shouldCallResume_andReportInitiatedEvent() { + func testResume_withProxyStorageTask_shouldCallResume_andReportInitiatedEvent() async { let expectation = expectation(description: ".initiated event received on resume with only proxyStorageTask") let sessionTask = MockSessionTask() let storageTask = MockStorageTask() @@ -60,8 +60,8 @@ class StorageTransferTaskTests: XCTestCase { XCTAssertEqual(task.status, .paused) task.resume() - waitForExpectations(timeout: 0.5) - + await fulfillment(of: [expectation], timeout: 0.5) + XCTAssertEqual(sessionTask.resumeCount, 0) XCTAssertEqual(storageTask.resumeCount, 1) XCTAssertEqual(task.status, .inProgress) @@ -70,7 +70,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask with a sessionTask and a proxyStorageTask /// When: resume is invoked /// Then: an .initiated event is reported and the task set to .inProgress - func testResume_withSessionTask_andProxyStorageTask_shouldCallResume_andReportInitiatedEvent() { + func testResume_withSessionTask_andProxyStorageTask_shouldCallResume_andReportInitiatedEvent() async { let expectation = expectation(description: ".initiated event received on resume with sessionTask and proxyStorageTask") let sessionTask = MockSessionTask() let storageTask = MockStorageTask() @@ -88,8 +88,8 @@ class StorageTransferTaskTests: XCTestCase { XCTAssertEqual(task.status, .paused) task.resume() - waitForExpectations(timeout: 0.5) - + await fulfillment(of: [expectation], timeout: 0.5) + XCTAssertEqual(sessionTask.resumeCount, 1) XCTAssertEqual(storageTask.resumeCount, 0) XCTAssertEqual(task.status, .inProgress) @@ -98,7 +98,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask without a sessionTask and without a proxyStorageTask /// When: resume is invoked /// Then: No event is reported and the task is not to .inProgress - func testResume_withoutSessionTask_withoutProxyStorateTask_shouldNotCallResume_andNotReportEvent() { + func testResume_withoutSessionTask_withoutProxyStorateTask_shouldNotCallResume_andNotReportEvent() async { let expectation = expectation(description: "no event is received on resume when no sessionTask nor proxyStorageTask") expectation.isInverted = true let sessionTask = MockSessionTask() @@ -114,8 +114,8 @@ class StorageTransferTaskTests: XCTestCase { XCTAssertEqual(task.status, .paused) task.resume() - waitForExpectations(timeout: 0.5) - + await fulfillment(of: [expectation], timeout: 0.5) + XCTAssertEqual(sessionTask.resumeCount, 0) XCTAssertEqual(task.status, .paused) } @@ -393,7 +393,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask /// When: fail is invoked /// Then: A .failed event is reported - func testFail_shouldReportFailEvent() { + func testFail_shouldReportFailEvent() async { let expectation = expectation(description: ".failed event received on fail") let task = createTask( transferType: .upload(onEvent: { event in @@ -408,7 +408,7 @@ class StorageTransferTaskTests: XCTestCase { ) task.fail(error: CancellationError()) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [expectation], timeout: 0.5) XCTAssertEqual(task.status, .error) XCTAssertTrue(task.isFailed) XCTAssertNil(task.proxyStorageTask) @@ -417,7 +417,7 @@ class StorageTransferTaskTests: XCTestCase { /// Given: A StorageTransferTask with status .failed /// When: fail is invoked /// Then: No event is reported - func testFail_withFailedTask_shouldNotReportEvent() { + func testFail_withFailedTask_shouldNotReportEvent() async { let expectation = expectation(description: "event received on fail for failed task") expectation.isInverted = true let task = createTask( @@ -434,7 +434,7 @@ class StorageTransferTaskTests: XCTestCase { XCTAssertEqual(task.status, .error) task.fail(error: CancellationError()) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [expectation], timeout: 0.5) XCTAssertNotNil(task.proxyStorageTask) } diff --git a/AmplifyTests/CategoryTests/API/APICategoryClientInterceptorTests.swift b/AmplifyTests/CategoryTests/API/APICategoryClientInterceptorTests.swift index 5b81079e29..b93078944b 100644 --- a/AmplifyTests/CategoryTests/API/APICategoryClientInterceptorTests.swift +++ b/AmplifyTests/CategoryTests/API/APICategoryClientInterceptorTests.swift @@ -25,7 +25,7 @@ class APICategoryClientInterceptorTests: XCTestCase { mockAmplifyConfig = AmplifyConfiguration(api: apiConfig) } - func testAddInterceptor() throws { + func testAddInterceptor() async throws { let plugin = try makeAndAddMockPlugin() let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") plugin.listeners.append { message in @@ -37,7 +37,7 @@ class APICategoryClientInterceptorTests: XCTestCase { let interceptor = MockURLRequestInterceptor() _ = try Amplify.API.add(interceptor: interceptor, for: "apiName") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } // MARK: - Utilities diff --git a/AmplifyTests/CategoryTests/API/APICategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/API/APICategoryConfigurationTests.swift index 8b62beda65..56ea2b9c39 100644 --- a/AmplifyTests/CategoryTests/API/APICategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/API/APICategoryConfigurationTests.swift @@ -230,7 +230,7 @@ class APICategoryConfigurationTests: XCTestCase { ) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockAPICategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -258,7 +258,7 @@ class APICategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.API.getPlugin(for: "MockAPICategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } // TODO: this test is disabled for now since `catchBadInstruction` only takes in closure @@ -350,7 +350,7 @@ class APICategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -372,7 +372,7 @@ class APICategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test if adding a plugin after configuration throws an error diff --git a/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryClientAPITests.swift b/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryClientAPITests.swift index 603163c0b7..9e1d8c8044 100644 --- a/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryClientAPITests.swift +++ b/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryClientAPITests.swift @@ -34,7 +34,7 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } - func testIdentifyUser() throws { + func testIdentifyUser() async throws { let expectedMessage = "identifyUser(test)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -44,10 +44,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } analytics.identifyUser(userId: "test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testRecordWithString() throws { + func testRecordWithString() async throws { let expectedMessage = "record(eventWithName:test)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -56,10 +56,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.record(eventWithName: "test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testRecordWithEvent() throws { + func testRecordWithEvent() async throws { let event = BasicAnalyticsEvent(name: "test") let expectedMessage = "record(event:test)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") @@ -69,10 +69,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.record(event: event) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testRegisterGlobalProperties() throws { + func testRegisterGlobalProperties() async throws { let expectedMessage = "registerGlobalProperties" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -81,10 +81,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.registerGlobalProperties([:]) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testUnregisterGlobalProperties() throws { + func testUnregisterGlobalProperties() async throws { let expectedMessage = "unregisterGlobalProperties(_:)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -93,10 +93,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.unregisterGlobalProperties() - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testUnregisterGlobalPropertiesWithVariadicParameter() throws { + func testUnregisterGlobalPropertiesWithVariadicParameter() async throws { let expectedMessage = "unregisterGlobalProperties(_:)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -105,10 +105,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.unregisterGlobalProperties("one", "two") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testUnregisterGlobalPropertiesWithArrayParameter() throws { + func testUnregisterGlobalPropertiesWithArrayParameter() async throws { let expectedMessage = "unregisterGlobalProperties(_:)" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -118,10 +118,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } let properties: [String] = ["one", "two"] analytics.unregisterGlobalProperties(properties) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testFlushEvents() { + func testFlushEvents() async { let expectedMessage = "flushEvents()" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -130,10 +130,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.flushEvents() - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testDisable() { + func testDisable() async { let expectedMessage = "disable()" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -142,10 +142,10 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.disable() - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } - func testEnable() { + func testEnable() async { let expectedMessage = "enable()" let methodInvoked = expectation(description: "Expected method was invoked on plugin") plugin.listeners.append { message in @@ -154,6 +154,6 @@ class AnalyticsCategoryClientAPITests: XCTestCase { } } analytics.enable() - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvoked], timeout: 1) } } diff --git a/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryConfigurationTests.swift index a3a46e4312..b4eaef7b6b 100644 --- a/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Analytics/AnalyticsCategoryConfigurationTests.swift @@ -129,7 +129,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { XCTAssertNotNil(try Amplify.Analytics.getPlugin(for: "MockSecondAnalyticsCategoryPlugin")) } - func testCanUseDefaultPluginIfOnlyOnePlugin() throws { + func testCanUseDefaultPluginIfOnlyOnePlugin() async throws { let plugin = MockAnalyticsCategoryPlugin() let methodInvokedOnDefaultPlugin = expectation(description: "test method invoked on default plugin") plugin.listeners.append { message in @@ -147,7 +147,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { Amplify.Analytics.record(eventWithName: "test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvokedOnDefaultPlugin], timeout: 1) } func testPreconditionFailureInvokingWithMultiplePlugins() throws { @@ -173,7 +173,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { } } - func testCanUseSpecifiedPlugin() throws { + func testCanUseSpecifiedPlugin() async throws { let plugin1 = MockAnalyticsCategoryPlugin() let methodShouldNotBeInvokedOnDefaultPlugin = expectation(description: "test method should not be invoked on default plugin") @@ -206,10 +206,10 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Analytics.getPlugin(for: "MockSecondAnalyticsCategoryPlugin").record(eventWithName: "test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodShouldBeInvokedOnSecondPlugin, methodShouldNotBeInvokedOnDefaultPlugin], timeout: 1) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockAnalyticsCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -237,7 +237,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Analytics.getPlugin(for: "MockAnalyticsCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } func testPreconditionFailureInvokingBeforeConfig() throws { @@ -292,7 +292,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -314,7 +314,7 @@ class AnalyticsCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test if adding a plugin after configuration throws an error diff --git a/AmplifyTests/CategoryTests/Auth/AuthCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Auth/AuthCategoryConfigurationTests.swift index 5035213a5a..8cb62497d4 100644 --- a/AmplifyTests/CategoryTests/Auth/AuthCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Auth/AuthCategoryConfigurationTests.swift @@ -265,7 +265,7 @@ class AuthCategoryConfigurationTests: XCTestCase { /// - Then: /// - Should work without any error. /// - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockAuthCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -293,7 +293,7 @@ class AuthCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Auth.getPlugin(for: "MockAuthCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } /// Test if unconfigured plugin throws an error @@ -385,7 +385,7 @@ class AuthCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -407,7 +407,7 @@ class AuthCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test that Amplify throws an `AuthError` if it encounters a plugin without a key diff --git a/AmplifyTests/CategoryTests/DataStore/DataStoreCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/DataStore/DataStoreCategoryConfigurationTests.swift index 7333c2654b..18d4014d56 100644 --- a/AmplifyTests/CategoryTests/DataStore/DataStoreCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/DataStore/DataStoreCategoryConfigurationTests.swift @@ -239,7 +239,7 @@ class DataStoreCategoryConfigurationTests: XCTestCase { ) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockDataStoreCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -267,7 +267,7 @@ class DataStoreCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.DataStore.getPlugin(for: "MockDataStoreCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } // TODO: this test is disabled for now since `catchBadInstruction` only takes in closure @@ -326,7 +326,7 @@ class DataStoreCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -348,7 +348,7 @@ class DataStoreCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test if adding a plugin after configuration throws an error diff --git a/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift b/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift index 40efdd348c..35eb70b5b1 100644 --- a/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift +++ b/AmplifyTests/CategoryTests/DataStore/ModelFieldAssociationTests.swift @@ -28,7 +28,7 @@ class ModelFieldAssociationTests: XCTestCase { func testHasManyWithCodingKeys() { let hasMany = ModelAssociation.hasMany(associatedWith: Comment.keys.post) - guard case .hasMany(let fieldName, let targetNames) = hasMany else { + guard case .hasMany(let fieldName, _) = hasMany else { XCTFail("Should create hasMany association") return } diff --git a/AmplifyTests/CategoryTests/Geo/GeoCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Geo/GeoCategoryConfigurationTests.swift index 0540cb719e..75767a9689 100644 --- a/AmplifyTests/CategoryTests/Geo/GeoCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Geo/GeoCategoryConfigurationTests.swift @@ -188,7 +188,7 @@ class GeoCategoryConfigurationTests: XCTestCase { XCTAssertTrue(methodInvokedOnSecondPlugin) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockGeoCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -216,7 +216,7 @@ class GeoCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Geo.getPlugin(for: "MockGeoCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } func testPreconditionFailureInvokingBeforeConfig() async throws { @@ -271,7 +271,7 @@ class GeoCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -293,7 +293,7 @@ class GeoCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test if adding a plugin after configuration throws an error diff --git a/AmplifyTests/CategoryTests/Hub/DefaultPluginTests/DefaultHubPluginTests.swift b/AmplifyTests/CategoryTests/Hub/DefaultPluginTests/DefaultHubPluginTests.swift index e6a3bf08ab..bf8fc5394a 100644 --- a/AmplifyTests/CategoryTests/Hub/DefaultPluginTests/DefaultHubPluginTests.swift +++ b/AmplifyTests/CategoryTests/Hub/DefaultPluginTests/DefaultHubPluginTests.swift @@ -153,7 +153,7 @@ class DefaultHubPluginTests: XCTestCase { /// Given: The default Hub plugin /// When: I invoke listen() for a specified channel and subsequently dispatch a message to a different channel /// Then: My listener is not invoked - func testMessagesAreDeliveredOnlyToSpecifiedChannel() { + func testMessagesAreDeliveredOnlyToSpecifiedChannel() async { let messageShouldNotBeReceived = expectation(description: "Message should not be received") messageShouldNotBeReceived.isInverted = true _ = plugin.listen(to: .storage, isIncluded: nil) { hubPayload in @@ -164,7 +164,7 @@ class DefaultHubPluginTests: XCTestCase { messageShouldNotBeReceived.fulfill() } plugin.dispatch(to: .custom("DifferentChannel"), payload: HubPayload(eventName: "TEST_EVENT")) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [messageShouldNotBeReceived], timeout: 0.5) } } diff --git a/AmplifyTests/CategoryTests/Hub/HubCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Hub/HubCategoryConfigurationTests.swift index ffaddccf74..305cd1ef0e 100644 --- a/AmplifyTests/CategoryTests/Hub/HubCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Hub/HubCategoryConfigurationTests.swift @@ -174,7 +174,7 @@ class HubCategoryConfigurationTests: XCTestCase { } } - func testCanUseSpecifiedPlugin() throws { + func testCanUseSpecifiedPlugin() async throws { let plugin1 = MockHubCategoryPlugin() let methodShouldNotBeInvokedOnDefaultPlugin = expectation(description: "test method should not be invoked on default plugin") @@ -208,10 +208,10 @@ class HubCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) let unsubscribeToken = UnsubscribeToken(channel: .storage, id: UUID()) try Amplify.Hub.getPlugin(for: "MockSecondHubCategoryPlugin").removeListener(unsubscribeToken) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodShouldBeInvokedOnSecondPlugin, methodShouldNotBeInvokedOnDefaultPlugin], timeout: 1) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockHubCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -239,7 +239,7 @@ class HubCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Hub.getPlugin(for: "MockHubCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } func testPreconditionFailureInvokingBeforeConfig() throws { @@ -294,7 +294,7 @@ class HubCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -316,7 +316,7 @@ class HubCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } } diff --git a/AmplifyTests/CategoryTests/Hub/HubClientAPITests.swift b/AmplifyTests/CategoryTests/Hub/HubClientAPITests.swift index 8324258ff2..ffe39197f0 100644 --- a/AmplifyTests/CategoryTests/Hub/HubClientAPITests.swift +++ b/AmplifyTests/CategoryTests/Hub/HubClientAPITests.swift @@ -23,7 +23,7 @@ class HubClientAPITests: XCTestCase { mockAmplifyConfig = AmplifyConfiguration(hub: hubConfig) } - func testDispatch() throws { + func testDispatch() async throws { let plugin = try makeAndAddMockPlugin() let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") plugin.listeners.append { message in @@ -34,10 +34,10 @@ class HubClientAPITests: XCTestCase { Amplify.Hub.dispatch(to: .storage, payload: HubPayload(eventName: "")) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testListen() throws { + func testListen() async throws { let plugin = try makeAndAddMockPlugin() let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") plugin.listeners.append { message in @@ -47,10 +47,10 @@ class HubClientAPITests: XCTestCase { } _ = Amplify.Hub.listen(to: .storage) { _ in } - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testListenToEventName() throws { + func testListenToEventName() async throws { let plugin = try makeAndAddMockPlugin() let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") plugin.listeners.append { message in @@ -60,10 +60,10 @@ class HubClientAPITests: XCTestCase { } _ = Amplify.Hub.listen(to: .storage, eventName: "testEvent") { _ in } - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testRemove() throws { + func testRemove() async throws { let plugin = try makeAndAddMockPlugin() let methodWasInvokedOnPlugin = expectation(description: "method was invoked on plugin") plugin.listeners.append { message in @@ -73,7 +73,7 @@ class HubClientAPITests: XCTestCase { } let unsubscribeToken = UnsubscribeToken(channel: .storage, id: UUID()) Amplify.Hub.removeListener(unsubscribeToken) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } // MARK: - Utilities diff --git a/AmplifyTests/CategoryTests/Hub/HubCombineTests.swift b/AmplifyTests/CategoryTests/Hub/HubCombineTests.swift index a0af1796ae..4f3aedc3fb 100644 --- a/AmplifyTests/CategoryTests/Hub/HubCombineTests.swift +++ b/AmplifyTests/CategoryTests/Hub/HubCombineTests.swift @@ -14,7 +14,7 @@ import Combine class HubCombineTests: XCTestCase { - func testValue() { + func testValue() async { let receivedValue = expectation(description: "Received value") let sink = Amplify.Hub.publisher(for: .auth) @@ -23,11 +23,11 @@ class HubCombineTests: XCTestCase { } Amplify.Hub.dispatch(to: .auth, payload: HubPayload(eventName: "test")) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue], timeout: 0.05) sink.cancel() } - func testMultipleSubscribersReceiveValue() { + func testMultipleSubscribersReceiveValue() async { let sub1ReceivedValue = expectation(description: "Subscriber 1 received value") let sub2ReceivedValue = expectation(description: "Subscriber 2 received value") @@ -43,13 +43,15 @@ class HubCombineTests: XCTestCase { Amplify.Hub.dispatch(to: .auth, payload: HubPayload(eventName: "test")) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [sub1ReceivedValue, + sub2ReceivedValue], + timeout: 0.05) sub1.cancel() sub2.cancel() } - func testCustomChannel() { + func testCustomChannel() async { let receivedValueForAuth = expectation(description: "receivedValueForAuth") let receivedValueForCustom = expectation(description: "receivedValueForCustom") @@ -61,7 +63,9 @@ class HubCombineTests: XCTestCase { Amplify.Hub.dispatch(to: .auth, payload: HubPayload(eventName: "test")) Amplify.Hub.dispatch(to: .custom("testChannel"), payload: HubPayload(eventName: "test")) - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValueForAuth, + receivedValueForCustom], + timeout: 0.05) authSink.cancel() customSink.cancel() diff --git a/AmplifyTests/CategoryTests/Logging/DefaultLoggingPluginTests.swift b/AmplifyTests/CategoryTests/Logging/DefaultLoggingPluginTests.swift index c3dd41442b..a2b7c47d08 100644 --- a/AmplifyTests/CategoryTests/Logging/DefaultLoggingPluginTests.swift +++ b/AmplifyTests/CategoryTests/Logging/DefaultLoggingPluginTests.swift @@ -46,7 +46,7 @@ class DefaultLoggingPluginTests: XCTestCase { /// - I log messages using `Amplify.Logging` /// - Then: /// - It uses the default logging level - func testUsesDefaultLoggingLevel() { + func testUsesDefaultLoggingLevel() async { // Relies on Amplify.Logging.logLevel defaulting to `.error` let errorMessageCorrectlyEvaluated = expectation(description: "error message was correctly evaluated") @@ -68,7 +68,12 @@ class DefaultLoggingPluginTests: XCTestCase { verboseMessageIncorrectlyEvaluated.isInverted = true Amplify.Logging.verbose("verbose \(verboseMessageIncorrectlyEvaluated.fulfill())") - waitForExpectations(timeout: 0.1) + await fulfillment(of: [errorMessageCorrectlyEvaluated, + warnMessageIncorrectlyEvaluated, + infoMessageIncorrectlyEvaluated, + debugMessageIncorrectlyEvaluated, + verboseMessageIncorrectlyEvaluated], + timeout: 0.1) } /// - Given: default configuration @@ -76,7 +81,7 @@ class DefaultLoggingPluginTests: XCTestCase { /// - I change the global Amplify.Logging.logLevel /// - Then: /// - My log statements are evaluated appropriately - func testRespectsChangedDefaultLogLevel() { + func testRespectsChangedDefaultLogLevel() async { Amplify.Logging.logLevel = .error let warnMessageIncorrectlyEvaluated = expectation(description: "warn message was incorrectly evaluated") @@ -97,7 +102,11 @@ class DefaultLoggingPluginTests: XCTestCase { infoMessageIncorrectlyEvaluatedAgain.isInverted = true Amplify.Logging.info("info \(infoMessageIncorrectlyEvaluatedAgain.fulfill())") - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warnMessageCorrectlyEvaluated, + infoMessageIncorrectlyEvaluated, + warnMessageIncorrectlyEvaluated, + infoMessageIncorrectlyEvaluatedAgain], + timeout: 0.1) } /// Although we can't assert it, the messages in the console log are expected to have different "category" tags @@ -107,7 +116,7 @@ class DefaultLoggingPluginTests: XCTestCase { /// - I obtain a category-specific log /// - Then: /// - I can send messages to it - func testCategorySpecificLog() throws { + func testCategorySpecificLog() async throws { let logger1MessageCorrectlyEvaluated = expectation(description: "logger1 message was correctly evaluated") let logger2MessageCorrectlyEvaluated = expectation(description: "logger2 message was correctly evaluated") @@ -119,7 +128,7 @@ class DefaultLoggingPluginTests: XCTestCase { logger2.error("logger2 \(logger2MessageCorrectlyEvaluated.fulfill())") } - waitForExpectations(timeout: 0.1) + await fulfillment(of: [logger1MessageCorrectlyEvaluated, logger2MessageCorrectlyEvaluated], timeout: 0.1) } /// - Given: default configuration @@ -127,7 +136,7 @@ class DefaultLoggingPluginTests: XCTestCase { /// - I obtain category specific logs with different log levels /// - Then: /// - Each category-specific log evalutes at the appropriate level - func testDifferentLoggersWithDifferentLogLevels() { + func testDifferentLoggersWithDifferentLogLevels() async { let globalMessageCorrectlyEvaluated = expectation(description: "global message was correctly evaluated") let logger1MessageCorrectlyEvaluated = expectation(description: "logger1 message was correctly evaluated") let logger2MessageIncorrectlyEvaluated = expectation(description: "logger2 message was incorrectly evaluated") @@ -141,6 +150,9 @@ class DefaultLoggingPluginTests: XCTestCase { logger1.info("logger1 \(logger1MessageCorrectlyEvaluated.fulfill())") logger2.info("logger2 \(logger2MessageIncorrectlyEvaluated.fulfill())") - waitForExpectations(timeout: 0.1) + await fulfillment(of: [logger1MessageCorrectlyEvaluated, + logger2MessageIncorrectlyEvaluated, + globalMessageCorrectlyEvaluated], + timeout: 0.1) } } diff --git a/AmplifyTests/CategoryTests/Logging/LoggingCategoryClientAPITests.swift b/AmplifyTests/CategoryTests/Logging/LoggingCategoryClientAPITests.swift index 2236cc6228..b155cf8a2f 100644 --- a/AmplifyTests/CategoryTests/Logging/LoggingCategoryClientAPITests.swift +++ b/AmplifyTests/CategoryTests/Logging/LoggingCategoryClientAPITests.swift @@ -24,7 +24,7 @@ class LoggingCategoryClientAPITests: XCTestCase { // MARK: - Test passthrough delegations - func testErrorWithString() throws { + func testErrorWithString() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -38,10 +38,10 @@ class LoggingCategoryClientAPITests: XCTestCase { Amplify.Logging.error("Test") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testErrorWithError() throws { + func testErrorWithError() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -56,10 +56,10 @@ class LoggingCategoryClientAPITests: XCTestCase { let error = ConfigurationError.amplifyAlreadyConfigured("Test", "Test") Amplify.Logging.error(error: error) - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testWarn() throws { + func testWarn() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -74,10 +74,10 @@ class LoggingCategoryClientAPITests: XCTestCase { Amplify.Logging.warn("Test") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testInfo() throws { + func testInfo() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -91,10 +91,10 @@ class LoggingCategoryClientAPITests: XCTestCase { Amplify.Logging.info("Test") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testDebug() throws { + func testDebug() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -108,10 +108,10 @@ class LoggingCategoryClientAPITests: XCTestCase { Amplify.Logging.debug("Test") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } - func testVerbose() throws { + func testVerbose() async throws { let plugin = MockLoggingCategoryPlugin() try Amplify.add(plugin: plugin) try Amplify.configure(mockAmplifyConfig) @@ -128,12 +128,12 @@ class LoggingCategoryClientAPITests: XCTestCase { Amplify.Logging.verbose("Testing verbose logging") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [methodWasInvokedOnPlugin], timeout: 0.5) } // MARK: - Other tests - func testAmplifyDoesNotEvaluateMessageAutoclosureForLoggingStatements() throws { + func testAmplifyDoesNotEvaluateMessageAutoclosureForLoggingStatements() async throws { let plugin = NonEvaluatingLoggingPlugin() try Amplify.add(plugin: plugin) @@ -145,7 +145,7 @@ class LoggingCategoryClientAPITests: XCTestCase { messageWasEvaluated.isInverted = true Amplify.Logging.warn("Should not evaluate \(messageWasEvaluated.fulfill())") - waitForExpectations(timeout: 0.5) + await fulfillment(of: [messageWasEvaluated], timeout: 0.5) } } diff --git a/AmplifyTests/CategoryTests/Logging/LoggingCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Logging/LoggingCategoryConfigurationTests.swift index 78e96f98ff..15432c3aab 100644 --- a/AmplifyTests/CategoryTests/Logging/LoggingCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Logging/LoggingCategoryConfigurationTests.swift @@ -150,7 +150,7 @@ class LoggingCategoryConfigurationTests: XCTestCase { XCTAssertNotNil(try Amplify.Logging.getPlugin(for: "MockSecondLoggingCategoryPlugin")) } - func testCanUseDefaultPluginIfOnlyOnePlugin() throws { + func testCanUseDefaultPluginIfOnlyOnePlugin() async throws { let plugin = MockLoggingCategoryPlugin() let methodInvokedOnDefaultPlugin = expectation(description: "test method invoked on default plugin") plugin.listeners.append { message in @@ -167,10 +167,10 @@ class LoggingCategoryConfigurationTests: XCTestCase { Amplify.Logging.error("test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodInvokedOnDefaultPlugin], timeout: 1) } - func testCanUseSpecifiedPlugin() throws { + func testCanUseSpecifiedPlugin() async throws { let plugin1 = MockLoggingCategoryPlugin() let methodShouldNotBeInvokedOnDefaultPlugin = expectation(description: "test method should not be invoked on default plugin") @@ -205,10 +205,10 @@ class LoggingCategoryConfigurationTests: XCTestCase { try Amplify.Logging.getPlugin(for: "MockSecondLoggingCategoryPlugin") .default .error("test") - waitForExpectations(timeout: 1.0) + await fulfillment(of: [methodShouldBeInvokedOnSecondPlugin, methodShouldNotBeInvokedOnDefaultPlugin], timeout: 1) } - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockLoggingCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -236,7 +236,7 @@ class LoggingCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Logging.getPlugin(for: "MockLoggingCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } // MARK: - Test internal config behavior guarantees diff --git a/AmplifyTests/CategoryTests/Notifications/Push/PushNotificationsCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Notifications/Push/PushNotificationsCategoryConfigurationTests.swift index 9631f0cd42..5e0214ec44 100644 --- a/AmplifyTests/CategoryTests/Notifications/Push/PushNotificationsCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Notifications/Push/PushNotificationsCategoryConfigurationTests.swift @@ -86,7 +86,7 @@ class PushNotificationsCategoryConfigurationTests: XCTestCase { XCTAssertNoThrow(try Amplify.Notifications.Push.configure(using: categoryConfig)) } - func testConfigure_withConfigurationUsingMissingPlugin_shouldLogWarning() throws { + func testConfigure_withConfigurationUsingMissingPlugin_shouldLogWarning() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -107,7 +107,7 @@ class PushNotificationsCategoryConfigurationTests: XCTestCase { let amplifyConfig = AmplifyConfiguration(logging: loggingConfig, notifications: categoryConfig) try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } func testReset_shouldSucceed() async throws { @@ -253,7 +253,7 @@ class PushNotificationsCategoryConfigurationTests: XCTestCase { await fulfillment(of: [methodShouldNotBeInvokedOnDefaultPlugin, methodShouldBeInvokedOnSecondPlugin], timeout: 1.0) } - func testUsingPlugin_callingConfigure_shouldSucceed() throws { + func testUsingPlugin_callingConfigure_shouldSucceed() async throws { let plugin = MockPushNotificationsCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -275,6 +275,6 @@ class PushNotificationsCategoryConfigurationTests: XCTestCase { try Amplify.configure(createAmplifyConfig()) try Amplify.Notifications.Push.getPlugin(for: "MockPushNotificationsCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } } diff --git a/AmplifyTests/CategoryTests/Predictions/PredictionsCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Predictions/PredictionsCategoryConfigurationTests.swift index 7553caae0e..8aca2e84ea 100644 --- a/AmplifyTests/CategoryTests/Predictions/PredictionsCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Predictions/PredictionsCategoryConfigurationTests.swift @@ -171,7 +171,7 @@ class PredictionsCategoryConfigurationTests: XCTestCase { /// - Then: /// - Should work without any error. /// - func testCanConfigurePluginDirectly() throws { + func testCanConfigurePluginDirectly() async throws { let plugin = MockPredictionsCategoryPlugin() let configureShouldBeInvokedFromCategory = expectation(description: "Configure should be invoked by Amplify.configure()") @@ -199,7 +199,7 @@ class PredictionsCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) try Amplify.Predictions.getPlugin(for: "MockPredictionsCategoryPlugin").configure(using: true) - waitForExpectations(timeout: 1.0) + await fulfillment(of: [configureShouldBeInvokedDirectly, configureShouldBeInvokedFromCategory], timeout: 1) } // MARK: - Test internal config behavior guarantees @@ -260,7 +260,7 @@ class PredictionsCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -282,6 +282,6 @@ class PredictionsCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } } diff --git a/AmplifyTests/CategoryTests/Storage/StorageCategoryConfigurationTests.swift b/AmplifyTests/CategoryTests/Storage/StorageCategoryConfigurationTests.swift index 1c27a6779e..49d2a3cc47 100644 --- a/AmplifyTests/CategoryTests/Storage/StorageCategoryConfigurationTests.swift +++ b/AmplifyTests/CategoryTests/Storage/StorageCategoryConfigurationTests.swift @@ -288,7 +288,7 @@ class StorageCategoryConfigurationTests: XCTestCase { /// - Then: /// - I should see a log warning /// - func testWarnsOnMissingPlugin() throws { + func testWarnsOnMissingPlugin() async throws { let warningReceived = expectation(description: "Warning message received") let loggingPlugin = MockLoggingCategoryPlugin() @@ -310,7 +310,7 @@ class StorageCategoryConfigurationTests: XCTestCase { try Amplify.configure(amplifyConfig) - waitForExpectations(timeout: 0.1) + await fulfillment(of: [warningReceived], timeout: 0.1) } /// Test if adding a plugin after configuration throws an error diff --git a/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationChainedTests.swift b/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationChainedTests.swift index f6f1d770c9..30ea3d6b7c 100644 --- a/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationChainedTests.swift +++ b/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationChainedTests.swift @@ -15,7 +15,7 @@ import Combine // swiftlint:disable:next type_name class AmplifyInProcessReportingOperationChainedTests: XCTestCase { - func testChainedResultPublishersSucceed() { + func testChainedResultPublishersSucceed() async { let makeSuccessResponder: (Int) -> MockPublisherInProcessOperation.Responder = { value in let successResponder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -57,11 +57,14 @@ class AmplifyInProcessReportingOperationChainedTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFailure, + receivedFinished], + timeout: 0.05) sink.cancel() } - func testChainedResultPublishersFail() { + func testChainedResultPublishersFail() async { let makeSuccessResponder: (Int) -> MockPublisherInProcessOperation.Responder = { value in let successResponder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -109,11 +112,14 @@ class AmplifyInProcessReportingOperationChainedTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFailure, + receivedFinished], + timeout: 0.05) sink.cancel() } - func testChainedResultPublishersCancel() { + func testChainedResultPublishersCancel() async { let makeSuccessResponder: (Int) -> MockPublisherInProcessOperation.Responder = { value in let successResponder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -156,7 +162,10 @@ class AmplifyInProcessReportingOperationChainedTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, + receivedFailure, + receivedFinished], + timeout: 0.05) sink.cancel() } diff --git a/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationCombineTests.swift b/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationCombineTests.swift index 82209ee52b..6452d90e08 100644 --- a/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationCombineTests.swift +++ b/AmplifyTests/CoreTests/AmplifyInProcessReportingOperationCombineTests.swift @@ -26,7 +26,7 @@ class AmplifyInProcessReportingOperationCombineTests: XCTestCase { var resultSink: AnyCancellable? var inProcessSink: AnyCancellable? - override func setUp() { + override func setUp() async throws { receivedResultValue = expectation(description: "receivedResultValue") receivedResultFinished = expectation(description: "receivedResultFinished") receivedResultFailure = expectation(description: "receivedResultFailure") @@ -40,7 +40,7 @@ class AmplifyInProcessReportingOperationCombineTests: XCTestCase { receivedInProcessFailure.isInverted = true } - func testResultPublisherSucceeds() { + func testResultPublisherSucceeds() async { let responder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatchInProcess(data: "One") operation.dispatch(result: .success(1)) @@ -53,10 +53,16 @@ class AmplifyInProcessReportingOperationCombineTests: XCTestCase { let operation = makeOperation(using: responder) operation.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedResultValue, + receivedResultFailure, + receivedResultFinished, + receivedInProcessValue, + receivedInProcessFailure, + receivedInProcessFinished], + timeout: 0.05) } - func testResultPublisherFails() { + func testResultPublisherFails() async { let responder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatchInProcess(data: "One") operation.dispatch(result: .failure(.unknown("Test", "Test"))) @@ -69,10 +75,16 @@ class AmplifyInProcessReportingOperationCombineTests: XCTestCase { let operation = makeOperation(using: responder) operation.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedResultValue, + receivedResultFailure, + receivedResultFinished, + receivedInProcessValue, + receivedInProcessFailure, + receivedInProcessFinished], + timeout: 0.05) } - func testResultPublisherCancels() { + func testResultPublisherCancels() async { let responder: MockPublisherInProcessOperation.Responder = { operation in operation.dispatchInProcess(data: "One") operation.dispatch(result: .success(1)) @@ -87,7 +99,13 @@ class AmplifyInProcessReportingOperationCombineTests: XCTestCase { let operation = makeOperation(using: responder) operation.cancel() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedResultValue, + receivedResultFailure, + receivedResultFinished, + receivedInProcessValue, + receivedInProcessFailure, + receivedInProcessFinished], + timeout: 0.05) } func makeOperation( diff --git a/AmplifyTests/CoreTests/AmplifyOperationCombineTests.swift b/AmplifyTests/CoreTests/AmplifyOperationCombineTests.swift index f2995044ca..ec85f46e58 100644 --- a/AmplifyTests/CoreTests/AmplifyOperationCombineTests.swift +++ b/AmplifyTests/CoreTests/AmplifyOperationCombineTests.swift @@ -14,7 +14,7 @@ import Combine class AmplifyOperationCombineTests: XCTestCase { - func testResultPublisherSucceeds() { + func testResultPublisherSucceeds() async { let responder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .success(1)) operation.finish() @@ -41,11 +41,11 @@ class AmplifyOperationCombineTests: XCTestCase { operation.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } - func testResultPublisherFails() { + func testResultPublisherFails() async { let responder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .failure(.unknown("Test", "Test"))) operation.finish() @@ -73,11 +73,11 @@ class AmplifyOperationCombineTests: XCTestCase { operation.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } - func testResultPublisherCancels() { + func testResultPublisherCancels() async { let responder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .success(1)) operation.finish() @@ -105,11 +105,11 @@ class AmplifyOperationCombineTests: XCTestCase { operation.cancel() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } - func testChainedResultPublishersSucceed() { + func testChainedResultPublishersSucceed() async { let makeSuccessResponder: (Int) -> MockPublisherOperation.Responder = { value in let successResponder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -151,11 +151,11 @@ class AmplifyOperationCombineTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } - func testChainedResultPublishersFail() { + func testChainedResultPublishersFail() async { let makeSuccessResponder: (Int) -> MockPublisherOperation.Responder = { value in let successResponder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -203,11 +203,11 @@ class AmplifyOperationCombineTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } - func testChainedResultPublishersCancel() { + func testChainedResultPublishersCancel() async { let makeSuccessResponder: (Int) -> MockPublisherOperation.Responder = { value in let successResponder: MockPublisherOperation.Responder = { operation in operation.dispatch(result: .success(value)) @@ -250,7 +250,7 @@ class AmplifyOperationCombineTests: XCTestCase { mockOp1.main() mockOp2.main() - waitForExpectations(timeout: 0.05) + await fulfillment(of: [receivedValue, receivedFailure, receivedFinished], timeout: 0.05) sink.cancel() } diff --git a/AmplifyTests/CoreTests/AtomicValueTests.swift b/AmplifyTests/CoreTests/AtomicValueTests.swift index 16a5e7b387..ebd76866e6 100644 --- a/AmplifyTests/CoreTests/AtomicValueTests.swift +++ b/AmplifyTests/CoreTests/AtomicValueTests.swift @@ -70,7 +70,7 @@ class AtomicValueTests: XCTestCase { } } - func testWithNullable() { + func testWithNullable() async { let deinitialized = expectation(description: "deinitialized") let atomicNotifier = AtomicValue( initialValue: InvocationCounter(fulfillingOnDeinit: deinitialized) @@ -83,7 +83,7 @@ class AtomicValueTests: XCTestCase { } } - waitForExpectations(timeout: 1.0) + await fulfillment(of: [deinitialized], timeout: 1) } } From e51aee86304b6a55b018315a2cd3b2bda0d84e3a Mon Sep 17 00:00:00 2001 From: Di Wu Date: Mon, 27 May 2024 17:50:47 +0000 Subject: [PATCH 2/2] fix(datastore): change OutgoingMutationQueue use TaskQueue for state transitions (#3720) * fix(datastore): change OutgoingMutationQueue use TaskQueue for state transition * Update AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com> --------- Co-authored-by: Michael Law <1365977+lawmicha@users.noreply.github.com> --- .../OutgoingMutationQueue/OutgoingMutationQueue.swift | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift b/AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift index 26cde77852..d517b170af 100644 --- a/AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift +++ b/AmplifyPlugins/DataStore/Sources/AWSDataStorePlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift @@ -27,10 +27,7 @@ final class OutgoingMutationQueue: OutgoingMutationQueueBehavior { private let operationQueue: OperationQueue /// A DispatchQueue for synchronizing state on the mutation queue - private let mutationDispatchQueue = DispatchQueue( - label: "com.amazonaws.OutgoingMutationQueue", - target: DispatchQueue.global() - ) + private let mutationDispatchQueue = TaskQueue() private weak var api: APICategoryGraphQLBehaviorExtended? private weak var reconciliationQueue: IncomingEventReconciliationQueue? @@ -55,7 +52,7 @@ final class OutgoingMutationQueue: OutgoingMutationQueueBehavior { let operationQueue = OperationQueue() operationQueue.name = "com.amazonaws.OutgoingMutationOperationQueue" - operationQueue.underlyingQueue = mutationDispatchQueue + operationQueue.qualityOfService = .default operationQueue.maxConcurrentOperationCount = 1 operationQueue.isSuspended = true @@ -139,6 +136,10 @@ final class OutgoingMutationQueue: OutgoingMutationQueueBehavior { queryMutationEventsFromStorage { [weak self] in guard let self = self else { return } + guard case .starting = self.stateMachine.state else { + self.log.debug("Unexpected state transition while performing `doStart()` during `.starting` state. Current state: \(self.stateMachine.state).") + return + } self.operationQueue.isSuspended = false // State machine notification to ".receivedSubscription" will be handled in `receive(subscription:)`