Search in sources :

Example 1 with GraphQLResponse

use of com.amplifyframework.api.graphql.GraphQLResponse in project amplify-android by aws-amplify.

the class SubscriptionProcessorTest method isDataMergedWhenBufferDrainedForBlogOwnerNamed.

/**
 * Return whether a response with a BlogOwner with the given name gets merged with the merger.
 * @param name name of the BlogOwner returned in the subscription
 * @return whether the data was merged
 * @throws DataStoreException On failure to arrange mocking
 * @throws InterruptedException On failure to await latch
 */
private boolean isDataMergedWhenBufferDrainedForBlogOwnerNamed(String name) throws DataStoreException, InterruptedException {
    // By default, start the subscriptions up.
    arrangeStartedSubscriptions(appSync, modelSchemas, SubscriptionType.values());
    // Arrange some subscription data
    BlogOwner model = BlogOwner.builder().name(name).build();
    ModelMetadata modelMetadata = new ModelMetadata(model.getId(), false, 1, Temporal.Timestamp.now());
    ModelWithMetadata<BlogOwner> modelWithMetadata = new ModelWithMetadata<>(model, modelMetadata);
    GraphQLResponse<ModelWithMetadata<BlogOwner>> response = new GraphQLResponse<>(modelWithMetadata, null);
    arrangeDataEmittingSubscription(appSync, schemaRegistry.getModelSchemaForModelInstance(model), SubscriptionType.ON_CREATE, response);
    // Merge will be invoked for the subcription data, when we start draining...
    CountDownLatch latch = new CountDownLatch(1);
    doAnswer(invocation -> {
        latch.countDown();
        return Completable.complete();
    }).when(merger).merge(eq(response.getData()));
    // Start draining....
    subscriptionProcessor.startSubscriptions();
    subscriptionProcessor.startDrainingMutationBuffer();
    // Was the data merged?
    return latch.await(OPERATION_TIMEOUT_MS, TimeUnit.MILLISECONDS);
}
Also used : ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) CountDownLatch(java.util.concurrent.CountDownLatch) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata)

Example 2 with GraphQLResponse

use of com.amplifyframework.api.graphql.GraphQLResponse 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);
}
Also used : GraphQLLocation(com.amplifyframework.api.graphql.GraphQLLocation) HashMap(java.util.HashMap) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) GraphQLPathSegment(com.amplifyframework.api.graphql.GraphQLPathSegment) CountDownLatch(java.util.concurrent.CountDownLatch) ModelSchema(com.amplifyframework.core.model.ModelSchema) BlogOwner(com.amplifyframework.testmodels.commentsblog.BlogOwner) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata) Test(org.junit.Test)

Example 3 with GraphQLResponse

use of com.amplifyframework.api.graphql.GraphQLResponse in project amplify-android by aws-amplify.

the class CodeGenerationInstrumentationTest method belongsToRelationship.

/**
 * For a model having an {@link BelongsTo} relationship to another model, validate
 * successful query, mutations, subscription.
 * TODO: Add mutate with condition and list with predicate since those are the ones
 *       that actually use the original model name
 * @throws ApiException On failure to obtain valid response from endpoint
 */
@Test
public void belongsToRelationship() throws ApiException {
    // Subscribe to creation events for any Projectfields
    TestObserver<GraphQLResponse<Projectfields>> observer = api.onCreate(PROJECT_API_NAME, Projectfields.class).test();
    // Create a team
    Team team = Team.builder().name("AWS Mobile SDK").build();
    Team createdTeam = api.create(PROJECT_API_NAME, team);
    // Create a Projectfields
    Projectfields projectfields = Projectfields.builder().name("API Codegen").team(Team.justId(createdTeam.getId())).build();
    Projectfields createdProjectfields = api.create(PROJECT_API_NAME, projectfields);
    // Query for the Projectfields that were just created. The referenced team
    // should be the same as the one we requested for creation, earlier.
    assertEquals(team, api.get(PROJECT_API_NAME, Projectfields.class, createdProjectfields.getId()).getTeam());
    // Validate that subscription received the newly created team, too.
    Projectfields projectfieldsOnSubscription = observer.awaitCount(1).values().get(0).getData();
    assertEquals(projectfields.getName(), projectfieldsOnSubscription.getName());
    assertEquals(team, projectfieldsOnSubscription.getTeam());
    // Cancel the subscription
    observer.dispose();
}
Also used : GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Team(com.amplifyframework.testmodels.teamproject.Team) Projectfields(com.amplifyframework.testmodels.teamproject.Projectfields) Test(org.junit.Test)

