Skip to content

Commit

Permalink
[#3030] Fix no-cache fetchPolicy returns null or undefined (#3102)
Browse files Browse the repository at this point in the history
* Set query newData if using no-cache fetch policy and set resultFromStore

* Add tests for no-cache fetch policy

* Get VSCode to run jest for apollo-client for debugging

* Update authors/changelog

* Move tests to appropriate location

* Pass through no-cache fetch policy
  • Loading branch information
kamranayub authored and James Baxley committed Mar 23, 2018
1 parent a511a3f commit c4a1ad6
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 12 deletions.
15 changes: 7 additions & 8 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@
"configurations": [
{
"name": "Test",
"request": "launch",
"type": "node",
"program": "${workspaceRoot}/node_modules/mocha/bin/_mocha",
"program":
"${workspaceRoot}/packages/apollo-client/node_modules/jest/bin/jest.js",
"internalConsoleOptions": "openOnSessionStart",
"stopOnEntry": false,
"args": [
"--no-timeouts",
"lib/test/tests.js"
],
"cwd": "${workspaceRoot}",
"runtimeExecutable": null,
"args": ["-i"],
"cwd": "${workspaceRoot}/packages/apollo-client",
"sourceMaps": true,
"outDir": "${workspaceRoot}/lib"
"outFiles": ["${workspaceRoot}/lib/**/*"]
}
]
}
1 change: 1 addition & 0 deletions packages/apollo-client/AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ John Pinkerton <[email protected]>
Jonas Helfer <[email protected]>
Jonas Helfer <[email protected]>
Kamil Kisiela <[email protected]>
Kamran Ayub <[email protected]>
Kerem Kazan <[email protected]>
Kiran Abburi <[email protected]>
Louis DeScioli <[email protected]>
Expand Down
1 change: 1 addition & 0 deletions packages/apollo-client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### 2.2.4
- Added `getCacheKey` function to the link context for use in state-link [PR#2998](https://github.com/apollographql/apollo-client/pull/2998)
- Fix `no-cache` fetch policy so it returns data [PR#3102](https://github.com/apollographql/apollo-client/pull/3102)
- Fix Memory Leak in Query Manager [PR#3119](https://github.com/apollographql/apollo-client/pull/3119)
- Pass non-optimistic query to `subscribeToMore` updateQuery
[PR#3068](https://github.com/apollographql/apollo-client/pull/3068)
Expand Down
9 changes: 7 additions & 2 deletions packages/apollo-client/src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,9 @@ export class ObservableQuery<T> extends Observable<ApolloQueryResult<T>> {
}

public refetch(variables?: any): Promise<ApolloQueryResult<T>> {
const { fetchPolicy } = this.options;
// early return if trying to read from cache during refetch
if (this.options.fetchPolicy === 'cache-only') {
if (fetchPolicy === 'cache-only') {
return Promise.reject(
new Error(
'cache-only fetchPolicy option should not be used together with query refetch.',
Expand All @@ -264,9 +265,13 @@ export class ObservableQuery<T> extends Observable<ApolloQueryResult<T>> {
}

// Override fetchPolicy for this call only
// only network-only and no-cache are safe to use
const isNetworkFetchPolicy =
fetchPolicy === 'network-only' || fetchPolicy === 'no-cache';

const combinedOptions: WatchQueryOptions = {
...this.options,
fetchPolicy: 'network-only',
fetchPolicy: isNetworkFetchPolicy ? fetchPolicy : 'network-only',
};

return this.queryManager
Expand Down
6 changes: 5 additions & 1 deletion packages/apollo-client/src/core/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1081,6 +1081,10 @@ export class QueryManager<TStore> {
reject(e);
return;
}
} else {
this.setQuery(queryId, () => ({
newData: { result: result.data, complete: true },
}));
}

this.queryStore.markQueryResult(
Expand All @@ -1105,7 +1109,7 @@ export class QueryManager<TStore> {
errorsFromStore = result.errors;
}

if (fetchMoreForQueryId) {
if (fetchMoreForQueryId || fetchPolicy === 'no-cache') {
// We don't write fetchMore results to the store because this would overwrite
// the original result in case an @connection directive is used.
resultFromStore = result.data;
Expand Down
78 changes: 77 additions & 1 deletion packages/apollo-client/src/core/__tests__/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { mockSingleLink } from '../../__mocks__/mockLinks';

import { ObservableQuery, ApolloCurrentResult } from '../ObservableQuery';
import { NetworkStatus } from '../networkStatus';
import { ApolloQueryResult } from '../types';
import { ApolloQueryResult, FetchType } from '../types';
import { QueryManager } from '../QueryManager';
import { DataStore } from '../../data/store';
import ApolloClient from '../../';
Expand Down Expand Up @@ -1149,6 +1149,82 @@ describe('ObservableQuery', () => {
});
});

describe('refetch', () => {
it('calls fetchRequest with fetchPolicy `network-only` when using a non-networked fetch policy', done => {
const mockedResponses = [
{
request: { query, variables },
result: { data: dataOne },
},
{
request: { query, variables: differentVariables },
result: { data: dataTwo },
},
];

const queryManager = mockQueryManager(...mockedResponses);
const firstRequest = mockedResponses[0].request;
const observable = queryManager.watchQuery({
query: firstRequest.query,
variables: firstRequest.variables,
fetchPolicy: 'cache-and-network',
});

const origFetchQuery = queryManager.fetchQuery;
queryManager.fetchQuery = jest.fn(() =>
origFetchQuery.apply(queryManager, arguments),
);

subscribeAndCount(done, observable, (handleCount, result) => {
if (handleCount === 1) {
observable.refetch(differentVariables);
} else if (handleCount === 3) {
expect(queryManager.fetchQuery.mock.calls[1][1].fetchPolicy).toEqual(
'network-only',
);
done();
}
});
});

it('calls fetchRequest with fetchPolicy `no-cache` when using `no-cache` fetch policy', done => {
const mockedResponses = [
{
request: { query, variables },
result: { data: dataOne },
},
{
request: { query, variables: differentVariables },
result: { data: dataTwo },
},
];

const queryManager = mockQueryManager(...mockedResponses);
const firstRequest = mockedResponses[0].request;
const observable = queryManager.watchQuery({
query: firstRequest.query,
variables: firstRequest.variables,
fetchPolicy: 'no-cache',
});

const origFetchQuery = queryManager.fetchQuery;
queryManager.fetchQuery = jest.fn(() =>
origFetchQuery.apply(queryManager, arguments),
);

subscribeAndCount(done, observable, (handleCount, result) => {
if (handleCount === 1) {
observable.refetch(differentVariables);
} else if (handleCount === 3) {
expect(queryManager.fetchQuery.mock.calls[1][1].fetchPolicy).toEqual(
'no-cache',
);
done();
}
});
});
});

describe('currentResult', () => {
it('returns the same value as observableQuery.next got', done => {
const queryWithFragment = gql`
Expand Down
22 changes: 22 additions & 0 deletions packages/apollo-client/src/core/__tests__/fetchPolicies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,28 @@ describe('network-only', () => {
});
});
describe('no-cache', () => {
it('requests from the network when not in cache', () => {
let called = 0;
const inspector = new ApolloLink((operation, forward) => {
called++;
return forward(operation).map(result => {
called++;
return result;
});
});

const client = new ApolloClient({
link: inspector.concat(createLink()),
cache: new InMemoryCache({ addTypename: false }),
});

return client
.query({ fetchPolicy: 'no-cache', query })
.then(actualResult => {
expect(actualResult.data).toEqual(result);
expect(called).toBe(2);
});
});
it('requests from the network even if already in cache', () => {
let called = 0;
const inspector = new ApolloLink((operation, forward) => {
Expand Down

0 comments on commit c4a1ad6

Please sign in to comment.