Skip to content

Commit

Permalink
Support hasNext on payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
robrichard committed Jul 14, 2020
1 parent 34d36ab commit cd4a139
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
3 changes: 3 additions & 0 deletions packages/relay-runtime/network/RelayNetworkTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export type GraphQLResponseWithData = {|
+extensions?: PayloadExtensions,
+label?: string,
+path?: Array<string | number>,
+hasNext?: boolean,
|};

export type GraphQLResponseWithoutData = {|
Expand All @@ -59,6 +60,7 @@ export type GraphQLResponseWithoutData = {|
+extensions?: PayloadExtensions,
+label?: string,
+path?: Array<string | number>,
+hasNext?: boolean,
|};

export type GraphQLResponseWithExtensionsOnly = {|
Expand All @@ -72,6 +74,7 @@ export type GraphQLResponseWithExtensionsOnly = {|
// does not necessarily indicate that there was an error.
+data: null,
+extensions: PayloadExtensions,
+hasNext?: boolean,
|};

export type GraphQLSingularResponse =
Expand Down
48 changes: 48 additions & 0 deletions packages/relay-runtime/query/__tests__/fetchQueryInternal-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,30 @@ describe('getObservableForActiveRequest', () => {
expect(events).toEqual(['next']);
});

it('calls next asynchronously with subsequent non-final payloads (OSS)', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
environment,
query.request,
);
expect(observable).not.toEqual(null);
if (!observable) {
return;
}

response = {
...response,
extensions: {},
hasNext: true,
};

observable.subscribe(observer);
expect(events).toEqual([]);

environment.mock.nextValue(gqlQuery, response);
expect(events).toEqual(['next']);
});

it('calls complete asynchronously with subsequent final payload', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
Expand All @@ -982,6 +1006,30 @@ describe('getObservableForActiveRequest', () => {
expect(events).toEqual(['complete']);
});

it('calls complete asynchronously with subsequent final payload (OSS)', () => {
fetchQuery(environment, query).subscribe({});
const observable = getObservableForActiveRequest(
environment,
query.request,
);
expect(observable).not.toEqual(null);
if (!observable) {
return;
}

response = {
...response,
extensions: {},
hasNext: false,
};

observable.subscribe(observer);
expect(events).toEqual([]);

environment.mock.nextValue(gqlQuery, response);
expect(events).toEqual(['complete']);
});

describe('when loading @module', () => {
let operationLoader;
let resolveModule;
Expand Down
19 changes: 16 additions & 3 deletions packages/relay-runtime/store/RelayModernQueryExecutor.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ class Executor {
if (responsesWithData.length === 0) {
// no results with data, nothing to process
// this can occur with extensions-only payloads
const isFinal = responses.some(x => x.extensions?.is_final === true);
const isFinal = responses.some(x => responseIsFinal(x));
if (isFinal) {
this._state = 'loading_final';
this._updateActiveState();
Expand Down Expand Up @@ -1019,7 +1019,7 @@ class Executor {
incrementalPlaceholders: null,
moduleImportPayloads: null,
source: RelayRecordSource.create(),
isFinal: response.extensions?.is_final === true,
isFinal: responseIsFinal(response),
};
this._publishQueue.commitPayload(
this._operation,
Expand Down Expand Up @@ -1296,7 +1296,7 @@ function normalizeResponse(
return {
...relayPayload,
errors,
isFinal: response.extensions?.is_final === true,
isFinal: responseIsFinal(response),
};
}

Expand All @@ -1318,4 +1318,17 @@ function validateOptimisticResponsePayload(
}
}

/**
* Check for both FB specific (extensions?.is_final)
* and spec-complaint (hasNext) properties.
*/
function responseIsFinal(response: GraphQLSingularResponse): boolean {
if (response.extensions?.is_final === true) {
return true;
} else if (response.hasNext === false) {
return true;
}
return false;
}

module.exports = {execute};

0 comments on commit cd4a139

Please sign in to comment.