Example 4 with GraphQLResponse

use of com.amplifyframework.api.graphql.GraphQLResponse in project amplify-android by aws-amplify.

the class CodeGenerationInstrumentationTest method subscribeReceivesMutationEvent.

/**
 * Tests that a subscription can receive an event when a create mutation takes place.
 * @throws ApiException On failure to obtain valid response from endpoint
 */
@Test
public void subscribeReceivesMutationEvent() throws ApiException {
    TestObserver<GraphQLResponse<Person>> observer = api.onCreate(PERSON_API_NAME, Person.class).test();
    Person johnDoe = Person.builder().firstName("John").lastName("Doe").build();
    api.create(PERSON_API_NAME, johnDoe);
    // Validate that subscription received the newly created person.
    Person firstPersonOnSubscription = observer.awaitCount(1).values().get(0).getData();
    assertEquals(johnDoe.getFirstName(), firstPersonOnSubscription.getFirstName());
    assertEquals(johnDoe.getLastName(), firstPersonOnSubscription.getLastName());
    // Cancel the subscription
    observer.dispose();
}
Also used : GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Person(com.amplifyframework.testmodels.personcar.Person) Test(org.junit.Test)

Example 5 with GraphQLResponse

use of com.amplifyframework.api.graphql.GraphQLResponse in project amplify-android by aws-amplify.

the class ConflictResolverIntegrationTest method setupApiMock.

