Skip to content

Commit 4cb25de

Browse files
authored
test(DataStore): Integration tests for consecutive updates - save then multiple updates scenario (#1455)
* test(DataStore): Integration tests for consecutive updates - save then multiple updates scenario * Address review comments
1 parent 2eeaa27 commit 4cb25de

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginIntegrationTests/DataStoreConsecutiveUpdatesTests.swift

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,123 @@ class DataStoreConsecutiveUpdatesTests: SyncEngineIntegrationTestBase {
368368
wait(for: [apiQuerySuccess], timeout: networkTimeout)
369369
}
370370

371+
/// - Given: API has been setup with `Post` model registered
372+
/// - When: A Post is saved with sync complete, then it is updated 10 times
373+
/// - Then: The Post should be updated with new fields
374+
func testSaveThenMultipleUpdate() throws {
375+
try startAmplifyAndWaitForSync()
376+
377+
let newPost = Post(title: "MyPost",
378+
content: "This is my post.",
379+
createdAt: .now(),
380+
rating: 3,
381+
status: .published)
382+
var updatedPost = newPost
383+
let updatedPostDefaultTitle = "MyUpdatedPost"
384+
let updateCount = 10
385+
386+
let saveSyncReceived = expectation(description: "Received create mutation event on subscription for Post")
387+
let updateSyncReceived = expectation(description: "Received update mutation event on subscription for Post")
388+
389+
let hubListener = Amplify.Hub.listen(
390+
to: .dataStore,
391+
eventName: HubPayload.EventName.DataStore.syncReceived) { payload in
392+
guard let mutationEvent = payload.data as? MutationEvent else {
393+
XCTFail("Can't cast payload as mutation event")
394+
return
395+
}
396+
397+
guard let post = try? mutationEvent.decodeModel() as? Post, post.id == newPost.id else {
398+
return
399+
}
400+
401+
if mutationEvent.mutationType == GraphQLMutationType.create.rawValue {
402+
XCTAssertEqual(post, newPost)
403+
XCTAssertEqual(mutationEvent.version, 1)
404+
saveSyncReceived.fulfill()
405+
return
406+
}
407+
408+
if mutationEvent.mutationType == GraphQLMutationType.update.rawValue {
409+
if post.title == updatedPostDefaultTitle + String(updateCount) {
410+
updateSyncReceived.fulfill()
411+
return
412+
}
413+
}
414+
415+
}
416+
417+
guard try HubListenerTestUtilities.waitForListener(with: hubListener, timeout: 5.0) else {
418+
XCTFail("Listener not registered for hub")
419+
return
420+
}
421+
422+
let saveCompleted = expectation(description: "Save is completed")
423+
Amplify.DataStore.save(newPost) { result in
424+
switch result {
425+
case .success:
426+
saveCompleted.fulfill()
427+
case .failure(let error):
428+
XCTFail("Error: \(error)")
429+
}
430+
}
431+
wait(for: [saveCompleted, saveSyncReceived], timeout: networkTimeout)
432+
433+
for index in 1 ... updateCount {
434+
updatedPost.title = updatedPostDefaultTitle + String(index)
435+
let saveExpectation = expectation(description: "Save \(index) is successful")
436+
Amplify.DataStore.save(updatedPost) { result in
437+
switch result {
438+
case .success:
439+
saveExpectation.fulfill()
440+
case .failure(let error):
441+
XCTFail("Error: \(error)")
442+
}
443+
}
444+
wait(for: [saveExpectation], timeout: networkTimeout)
445+
}
446+
447+
wait(for: [updateSyncReceived], timeout: networkTimeout)
448+
449+
// query the updated post in eventual consistent state
450+
guard let queryResultAfterSync = queryPost(byId: updatedPost.id) else {
451+
XCTFail("Post should be available after update and sync")
452+
return
453+
}
454+
455+
XCTAssertEqual(queryResultAfterSync, updatedPost)
456+
457+
let queryRequest =
458+
GraphQLRequest<MutationSyncResult?>.query(modelName: updatedPost.modelName, byId: updatedPost.id)
459+
let apiQuerySuccess = expectation(description: "API query is successful")
460+
Amplify.API.query(request: queryRequest) { result in
461+
switch result {
462+
case .success(let mutationSyncResult):
463+
switch mutationSyncResult {
464+
case .success(let data):
465+
guard let post = data else {
466+
XCTFail("Failed to get data")
467+
return
468+
}
469+
470+
XCTAssertEqual(post.model["title"] as? String, updatedPost.title)
471+
XCTAssertEqual(post.model["content"] as? String, updatedPost.content)
472+
XCTAssertEqual(post.model["rating"] as? Double, updatedPost.rating)
473+
// version can be anything between 3 to 11 depending on how many
474+
// pending mutations are overwritten in pending mutation queue
475+
// while the first update mutation is being processed
476+
XCTAssertTrue(post.syncMetadata.version >= 3 && post.syncMetadata.version <= 11)
477+
apiQuerySuccess.fulfill()
478+
case .failure(let error):
479+
XCTFail("Error: \(error)")
480+
}
481+
case .failure(let error):
482+
XCTFail("Error: \(error)")
483+
}
484+
}
485+
wait(for: [apiQuerySuccess], timeout: networkTimeout)
486+
}
487+
371488
private func queryPost(byId id: String) -> Post? {
372489
let queryExpectation = expectation(description: "Query is successful")
373490
var queryResult: Post?

0 commit comments

Comments
 (0)