Skip to content

Commit a8b1c37

Browse files
committed
Add failing test for fetchMore with full cache
1 parent 3e56597 commit a8b1c37

1 file changed

Lines changed: 162 additions & 1 deletion

File tree

src/__tests__/fetchMore.ts

Lines changed: 162 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { gql } from "graphql-tag";
22
import { assign, cloneDeep } from "lodash";
3-
import { Observable } from "rxjs";
3+
import { delay, Observable, of } from "rxjs";
44

55
import type { TypedDocumentNode } from "@apollo/client";
66
import {
@@ -22,6 +22,7 @@ import {
2222
mockDeferStream,
2323
ObservableStream,
2424
setupPaginatedCase,
25+
withCacheSizes,
2526
} from "@apollo/client/testing/internal";
2627
import {
2728
concatPagination,
@@ -2686,6 +2687,166 @@ test("does not allow fetchMore on a cache-only query", async () => {
26862687
await expect(stream).not.toEmitAnything();
26872688
});
26882689

2690+
// https://github.com/apollographql/apollo-client/issues/12932
2691+
test("emits final result from fetchMore when executeSubSelectedArray cache is full", async () => {
2692+
using _ = withCacheSizes({ "inMemoryCache.executeSubSelectedArray": 10 });
2693+
2694+
const itemData = Array(20)
2695+
.fill(undefined)
2696+
.map((_, index) => ({
2697+
__typename: "Item" as const,
2698+
id: index.toString(),
2699+
attributes: ["data"],
2700+
}));
2701+
type GetCommentsData = {
2702+
items: Array<{
2703+
__typename: "Item";
2704+
id: string;
2705+
attributes: string[];
2706+
}>;
2707+
};
2708+
2709+
type GetCommentsVariables = {
2710+
offset: number;
2711+
limit: number;
2712+
};
2713+
2714+
const query: TypedDocumentNode<GetCommentsData, GetCommentsVariables> = gql`
2715+
query GetComments($offset: Int!, $limit: Int!) {
2716+
items(offset: $offset, limit: $limit) {
2717+
id
2718+
attributes
2719+
}
2720+
}
2721+
`;
2722+
2723+
const client = new ApolloClient({
2724+
cache: new InMemoryCache({
2725+
typePolicies: {
2726+
Query: {
2727+
fields: {
2728+
items: offsetLimitPagination(),
2729+
},
2730+
},
2731+
},
2732+
}),
2733+
link: new ApolloLink((operation) => {
2734+
const { offset, limit } = operation.variables;
2735+
2736+
return of({
2737+
data: {
2738+
items: itemData.slice(offset, offset + limit),
2739+
},
2740+
}).pipe(delay(10));
2741+
}),
2742+
});
2743+
2744+
const observable = client.watchQuery({
2745+
query,
2746+
variables: { offset: 0, limit: 10 },
2747+
});
2748+
const stream = new ObservableStream(observable);
2749+
2750+
await expect(stream).toEmitTypedValue({
2751+
data: undefined,
2752+
dataState: "empty",
2753+
loading: true,
2754+
networkStatus: NetworkStatus.loading,
2755+
partial: true,
2756+
});
2757+
2758+
await expect(stream).toEmitTypedValue({
2759+
data: { items: itemData.slice(0, 10) },
2760+
dataState: "complete",
2761+
loading: false,
2762+
networkStatus: NetworkStatus.ready,
2763+
partial: false,
2764+
});
2765+
2766+
await expect(
2767+
observable.fetchMore({
2768+
variables: {
2769+
offset: stream.getCurrent()?.data?.items?.length ?? 0,
2770+
limit: 5,
2771+
},
2772+
})
2773+
).resolves.toStrictEqualTyped({
2774+
data: { items: itemData.slice(10, 15) },
2775+
});
2776+
2777+
await expect(stream).toEmitTypedValue({
2778+
data: { items: itemData.slice(0, 10) },
2779+
dataState: "complete",
2780+
loading: true,
2781+
networkStatus: NetworkStatus.fetchMore,
2782+
partial: false,
2783+
});
2784+
2785+
await expect(stream).toEmitTypedValue({
2786+
data: { items: itemData.slice(0, 15) },
2787+
dataState: "complete",
2788+
loading: false,
2789+
networkStatus: NetworkStatus.ready,
2790+
partial: false,
2791+
});
2792+
2793+
await expect(
2794+
observable.fetchMore({
2795+
variables: {
2796+
offset: stream.getCurrent()?.data?.items?.length ?? 0,
2797+
limit: 5,
2798+
},
2799+
})
2800+
).resolves.toStrictEqualTyped({
2801+
data: { items: itemData.slice(15, 20) },
2802+
});
2803+
2804+
await expect(stream).toEmitTypedValue({
2805+
data: { items: itemData.slice(0, 15) },
2806+
dataState: "complete",
2807+
loading: true,
2808+
networkStatus: NetworkStatus.fetchMore,
2809+
partial: false,
2810+
});
2811+
2812+
await expect(stream).toEmitTypedValue({
2813+
data: { items: itemData.slice(0, 20) },
2814+
dataState: "complete",
2815+
loading: false,
2816+
networkStatus: NetworkStatus.ready,
2817+
partial: false,
2818+
});
2819+
2820+
await expect(
2821+
observable.fetchMore({
2822+
variables: {
2823+
offset: stream.getCurrent()?.data?.items?.length ?? 0,
2824+
limit: 5,
2825+
},
2826+
})
2827+
).resolves.toStrictEqualTyped({
2828+
data: { items: [] },
2829+
});
2830+
2831+
await expect(stream).toEmitTypedValue({
2832+
data: { items: itemData.slice(0, 20) },
2833+
dataState: "complete",
2834+
loading: true,
2835+
networkStatus: NetworkStatus.fetchMore,
2836+
partial: false,
2837+
});
2838+
2839+
await expect(stream).toEmitTypedValue({
2840+
data: { items: itemData.slice(0, 20) },
2841+
dataState: "complete",
2842+
loading: false,
2843+
networkStatus: NetworkStatus.ready,
2844+
partial: false,
2845+
});
2846+
2847+
await expect(stream).not.toEmitAnything();
2848+
});
2849+
26892850
function commentsInRange(
26902851
start: number,
26912852
end: number,

0 commit comments

Comments
 (0)