@SuppressWarnings("unchecked")
private Person setupApiMock(CountDownLatch latch, ApiCategory mockApiCategory) {
    Person person1 = createPerson("Test", "Dummy I");
    // Mock success on subscription.
    doAnswer(invocation -> {
        int indexOfStartConsumer = 1;
        Consumer<String> onStart = invocation.getArgument(indexOfStartConsumer);
        GraphQLOperation<?> mockOperation = mock(GraphQLOperation.class);
        doAnswer(opAnswer -> {
            return null;
        }).when(mockOperation).cancel();
        // Trigger the subscription start event.
        onStart.accept(RandomString.string());
        return mockOperation;
    }).when(mockApiCategory).subscribe(any(GraphQLRequest.class), any(Consumer.class), any(Consumer.class), any(Consumer.class), any(Action.class));
    // When mutate is called on the appsync for the first time unhandled conflict error is returned.
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        List<GraphQLLocation> locations = new ArrayList<>();
        locations.add(new GraphQLLocation(2, 3));
        List<GraphQLPathSegment> path = new ArrayList<>();
        path.add(new GraphQLPathSegment("updatePost"));
        Map<String, Object> serverModelData = new HashMap<>();
        serverModelData.put("id", "5c895eae-88ef-4ce8-9d58-e27d0c7cbe99");
        serverModelData.put("createdAt", "2022-02-04T19:41:05.973Z");
        serverModelData.put("first_name", "test");
        serverModelData.put("last_name", "server last");
        serverModelData.put("_version", 92);
        serverModelData.put("_deleted", false);
        serverModelData.put("_lastChangedAt", 1_000);
        Map<String, Object> extensions = new HashMap<>();
        extensions.put("errorInfo", null);
        extensions.put("data", serverModelData);
        extensions.put("errorType", "ConflictUnhandled");
        ArrayList<GraphQLResponse.Error> errorList = new ArrayList<>();
        errorList.add(new GraphQLResponse.Error("Conflict resolver rejects mutation.", locations, path, extensions));
        onResponse.accept(new GraphQLResponse<>(null, errorList));
        // latch makes sure conflict unhandled response is returned.
        latch.countDown();
        return mock(GraphQLOperation.class);
    }).doAnswer(invocation -> {
        // When mutate is called on the appsync for the second time success response is returned
        int indexOfResponseConsumer = 1;
        Consumer<GraphQLResponse<ModelWithMetadata<Person>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        ModelMetadata modelMetadata = new ModelMetadata(person1.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person1, modelMetadata);
        onResponse.accept(new GraphQLResponse<>(modelWithMetadata, Collections.emptyList()));
        verify(mockApiCategory, atLeast(2)).mutate(argThat(getMatcherFor(person1)), any(), any());
        // latch makes sure success response is returned.
        latch.countDown();
        return mock(GraphQLOperation.class);
    }).when(mockApiCategory).mutate(any(), any(), any());
    // Setup to mimic successful sync
    doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        ModelMetadata modelMetadata = new ModelMetadata(person1.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Person> modelWithMetadata = new ModelWithMetadata<>(person1, modelMetadata);
        // Mock the API emitting an ApiEndpointStatusChangeEvent event.
        Consumer<GraphQLResponse<PaginatedResult<ModelWithMetadata<Person>>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        PaginatedResult<ModelWithMetadata<Person>> data = new PaginatedResult<>(Collections.singletonList(modelWithMetadata), null);
        onResponse.accept(new GraphQLResponse<>(data, Collections.emptyList()));
        latch.countDown();
        return mock(GraphQLOperation.class);
    }).doAnswer(invocation -> {
        int indexOfResponseConsumer = 1;
        Car car = Car.builder().build();
        ModelMetadata modelMetadata = new ModelMetadata(car.getId(), false, 1, Temporal.Timestamp.now());
        ModelWithMetadata<Car> modelWithMetadata = new ModelWithMetadata<>(car, modelMetadata);
        Consumer<GraphQLResponse<PaginatedResult<ModelWithMetadata<Car>>>> onResponse = invocation.getArgument(indexOfResponseConsumer);
        PaginatedResult<ModelWithMetadata<Car>> data = new PaginatedResult<>(Collections.singletonList(modelWithMetadata), null);
        onResponse.accept(new GraphQLResponse<>(data, Collections.emptyList()));
        latch.countDown();
        return mock(GraphQLOperation.class);
    }).when(mockApiCategory).query(any(), any(), any());
    return person1;
}
Also used : AmplifyException(com.amplifyframework.AmplifyException) ApplicationProvider.getApplicationContext(androidx.test.core.app.ApplicationProvider.getApplicationContext) ArgumentMatchers.argThat(org.mockito.ArgumentMatchers.argThat) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) ModelProvider(com.amplifyframework.core.model.ModelProvider) GraphQLPathSegment(com.amplifyframework.api.graphql.GraphQLPathSegment) ApiChannelEventName(com.amplifyframework.api.events.ApiChannelEventName) ArgumentMatcher(org.mockito.ArgumentMatcher) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject) GraphQLLocation(com.amplifyframework.api.graphql.GraphQLLocation) Map(java.util.Map) Mockito.doAnswer(org.mockito.Mockito.doAnswer) Mockito.atLeast(org.mockito.Mockito.atLeast) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Assert.fail(org.junit.Assert.fail) HubEvent(com.amplifyframework.hub.HubEvent) HubChannel(com.amplifyframework.hub.HubChannel) ApiCategory(com.amplifyframework.api.ApiCategory) InitializationStatus(com.amplifyframework.core.InitializationStatus) RobolectricTestRunner(org.robolectric.RobolectricTestRunner) Person(com.amplifyframework.testmodels.personcar.Person) CountDownLatch(java.util.concurrent.CountDownLatch) List(java.util.List) RandomString(com.amplifyframework.testutils.random.RandomString) Mockito.any(org.mockito.Mockito.any) Mockito.mock(org.mockito.Mockito.mock) Context(android.content.Context) GraphQLRequest(com.amplifyframework.api.graphql.GraphQLRequest) RunWith(org.junit.runner.RunWith) HashMap(java.util.HashMap) Car(com.amplifyframework.testmodels.personcar.Car) Mockito.spy(org.mockito.Mockito.spy) ArrayList(java.util.ArrayList) Consumer(com.amplifyframework.core.Consumer) ApiEndpointStatusChangeEvent(com.amplifyframework.api.events.ApiEndpointStatusChangeEvent) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata) PaginatedResult(com.amplifyframework.api.graphql.PaginatedResult) Before(org.junit.Before) Amplify(com.amplifyframework.core.Amplify) SynchronousDataStore(com.amplifyframework.testutils.sync.SynchronousDataStore) ApiPlugin(com.amplifyframework.api.ApiPlugin) CategoryType(com.amplifyframework.core.category.CategoryType) Assert.assertTrue(org.junit.Assert.assertTrue) Test(org.junit.Test) Completable(io.reactivex.rxjava3.core.Completable) Action(com.amplifyframework.core.Action) Mockito.when(org.mockito.Mockito.when) AmplifyCliGeneratedModelProvider(com.amplifyframework.testmodels.personcar.AmplifyCliGeneratedModelProvider) Mockito.verify(org.mockito.Mockito.verify) TimeUnit(java.util.concurrent.TimeUnit) ApiCategoryConfiguration(com.amplifyframework.api.ApiCategoryConfiguration) Temporal(com.amplifyframework.core.model.temporal.Temporal) GraphQLOperation(com.amplifyframework.api.graphql.GraphQLOperation) Collections(java.util.Collections) Assert.assertEquals(org.junit.Assert.assertEquals) Action(com.amplifyframework.core.Action) GraphQLLocation(com.amplifyframework.api.graphql.GraphQLLocation) ArrayList(java.util.ArrayList) GraphQLPathSegment(com.amplifyframework.api.graphql.GraphQLPathSegment) RandomString(com.amplifyframework.testutils.random.RandomString) GraphQLRequest(com.amplifyframework.api.graphql.GraphQLRequest) Consumer(com.amplifyframework.core.Consumer) List(java.util.List) ArrayList(java.util.ArrayList) ModelWithMetadata(com.amplifyframework.datastore.appsync.ModelWithMetadata) PaginatedResult(com.amplifyframework.api.graphql.PaginatedResult) GraphQLResponse(com.amplifyframework.api.graphql.GraphQLResponse) Car(com.amplifyframework.testmodels.personcar.Car) GraphQLOperation(com.amplifyframework.api.graphql.GraphQLOperation) Person(com.amplifyframework.testmodels.personcar.Person) Map(java.util.Map) HashMap(java.util.HashMap) ModelMetadata(com.amplifyframework.datastore.appsync.ModelMetadata)

