11import { gql } from "graphql-tag" ;
22import { assign , cloneDeep } from "lodash" ;
3- import { Observable } from "rxjs" ;
3+ import { delay , Observable , of } from "rxjs" ;
44
55import type { TypedDocumentNode } from "@apollo/client" ;
66import {
@@ -22,6 +22,7 @@ import {
2222 mockDeferStream ,
2323 ObservableStream ,
2424 setupPaginatedCase ,
25+ withCacheSizes ,
2526} from "@apollo/client/testing/internal" ;
2627import {
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+
26892850function commentsInRange (
26902851 start : number ,
26912852 end : number ,
0 commit comments