Skip to content

Commit 50dc13f

Browse files
authored
Update tests that check calls to internal QueryManager methods (#12573)
1 parent dde5f0c commit 50dc13f

File tree

5 files changed

+54
-108
lines changed

5 files changed

+54
-108
lines changed

.size-limits.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43438,
3-
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38878,
4-
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33207,
5-
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 28023
2+
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43424,
3+
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38812,
4+
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33179,
5+
"import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 28041
66
}

src/core/ObservableQuery.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,7 +1109,6 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
11091109
// We want to ensure we can re-run the custom document transforms the next
11101110
// time a request is made against the original query.
11111111
const query = this.transformDocument(options.query);
1112-
const { fetchPolicy } = options;
11131112

11141113
this.lastQuery = query;
11151114

@@ -1135,14 +1134,15 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
11351134
newOptions.variables &&
11361135
!equal(newOptions.variables, oldVariables) &&
11371136
// Don't mess with the fetchPolicy if it's currently "standby".
1138-
fetchPolicy !== "standby" &&
1137+
options.fetchPolicy !== "standby" &&
11391138
// If we're changing the fetchPolicy anyway, don't try to change it here
11401139
// using applyNextFetchPolicy. The explicit options.fetchPolicy wins.
1141-
(fetchPolicy === oldFetchPolicy ||
1140+
(options.fetchPolicy === oldFetchPolicy ||
11421141
// A `nextFetchPolicy` function has even higher priority, though,
11431142
// so in that case `applyNextFetchPolicy` must be called.
11441143
typeof options.nextFetchPolicy === "function")
11451144
) {
1145+
// This might mutate options.fetchPolicy
11461146
this.applyNextFetchPolicy("variables-changed", options);
11471147
if (newNetworkStatus === void 0) {
11481148
newNetworkStatus = NetworkStatus.setVariables;
@@ -1165,12 +1165,12 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
11651165

11661166
// QueryManager does not emit any values for standby fetch policies so we
11671167
// want ensure that the networkStatus remains ready.
1168-
if (fetchPolicy === "standby") {
1168+
if (options.fetchPolicy === "standby") {
11691169
newNetworkStatus = NetworkStatus.ready;
11701170
}
11711171
}
11721172

1173-
if (fetchPolicy === "standby") {
1173+
if (options.fetchPolicy === "standby") {
11741174
this.cancelPolling();
11751175
}
11761176

src/core/QueryManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ function validateDidEmitValue<T>() {
18931893
}
18941894

18951895
// Return types used by fetchQueryByPolicy and other private methods above.
1896-
export interface ObservableAndInfo<TData> {
1896+
interface ObservableAndInfo<TData> {
18971897
// Metadata properties that can be returned in addition to the Observable.
18981898
fromLink: boolean;
18991899
observable: Observable<ApolloQueryResult<TData>>;

src/core/__tests__/ObservableQuery.ts

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,6 @@ import {
2828
removeDirectivesFromDocument,
2929
} from "@apollo/client/utilities";
3030

31-
import type { ObservableAndInfo, QueryManager } from "../QueryManager.js";
32-
33-
export const mockFetchQuery = (queryManager: QueryManager) => {
34-
const mocks = {
35-
fetchObservableWithInfo: jest.fn<
36-
ObservableAndInfo<unknown>,
37-
Parameters<QueryManager["fetchObservableWithInfo"]>
38-
>(queryManager["fetchObservableWithInfo"].bind(queryManager)),
39-
fetchQueryByPolicy: jest.fn<
40-
ObservableAndInfo<unknown>,
41-
Parameters<QueryManager["fetchQueryByPolicy"]>
42-
>(queryManager["fetchQueryByPolicy"].bind(queryManager)),
43-
};
44-
45-
Object.assign(queryManager, mocks);
46-
47-
return mocks;
48-
};
49-
5031
describe("ObservableQuery", () => {
5132
// Standard data for all these tests
5233
const query: TypedDocumentNode<{
@@ -1597,34 +1578,29 @@ describe("ObservableQuery", () => {
15971578
});
15981579

15991580
describe("refetch", () => {
1581+
// TODO: If updating this to include a cache result for the changed
1582+
// variables, a cache value is emitted for the refetch, but I believe this
1583+
// should be undefined.
16001584
it("calls fetchRequest with fetchPolicy `network-only` when using a non-networked fetch policy", async () => {
1601-
const mockedResponses = [
1602-
{
1603-
request: { query, variables },
1604-
result: { data: dataOne },
1605-
delay: 20,
1606-
},
1607-
{
1608-
request: { query, variables: differentVariables },
1609-
result: { data: dataTwo },
1610-
delay: 20,
1611-
},
1612-
];
1613-
16141585
const client = new ApolloClient({
16151586
cache: new InMemoryCache(),
1616-
link: new MockLink(mockedResponses),
1587+
link: new MockLink([
1588+
{
1589+
request: { query, variables },
1590+
result: { data: dataOne },
1591+
},
1592+
{
1593+
request: { query, variables: differentVariables },
1594+
result: { data: dataTwo },
1595+
},
1596+
]),
16171597
});
1618-
const firstRequest = mockedResponses[0].request;
16191598
const observable = client.watchQuery({
1620-
query: firstRequest.query,
1621-
variables: firstRequest.variables,
1599+
query,
1600+
variables,
16221601
fetchPolicy: "cache-first",
16231602
});
16241603

1625-
// TODO: Determine if we can test this without reaching into internal
1626-
// implementation details
1627-
const mocks = mockFetchQuery(client["queryManager"]);
16281604
const stream = new ObservableStream(observable);
16291605

16301606
await expect(stream).toEmitTypedValue({
@@ -1657,20 +1633,6 @@ describe("ObservableQuery", () => {
16571633
partial: false,
16581634
});
16591635

1660-
const fqbpCalls = mocks.fetchQueryByPolicy.mock.calls;
1661-
expect(fqbpCalls.length).toBe(2);
1662-
expect(fqbpCalls[0][1].fetchPolicy).toEqual("cache-first");
1663-
expect(fqbpCalls[1][1].fetchPolicy).toEqual("network-only");
1664-
1665-
const fqoCalls = mocks.fetchObservableWithInfo.mock.calls;
1666-
expect(fqoCalls.length).toBe(2);
1667-
expect(fqoCalls[0][1].fetchPolicy).toEqual("cache-first");
1668-
expect(fqoCalls[1][1].fetchPolicy).toEqual("network-only");
1669-
1670-
// Although the options.fetchPolicy we passed just now to
1671-
// fetchQueryByPolicy should have been network-only,
1672-
// observable.options.fetchPolicy should now be updated to
1673-
// cache-first, thanks to options.nextFetchPolicy.
16741636
expect(observable.options.fetchPolicy).toBe("cache-first");
16751637

16761638
await expect(stream).not.toEmitAnything();

src/react/hooks/__tests__/useQuery.test.tsx

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ import {
4444
MockLink,
4545
mockSingleLink,
4646
MockSubscriptionLink,
47-
tick,
4847
wait,
4948
} from "@apollo/client/testing";
5049
import {
@@ -57,8 +56,6 @@ import type { Reference } from "@apollo/client/utilities";
5756
import { concatPagination } from "@apollo/client/utilities";
5857
import { InvariantError } from "@apollo/client/utilities/invariant";
5958

60-
import type { QueryManager } from "../../../core/QueryManager.js";
61-
6259
const IS_REACT_17 = React.version.startsWith("17");
6360
const IS_REACT_18 = React.version.startsWith("18");
6461

@@ -7426,20 +7423,20 @@ describe("useQuery Hook", () => {
74267423

74277424
it("should prioritize a `nextFetchPolicy` function over a `fetchPolicy` option when changing variables", async () => {
74287425
const query = gql`
7429-
{
7430-
hello
7426+
query ($id: ID!) {
7427+
user(id: $id) {
7428+
id
7429+
name
7430+
}
74317431
}
74327432
`;
74337433
const link = new MockLink([
74347434
{
7435-
request: { query, variables: { id: 1 } },
7436-
result: { data: { hello: "from link" } },
7437-
delay: 10,
7438-
},
7439-
{
7440-
request: { query, variables: { id: 2 } },
7441-
result: { data: { hello: "from link2" } },
7442-
delay: 10,
7435+
request: { query, variables: () => true },
7436+
result: ({ id }) => ({
7437+
data: { user: { __typename: "User", id, name: `User ${id}` } },
7438+
}),
7439+
maxUsageCount: Number.POSITIVE_INFINITY,
74437440
},
74447441
]);
74457442

@@ -7448,26 +7445,17 @@ describe("useQuery Hook", () => {
74487445
link,
74497446
});
74507447

7451-
const fetchQueryByPolicy = jest.spyOn(
7452-
client["queryManager"] as any as {
7453-
fetchQueryByPolicy: QueryManager["fetchQueryByPolicy"];
7454-
},
7455-
"fetchQueryByPolicy"
7456-
);
7448+
client.writeQuery({
7449+
query,
7450+
variables: { id: 1 },
7451+
data: { user: { __typename: "User", id: 1, name: "Cached User 1" } },
7452+
});
7453+
client.writeQuery({
7454+
query,
7455+
variables: { id: 2 },
7456+
data: { user: { __typename: "User", id: 2, name: "Cached User 2" } },
7457+
});
74577458

7458-
const expectQueryTriggered = (
7459-
nth: number,
7460-
fetchPolicy: WatchQueryFetchPolicy
7461-
) => {
7462-
expect(fetchQueryByPolicy).toHaveBeenCalledTimes(nth);
7463-
expect(fetchQueryByPolicy).toHaveBeenNthCalledWith(
7464-
nth,
7465-
expect.anything(),
7466-
expect.objectContaining({ fetchPolicy }),
7467-
expect.any(Number),
7468-
expect.any(Boolean)
7469-
);
7470-
};
74717459
const nextFetchPolicy: WatchQueryOptions<
74727460
OperationVariables,
74737461
any
@@ -7499,11 +7487,7 @@ describe("useQuery Hook", () => {
74997487
}
75007488
);
75017489

7502-
await tick();
7503-
7504-
// first network request triggers with initial fetchPolicy
7505-
expectQueryTriggered(1, "network-only");
7506-
7490+
// We skip the cache and go to the network
75077491
await expect(takeSnapshot()).resolves.toStrictEqualTyped({
75087492
data: undefined,
75097493
loading: true,
@@ -7513,7 +7497,7 @@ describe("useQuery Hook", () => {
75137497
});
75147498

75157499
await expect(takeSnapshot()).resolves.toStrictEqualTyped({
7516-
data: { hello: "from link" },
7500+
data: { user: { __typename: "User", id: 1, name: "User 1" } },
75177501
loading: false,
75187502
networkStatus: NetworkStatus.ready,
75197503
previousData: undefined,
@@ -7545,23 +7529,23 @@ describe("useQuery Hook", () => {
75457529
reason: "variables-changed",
75467530
})
75477531
);
7548-
// the return value of `nextFetchPolicy(..., {reason: "variables-changed"})`
7549-
expectQueryTriggered(2, "cache-and-network");
75507532

7533+
// We now see the effects of cache-and-network applied
75517534
await expect(takeSnapshot()).resolves.toStrictEqualTyped({
7552-
// TODO: Shouldn't this be undefined?
7553-
data: { hello: "from link" },
7535+
data: { user: { __typename: "User", id: 2, name: "Cached User 2" } },
75547536
loading: true,
75557537
networkStatus: NetworkStatus.setVariables,
7556-
previousData: { hello: "from link" },
7538+
previousData: { user: { __typename: "User", id: 1, name: "User 1" } },
75577539
variables: { id: 2 },
75587540
});
75597541

75607542
await expect(takeSnapshot()).resolves.toStrictEqualTyped({
7561-
data: { hello: "from link2" },
7543+
data: { user: { __typename: "User", id: 2, name: "User 2" } },
75627544
loading: false,
75637545
networkStatus: NetworkStatus.ready,
7564-
previousData: { hello: "from link" },
7546+
previousData: {
7547+
user: { __typename: "User", id: 2, name: "Cached User 2" },
7548+
},
75657549
variables: { id: 2 },
75667550
});
75677551

0 commit comments

Comments
 (0)