Aggregations

GraphQLResponse (com.amplifyframework.api.graphql.GraphQLResponse)30 Test (org.junit.Test)23 PaginatedResult (com.amplifyframework.api.graphql.PaginatedResult)14 Model (com.amplifyframework.core.model.Model)11 ApiException (com.amplifyframework.api.ApiException)10 Action (com.amplifyframework.core.Action)9 Consumer (com.amplifyframework.core.Consumer)9 ModelWithMetadata (com.amplifyframework.datastore.appsync.ModelWithMetadata)9 JSONObject (org.json.JSONObject)9 BlogOwner (com.amplifyframework.testmodels.commentsblog.BlogOwner)8 GraphQLRequest (com.amplifyframework.api.graphql.GraphQLRequest)7 RandomString (com.amplifyframework.testutils.random.RandomString)7 AmplifyException (com.amplifyframework.AmplifyException)6 ModelSchema (com.amplifyframework.core.model.ModelSchema)6 ModelMetadata (com.amplifyframework.datastore.appsync.ModelMetadata)6 RandomModel (com.amplifyframework.testutils.random.RandomModel)6 HashMap (java.util.HashMap)6 QueryType (com.amplifyframework.api.graphql.QueryType)5 SubscriptionType (com.amplifyframework.api.graphql.SubscriptionType)5 Cancelable (com.amplifyframework.core.async.Cancelable)5