func testSaveThenMultipleUpdate()

in AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginIntegrationTests/DataStoreConsecutiveUpdatesTests.swift [374:486]


    func testSaveThenMultipleUpdate() throws {
        try startAmplifyAndWaitForSync()

        let newPost = Post(title: "MyPost",
                          content: "This is my post.",
                          createdAt: .now(),
                          rating: 3,
                          status: .published)
        var updatedPost = newPost
        let updatedPostDefaultTitle = "MyUpdatedPost"
        let updateCount = 10

        let saveSyncReceived = expectation(description: "Received create mutation event on subscription for Post")
        let updateSyncReceived = expectation(description: "Received update mutation event on subscription for Post")

        let hubListener = Amplify.Hub.listen(
            to: .dataStore,
            eventName: HubPayload.EventName.DataStore.syncReceived) { payload in
            guard let mutationEvent = payload.data as? MutationEvent else {
                XCTFail("Can't cast payload as mutation event")
                return
            }

            guard let post = try? mutationEvent.decodeModel() as? Post, post.id == newPost.id else {
                return
            }

            if mutationEvent.mutationType == GraphQLMutationType.create.rawValue {
                XCTAssertEqual(post, newPost)
                XCTAssertEqual(mutationEvent.version, 1)
                saveSyncReceived.fulfill()
                return
            }

            if mutationEvent.mutationType == GraphQLMutationType.update.rawValue {
                if post.title == updatedPostDefaultTitle + String(updateCount) {
                    updateSyncReceived.fulfill()
                    return
                }
            }

        }

        guard try HubListenerTestUtilities.waitForListener(with: hubListener, timeout: 5.0) else {
            XCTFail("Listener not registered for hub")
            return
        }

        let saveCompleted = expectation(description: "Save is completed")
        Amplify.DataStore.save(newPost) { result in
            switch result {
            case .success:
                saveCompleted.fulfill()
            case .failure(let error):
                XCTFail("Error: \(error)")
            }
        }
        wait(for: [saveCompleted, saveSyncReceived], timeout: networkTimeout)

        for index in 1 ... updateCount {
            updatedPost.title = updatedPostDefaultTitle + String(index)
            let saveExpectation = expectation(description: "Save \(index) is successful")
            Amplify.DataStore.save(updatedPost) { result in
                switch result {
                case .success:
                    saveExpectation.fulfill()
                case .failure(let error):
                    XCTFail("Error: \(error)")
                }
            }
            wait(for: [saveExpectation], timeout: networkTimeout)
        }

        wait(for: [updateSyncReceived], timeout: networkTimeout)

        // query the updated post in eventual consistent state
        guard let queryResultAfterSync = queryPost(byId: updatedPost.id) else {
            XCTFail("Post should be available after update and sync")
            return
        }

        XCTAssertEqual(queryResultAfterSync, updatedPost)

        let queryRequest =
            GraphQLRequest<MutationSyncResult?>.query(modelName: updatedPost.modelName, byId: updatedPost.id)
        let apiQuerySuccess = expectation(description: "API query is successful")
        Amplify.API.query(request: queryRequest) { result in
            switch result {
            case .success(let mutationSyncResult):
                switch mutationSyncResult {
                case .success(let data):
                    guard let post = data else {
                        XCTFail("Failed to get data")
                        return
                    }

                    XCTAssertEqual(post.model["title"] as? String, updatedPost.title)
                    XCTAssertEqual(post.model["content"] as? String, updatedPost.content)
                    XCTAssertEqual(post.model["rating"] as? Double, updatedPost.rating)
                    // version can be anything between 3 to 11 depending on how many
                    // pending mutations are overwritten in pending mutation queue
                    // while the first update mutation is being processed
                    XCTAssertTrue(post.syncMetadata.version >= 3 && post.syncMetadata.version <= 11)
                    apiQuerySuccess.fulfill()
                case .failure(let error):
                    XCTFail("Error: \(error)")
                }
            case .failure(let error):
                XCTFail("Error: \(error)")
            }
        }
        wait(for: [apiQuerySuccess], timeout: networkTimeout)
    }