use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.
the class GsonPendingMutationConverterTest method convertPendingMutationWithSerializedModelWithChildToRecordAndBackWithNestedModelSchema.
/**
* Validate that the {@link GsonPendingMutationConverter} can be
* used to convert a sample {@link PendingMutation} to a
* {@link PendingMutation.PersistentRecord}, and vice-versa.
* @throws DataStoreException from DataStore conversion
* @throws AmplifyException On failure to arrange model schema
*/
@Test
public void convertPendingMutationWithSerializedModelWithChildToRecordAndBackWithNestedModelSchema() throws AmplifyException {
ModelSchema blogOwnerSchema = ModelSchema.fromModelClass(BlogOwner.class);
// register BlogOwner schema to ensure nested SerializedModel to be set with it's schema
schemaRegistry.register("BlogOwner", blogOwnerSchema);
// Arrange a PendingMutation<SerializedModel>
Blog blog = Blog.builder().name("A neat blog").owner(BlogOwner.builder().name("Joe Swanson").build()).build();
ModelSchema schema = ModelSchema.fromModelClass(Blog.class);
SerializedModel serializedBlog = SerializedModel.create(blog, schema);
PendingMutation<SerializedModel> originalMutation = PendingMutation.creation(serializedBlog, schema);
String expectedMutationId = originalMutation.getMutationId().toString();
// Instantiate the object under test
PendingMutation.Converter converter = new GsonPendingMutationConverter();
// Try to construct a record from the PendingMutation instance.
PendingMutation.PersistentRecord record = converter.toRecord(originalMutation);
assertNotNull(record);
assertEquals(expectedMutationId, record.getId());
// Now, try to convert it back...
PendingMutation<SerializedModel> reconstructedItemChange = converter.fromRecord(record);
assertEquals(originalMutation, reconstructedItemChange);
}
use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.
the class GsonPendingMutationConverterTest method convertPendingMutationWithSerializedModelWithChildToRecordAndBack.
/**
* Validate that the {@link GsonPendingMutationConverter} can be
* used to convert a sample {@link PendingMutation} to a
* {@link PendingMutation.PersistentRecord}, and vice-versa.
* @throws DataStoreException from DataStore conversion
* @throws AmplifyException On failure to arrange model schema
*/
@Test
public void convertPendingMutationWithSerializedModelWithChildToRecordAndBack() throws AmplifyException {
// Arrange a PendingMutation<SerializedModel>
Blog blog = Blog.builder().name("A neat blog").owner(BlogOwner.builder().name("Joe Swanson").build()).build();
ModelSchema schema = ModelSchema.fromModelClass(Blog.class);
SerializedModel serializedBlog = SerializedModel.create(blog, schema);
PendingMutation<SerializedModel> originalMutation = PendingMutation.creation(serializedBlog, schema);
String expectedMutationId = originalMutation.getMutationId().toString();
// Instantiate the object under test
PendingMutation.Converter converter = new GsonPendingMutationConverter();
// Try to construct a record from the PendingMutation instance.
PendingMutation.PersistentRecord record = converter.toRecord(originalMutation);
assertNotNull(record);
assertEquals(expectedMutationId, record.getId());
// Now, try to convert it back...
PendingMutation<SerializedModel> reconstructedItemChange = converter.fromRecord(record);
assertEquals(originalMutation, reconstructedItemChange);
}
use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.
the class MutationProcessorTest method conflictHandlerInvokedForUnhandledConflictError.
/**
* If the AppSync response to the mutation contains a ConflictUnhandled
* error in the GraphQLResponse error list, then the user-provided
* conflict handler should be invoked.
* @throws DataStoreException On failure to obtain configuration from the provider
* @throws AmplifyException On failure to build {@link ModelSchema}
*/
@Test
public void conflictHandlerInvokedForUnhandledConflictError() throws AmplifyException {
// Arrange a user-provided conflict handler.
CountDownLatch handlerInvocationsRemainingCount = new CountDownLatch(1);
when(configurationProvider.getConfiguration()).thenReturn(DataStoreConfiguration.builder().conflictHandler((conflictData, onDecision) -> handlerInvocationsRemainingCount.countDown()).build());
// Save a model, its metadata, and its last sync data.
BlogOwner model = BlogOwner.builder().name("Exceptional Blogger").build();
ModelMetadata metadata = new ModelMetadata(model.getModelName() + "|" + model.getId(), false, 1, Temporal.Timestamp.now());
ModelSchema schema = schemaRegistry.getModelSchemaForModelClass(BlogOwner.class);
LastSyncMetadata lastSyncMetadata = LastSyncMetadata.baseSyncedAt(schema.getName(), 1_000L);
synchronousStorageAdapter.save(model, metadata, lastSyncMetadata);
// Enqueue an update in the mutation outbox
assertTrue(mutationOutbox.enqueue(PendingMutation.update(model, schema)).blockingAwait(TIMEOUT_SECONDS, TimeUnit.SECONDS));
// Fields that represent the "server's" understanding of the model state
Map<String, Object> serverModelData = new HashMap<>();
serverModelData.put("id", model.getId());
serverModelData.put("name", "Server blogger name");
serverModelData.put("_version", 1);
serverModelData.put("_deleted", false);
serverModelData.put("_lastChangedAt", 1_000);
// When AppSync receives that update, have it respond
// with a ConflictUnhandledError.
String message = "Conflict resolver rejects mutation.";
List<GraphQLPathSegment> paths = Collections.singletonList(new GraphQLPathSegment("updateBlogOwner"));
List<GraphQLLocation> locations = Collections.singletonList(new GraphQLLocation(2, 3));
Map<String, Object> extensions = new HashMap<>();
extensions.put("errorType", "ConflictUnhandled");
extensions.put("data", serverModelData);
GraphQLResponse.Error error = new GraphQLResponse.Error(message, locations, paths, extensions);
AppSyncMocking.update(appSync).mockErrorResponse(model, 1, error);
// Start the mutation processor.
mutationProcessor.startDrainingMutationOutbox();
// Wait for the conflict handler to be called.
Latch.await(handlerInvocationsRemainingCount);
}
use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.
the class MutationProcessorTest method canDrainMutationOutbox.
/**
* Tests the {@link MutationProcessor#startDrainingMutationOutbox()}. After this method
* is called, any content in the {@link MutationOutbox} should be published via the {@link AppSync}
* and then removed.
* @throws DataStoreException On failure to interact with storage adapter during arrangement
* and verification
*/
@Test
public void canDrainMutationOutbox() throws DataStoreException {
// We will attempt to "sync" this model.
BlogOwner tony = BlogOwner.builder().name("Tony Daniels").build();
synchronousStorageAdapter.save(tony);
// Arrange a cooked response from AppSync.
AppSyncMocking.create(appSync).mockSuccessResponse(tony);
// Start listening for publication events.
HubAccumulator accumulator = HubAccumulator.create(HubChannel.DATASTORE, isProcessed(tony), 1).start();
ModelSchema schema = schemaRegistry.getModelSchemaForModelClass(BlogOwner.class);
PendingMutation<BlogOwner> createTony = PendingMutation.creation(tony, schema);
assertTrue(mutationOutbox.enqueue(createTony).blockingAwait(TIMEOUT_SECONDS, TimeUnit.SECONDS));
// Act! Start draining the outbox.
mutationProcessor.startDrainingMutationOutbox();
// Assert: the event was published
assertEquals(1, accumulator.await().size());
// And that it is no longer in the outbox.
assertFalse(mutationOutbox.hasPendingMutation(tony.getId()));
// And that it was passed to AppSync for publication.
verify(appSync).create(eq(tony), any(), any(), any());
}
use of com.amplifyframework.core.model.ModelSchema in project amplify-android by aws-amplify.
the class MutationProcessorTest method outboxStatusIsPublishedToHubOnProcess.
/**
* Processing a mutation should publish current outbox status.
*/
@Test
public void outboxStatusIsPublishedToHubOnProcess() {
BlogOwner raphael = BlogOwner.builder().name("Raphael Kim").build();
ModelSchema schema = schemaRegistry.getModelSchemaForModelClass(BlogOwner.class);
PendingMutation<BlogOwner> createRaphael = PendingMutation.creation(raphael, schema);
// Mock up a response from AppSync and enqueue a mutation.
AppSyncMocking.create(appSync).mockSuccessResponse(raphael);
assertTrue(mutationOutbox.enqueue(createRaphael).blockingAwait(TIMEOUT_SECONDS, TimeUnit.SECONDS));
// Start listening for publication events.
// outbox should be empty after processing its only mutation
HubAccumulator statusAccumulator = HubAccumulator.create(HubChannel.DATASTORE, isOutboxEmpty(true), 1).start();
// Start draining the outbox which has one mutation enqueued,
// and make sure that outbox status is published to hub.
mutationProcessor.startDrainingMutationOutbox();
statusAccumulator.await();
}
Aggregations