Skip to content

Commit

Permalink
Fix emitted fetchMore result from observableQuery for no-cache qu…
Browse files Browse the repository at this point in the history
…eries (#12351)
  • Loading branch information
jerelmiller authored Feb 7, 2025
1 parent a24ef94 commit 3da908b
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/curvy-ads-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@apollo/client": patch
---

Fixes an issue where the wrong `networkStatus` and `loading` value was emitted from `observableQuery` when calling `fetchMore` with a `no-cache` fetch policy. The `networkStatus` now properly reports as `ready` and `loading` as `false` after the result is returned.
4 changes: 2 additions & 2 deletions .size-limits.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dist/apollo-client.min.cjs": 41642,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34385
"dist/apollo-client.min.cjs": 41649,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 34394
}
139 changes: 138 additions & 1 deletion src/__tests__/fetchMore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from "../cache";

import { MockedResponse, mockSingleLink } from "../testing";
import { ObservableStream } from "../testing/internal";
import { ObservableStream, setupPaginatedCase } from "../testing/internal";

describe("updateQuery on a simple query", () => {
const query = gql`
Expand Down Expand Up @@ -1789,3 +1789,140 @@ describe("fetchMore on an observable query with connection", () => {
});
});
});

test("uses updateQuery to update the result of the query with no-cache queries", async () => {
const { query, link } = setupPaginatedCase();

const client = new ApolloClient({ cache: new InMemoryCache(), link });

const observable = client.watchQuery({
query,
fetchPolicy: "no-cache",
notifyOnNetworkStatusChange: true,
variables: { limit: 2 },
});

const stream = new ObservableStream(observable);

await expect(stream).toEmitApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "A", position: 1 },
{ __typename: "Letter", letter: "B", position: 2 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

let fetchMoreResult = await observable.fetchMore({
variables: { offset: 2 },
updateQuery: (prev, { fetchMoreResult }) => ({
letters: prev.letters.concat(fetchMoreResult.letters),
}),
});

expect(fetchMoreResult).toEqualApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "C", position: 3 },
{ __typename: "Letter", letter: "D", position: 4 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

await expect(stream).toEmitApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "A", position: 1 },
{ __typename: "Letter", letter: "B", position: 2 },
],
},
loading: true,
networkStatus: NetworkStatus.fetchMore,
});

await expect(stream).toEmitApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "A", position: 1 },
{ __typename: "Letter", letter: "B", position: 2 },
{ __typename: "Letter", letter: "C", position: 3 },
{ __typename: "Letter", letter: "D", position: 4 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

// Ensure we store the merged result as the last result
expect(observable.getCurrentResult(false)).toEqualApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "A", position: 1 },
{ __typename: "Letter", letter: "B", position: 2 },
{ __typename: "Letter", letter: "C", position: 3 },
{ __typename: "Letter", letter: "D", position: 4 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

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

fetchMoreResult = await observable.fetchMore({
variables: { offset: 4 },
updateQuery: (_, { fetchMoreResult }) => fetchMoreResult,
});

expect(fetchMoreResult).toEqualApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "E", position: 5 },
{ __typename: "Letter", letter: "F", position: 6 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

await expect(stream).toEmitApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "A", position: 1 },
{ __typename: "Letter", letter: "B", position: 2 },
{ __typename: "Letter", letter: "C", position: 3 },
{ __typename: "Letter", letter: "D", position: 4 },
],
},
loading: true,
networkStatus: NetworkStatus.fetchMore,
});

await expect(stream).toEmitApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "E", position: 5 },
{ __typename: "Letter", letter: "F", position: 6 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

expect(observable.getCurrentResult(false)).toEqualApolloQueryResult({
data: {
letters: [
{ __typename: "Letter", letter: "E", position: 5 },
{ __typename: "Letter", letter: "F", position: 6 },
],
},
loading: false,
networkStatus: NetworkStatus.ready,
});

await expect(stream).not.toEmitAnything();
});
7 changes: 6 additions & 1 deletion src/core/ObservableQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,12 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`,
});

this.reportResult(
{ ...lastResult, data: data as TData },
{
...lastResult,
networkStatus: originalNetworkStatus!,
loading: isNetworkRequestInFlight(originalNetworkStatus),
data: data as TData,
},
this.variables
);
}
Expand Down

0 comments on commit 3da908b

Please sign in to comment.