Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test validating resolver behavior with optimistic updates #4804

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions packages/relay-runtime/store/RelayPublishQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ class RelayPublishQueue implements PublishQueue {
selector,
this._missingFieldHandlers,
);
const selectorData = lookupSelector(source, selector);
const selectorData = lookupMutationSelector(source, selector);
updater(recordSourceSelectorProxy, selectorData);
}
const idsMarkedForInvalidation =
Expand Down Expand Up @@ -410,7 +410,7 @@ class RelayPublishQueue implements PublishQueue {
if (updater) {
let selectorData;
if (source) {
selectorData = lookupSelector(source, operation.fragment);
selectorData = lookupMutationSelector(source, operation.fragment);
}
const recordSourceSelectorProxy = new RelayRecordSourceSelectorProxy(
mutator,
Expand Down Expand Up @@ -447,10 +447,12 @@ class RelayPublishQueue implements PublishQueue {
}
}

function lookupSelector(
function lookupMutationSelector(
source: RecordSource,
selector: SingularReaderSelector,
): ?SelectorData {
// The compiler enforces that mutations may not use Resolvers, so it's okay to
// not pass a resolver cache here.
const selectorData = RelayReader.read(source, selector).data;
if (__DEV__) {
const deepFreeze = require('../util/deepFreeze');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
const {
live_external_greeting: LiveExternalGreeting,
} = require('./LiveExternalGreeting');
const invariant = require('invariant');

Check warning on line 18 in packages/relay-runtime/store/__tests__/resolvers/LiveResolvers-test.js

View workflow job for this annotation

GitHub Actions / JS Lint

'invariant' is assigned a value but never used. Allowed unused vars must match /^_/u

Check warning on line 18 in packages/relay-runtime/store/__tests__/resolvers/LiveResolvers-test.js

View workflow job for this annotation

GitHub Actions / JS Lint

'invariant' is assigned a value but never used. Allowed unused vars must match /^_/u
const {RelayFeatureFlags, suspenseSentinel} = require('relay-runtime');
const RelayNetwork = require('relay-runtime/network/RelayNetwork');
const {graphql} = require('relay-runtime/query/GraphQLTag');
Expand Down Expand Up @@ -336,3 +337,84 @@
const finalData: $FlowExpectedError = finalSnapshot.data;
expect(finalData.counter_throws_when_odd).toBe(2);
});

test('Reflects optimistic updates, and reverts of optimistic updates', () => {
const source = RelayRecordSource.create({
'client:root': {
__id: 'client:root',
__typename: '__Root',
me: {__ref: '4'},
},
'4': {
__id: '4',
__typename: 'User',
name: 'Alice',
},
});
const operation = createOperationDescriptor(
graphql`
query LiveResolversTestOptimisticUpdatesQuery {
me {
greeting
}
}
`,
{},
);

const store = new LiveResolverStore(source, {
gcReleaseBufferSize: 0,
});
const environment = new RelayModernEnvironment({
network: RelayNetwork.create(jest.fn()),
store,
});

const snapshot = environment.lookup(operation.fragment);

// When we start we greet Alice
expect(snapshot.data).toEqual({me: {greeting: 'Hello, Alice!'}});

const handler = jest.fn<[Snapshot], void>();
environment.subscribe(snapshot, handler);

const mutationSub = environment.applyMutation({
operation: createOperationDescriptor(
graphql`
mutation LiveResolversTestOptimisticUpdatesMutation(
$input: ActorNameChangeInput!
) {
actorNameChange(input: $input) {
actor {
name
}
}
}
`,
{input: {newName: 'Bob'}},
),
response: {
actorNameChange: {
actor: {
__typename: 'User',
id: '4',
name: 'Bob',
},
},
},
updater: null,
});

// In optimistic state we greet Bob
expect(handler.mock.calls.length).toBe(1);
expect(handler.mock.calls[0][0].data).toEqual({
me: {greeting: 'Hello, Bob!'},
});

mutationSub.dispose();
// When the optimistic update is disposed we greet Alice again
expect(handler.mock.calls.length).toBe(2);
expect(handler.mock.calls[1][0].data).toEqual({
me: {greeting: 'Hello, Alice!'},
});
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading