use of com.amplifyframework.api.graphql.PaginatedResult in project amplify-android by aws-amplify.
the class AppSyncMockingTest method mockFailureForSync.
/**
* When mockFailure() is called on the SyncConfigurator, the AppSync mock
* will emit the provided failure.
* @throws DataStoreException On failure to get a SyncConfigurator via sync()
*/
@Test
public void mockFailureForSync() throws DataStoreException {
DataStoreException failure = new DataStoreException("Foo", "Bar");
AppSyncMocking.sync(appSync).mockFailure(failure);
GraphQLRequest<PaginatedResult<ModelWithMetadata<BlogOwner>>> request = appSync.buildSyncRequest(schema, null, 100, QueryPredicates.all());
Single.create(emitter -> appSync.sync(request, emitter::onSuccess, emitter::onError)).test().awaitDone(TIMEOUT_SECONDS, TimeUnit.SECONDS).assertError(failure);
}
use of com.amplifyframework.api.graphql.PaginatedResult 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;
}
use of com.amplifyframework.api.graphql.PaginatedResult in project amplify-android by aws-amplify.
the class AppSyncClientTest method validateBaseSyncQueryGen.
/**
* Validates the construction of a base-sync query.
* @throws JSONException On bad request JSON found in API category call
* @throws DataStoreException If no valid response returned from AppSync endpoint during sync
* @throws AmplifyException On failure to arrange model schema
*/
@Test
public void validateBaseSyncQueryGen() throws JSONException, AmplifyException {
ModelSchema schema = ModelSchema.fromModelClass(BlogOwner.class);
Await.result((Consumer<GraphQLResponse<PaginatedResult<ModelWithMetadata<BlogOwner>>>> onResult, Consumer<DataStoreException> onError) -> {
try {
GraphQLRequest<PaginatedResult<ModelWithMetadata<BlogOwner>>> request = endpoint.buildSyncRequest(schema, null, null, QueryPredicates.all());
endpoint.sync(request, onResult, onError);
} catch (DataStoreException datastoreException) {
onError.accept(datastoreException);
}
});
// Now, capture the request argument on API, so we can see what was passed.
// Recall that we pass a raw doc to API.
ArgumentCaptor<GraphQLRequest<ModelWithMetadata<BlogOwner>>> requestCaptor = ArgumentCaptor.forClass(GraphQLRequest.class);
verify(api).query(requestCaptor.capture(), any(Consumer.class), any(Consumer.class));
GraphQLRequest<ModelWithMetadata<BlogOwner>> capturedRequest = requestCaptor.getValue();
Type type = TypeMaker.getParameterizedType(PaginatedResult.class, ModelWithMetadata.class, BlogOwner.class);
assertEquals(type, capturedRequest.getResponseType());
// The request was sent as JSON. It has a null variables field, and a present query field.
JSONAssert.assertEquals(Resources.readAsString("base-sync-request-document-for-blog-owner.txt"), capturedRequest.getContent(), true);
}
use of com.amplifyframework.api.graphql.PaginatedResult in project amplify-android by aws-amplify.
the class SyncProcessor method syncModel.
/**
* Sync models for a given model class.
* This involves three steps:
* 1. Lookup the last time the model class was synced;
* 2. Make a request to the AppSync endpoint. If the last sync time is within a recent window
* of time, then request a *delta* sync. If the last sync time is outside a recent window of time,
* perform a *base* sync. A base sync is preformed by passing null.
* 3. Continue fetching paged results until !hasNextResult() or we have synced the max records.
*
* @param schema The schema of the model to sync
* @param syncTime The time of a last successful sync.
* @param <T> The type of model to sync.
* @return a stream of all ModelWithMetadata<T> objects from all pages for the provided model.
* @throws DataStoreException if dataStoreConfigurationProvider.getConfiguration() fails
*/
private <T extends Model> Flowable<List<ModelWithMetadata<T>>> syncModel(ModelSchema schema, SyncTime syncTime) throws DataStoreException {
final Long lastSyncTimeAsLong = syncTime.exists() ? syncTime.toLong() : null;
final Integer syncPageSize = dataStoreConfigurationProvider.getConfiguration().getSyncPageSize();
final Integer syncMaxRecords = dataStoreConfigurationProvider.getConfiguration().getSyncMaxRecords();
AtomicReference<Integer> recordsFetched = new AtomicReference<>(0);
QueryPredicate predicate = queryPredicateProvider.getPredicate(schema.getName());
// Create a BehaviorProcessor, and set the default value to a GraphQLRequest that fetches the first page.
BehaviorProcessor<GraphQLRequest<PaginatedResult<ModelWithMetadata<T>>>> processor = BehaviorProcessor.createDefault(appSync.buildSyncRequest(schema, lastSyncTimeAsLong, syncPageSize, predicate));
return processor.concatMap(request -> {
if (isSyncRetryEnabled) {
return syncPageWithRetry(request).toFlowable();
} else {
return syncPage(request).toFlowable();
}
}).doOnNext(paginatedResult -> {
if (paginatedResult.hasNextResult()) {
processor.onNext(paginatedResult.getRequestForNextResult());
} else {
processor.onComplete();
}
}).map(paginatedResult -> Flowable.fromIterable(paginatedResult).map(modelWithMetadata -> hydrateSchemaIfNeeded(modelWithMetadata, schema)).toList().blockingGet()).takeUntil(items -> recordsFetched.accumulateAndGet(items.size(), Integer::sum) >= syncMaxRecords);
}
use of com.amplifyframework.api.graphql.PaginatedResult in project amplify-android by aws-amplify.
the class AWSApiPluginTest method requestUsesIamForAuth.
/**
* Ensure the auth mode used for the request is AWS_IAM. We verify this by
* @throws AmplifyException Not expected.
* @throws InterruptedException Not expected.
*/
@Test
public void requestUsesIamForAuth() throws AmplifyException, InterruptedException {
webServer.enqueue(new MockResponse().setBody(Resources.readAsString("blog-owners-query-results.json")));
AppSyncGraphQLRequest<PaginatedResult<BlogOwner>> appSyncGraphQLRequest = createQueryRequestWithAuthMode(BlogOwner.class, AuthorizationType.AWS_IAM);
GraphQLResponse<PaginatedResult<BlogOwner>> actualResponse = Await.<GraphQLResponse<PaginatedResult<BlogOwner>>, ApiException>result((onResult, onError) -> plugin.query(appSyncGraphQLRequest, onResult, onError));
RecordedRequest recordedRequest = webServer.takeRequest();
assertNull(recordedRequest.getHeader("x-api-key"));
assertNotNull(recordedRequest.getHeader("authorization"));
assertTrue(recordedRequest.getHeader("authorization").startsWith("AWS4-HMAC-SHA256"));
assertEquals(Arrays.asList("Curly", "Moe", "Larry"), Observable.fromIterable(actualResponse.getData()).map(BlogOwner::getName).toList().blockingGet());
}
Aggregations