func testSaveAndImmediatelyUpdate()

in AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginFlutterIntegrationTests/DataStoreFlutterConsecutiveUpdatesTests.swift [22:132]


    func testSaveAndImmediatelyUpdate() throws {
        try startAmplifyAndWaitForSync()
        let plugin: AWSDataStorePlugin = try Amplify.DataStore.getPlugin(for: "awsDataStorePlugin") as! AWSDataStorePlugin
        let newPost = try PostWrapper(title: "MyPost",
                          content: "This is my post.")

        let updatedPost = newPost
        try updatedPost.updateRating(rating: 5)
        try updatedPost.updateStringProp(key: "title", value: "MyUpdatedTitle")
        try updatedPost.updateStringProp(key: "content", value: "This is my updated post.")

        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? PostWrapper(json: mutationEvent.json) as! PostWrapper, post.idString() == newPost.idString() else {
                return
            }

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

            if mutationEvent.mutationType == GraphQLMutationType.update.rawValue {
                XCTAssertEqual(post, updatedPost)
                XCTAssertEqual(mutationEvent.version, 2)
                updateSyncReceived.fulfill()
                return
            }
        }

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

        let saveAndImmediatelyUpdate = expectation(description: "Post is saved and then immediately updated")
        plugin.save(newPost.model, modelSchema: Post.schema) { result in
            switch result {
            case .success:
                plugin.save(updatedPost.model, modelSchema: Post.schema) { result in
                    switch result {
                    case .success:
                        saveAndImmediatelyUpdate.fulfill()
                    case .failure(let error):
                        XCTFail("Error: \(error)")
                    }
                }
            case .failure(let error):
                XCTFail("Error: \(error)")
            }
        }
        wait(for: [saveAndImmediatelyUpdate], timeout: networkTimeout)

        // query the updated post immediately
        guard let queryResult = queryPost(id: updatedPost.idString(), plugin: plugin) else {
            XCTFail("Post should be available after update")
            return
        }
        XCTAssertEqual(queryResult, updatedPost)

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

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

        XCTAssertEqual(queryResultAfterSync, updatedPost)

        let queryRequest =
            GraphQLRequest<MutationSyncResult?>.query(modelName: "Post", byId: updatedPost.idString())
        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
                    }
                    
                    let testPost = self.convertToTestPost(model: post.model.instance as! Post)
                    XCTAssertNotNil(testPost)
                    
                    XCTAssertEqual(testPost?.title(), updatedPost.title())
                    XCTAssertEqual(testPost?.content(), updatedPost.content())
                    XCTAssertEqual(testPost?.rating(), updatedPost.rating())
                    XCTAssertEqual(post.syncMetadata.version, 2)
                    apiQuerySuccess.fulfill()
                case .failure(let error):
                    XCTFail("Error: \(error)")
                }
            case .failure(let error):
                XCTFail("Error: \(error)")
            }
        }
        wait(for: [apiQuerySuccess], timeout: networkTimeout)
    }