From 9f893553311323eb747f0250247b088afb8fc263 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Thu, 18 Jun 2020 15:02:37 -0400 Subject: [PATCH] Run fetchMore tests using both updateQuery and field policies. Once we remove the deprecated updateQuery function, we can remove those tests, but it seems important to test both styles for now. --- src/__tests__/fetchMore.ts | 674 ++++++++++++++------ src/react/hooks/__tests__/useQuery.test.tsx | 293 ++++++--- 2 files changed, 682 insertions(+), 285 deletions(-) diff --git a/src/__tests__/fetchMore.ts b/src/__tests__/fetchMore.ts index 595c68385dc..17aeecd18df 100644 --- a/src/__tests__/fetchMore.ts +++ b/src/__tests__/fetchMore.ts @@ -3,10 +3,10 @@ import gql from 'graphql-tag'; import { mockSingleLink } from '../utilities/testing/mocking/mockLink'; import subscribeAndCount from '../utilities/testing/subscribeAndCount'; -import { InMemoryCache } from '../cache/inmemory/inMemoryCache'; +import { InMemoryCache, InMemoryCacheConfig } from '../cache/inmemory/inMemoryCache'; import { ApolloClient, NetworkStatus, ObservableQuery } from '../'; import { itAsync } from '../utilities/testing/itAsync'; -import { offsetLimitPagination } from '../utilities'; +import { offsetLimitPagination, concatPagination } from '../utilities'; describe('updateQuery on a simple query', () => { const query = gql` @@ -233,82 +233,181 @@ describe('fetchMore on an observable query', () => { }); } - itAsync('triggers new result withAsync new variables', (resolve, reject) => { - const observable = setup(reject, { - request: { - query, - variables: variablesMore, - }, - result: resultMore, + function setupWithCacheConfig( + reject: (reason: any) => any, + cacheConfig: InMemoryCacheConfig, + ...mockedResponses: any[] + ) { + const client = new ApolloClient({ + link: mockSingleLink({ + request: { + query, + variables, + }, + result, + }, ...mockedResponses).setOnError(reject), + cache: new InMemoryCache(cacheConfig), }); - let latestResult: any; - observable.subscribe({ - next(result: any) { - latestResult = result; - }, + return client.watchQuery({ + query, + variables, }); + } - return observable.fetchMore({ - // Rely on the fact that the original variables had limit: 10 - variables: { start: 10 }, - updateQuery: (prev, options) => { - expect(options.variables).toEqual(variablesMore); + describe('triggers new result with async new variables', () => { + itAsync('updateQuery', (resolve, reject) => { + const observable = setup(reject, { + request: { + query, + variables: variablesMore, + }, + result: resultMore, + }); - const state = cloneDeep(prev) as any; - state.entry.comments = [ - ...state.entry.comments, - ...(options.fetchMoreResult as any).entry.comments, - ]; - return state; - }, - }).then(data => { - // This is the server result - expect(data.data.entry.comments).toHaveLength(10); - expect(data.loading).toBe(false); - const comments = latestResult.data.entry.comments; - expect(comments).toHaveLength(20); - for (let i = 1; i <= 20; i++) { - expect(comments[i - 1].text).toEqual(`comment ${i}`); - } - }).then(resolve, reject); - }); + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + // Rely on the fact that the original variables had limit: 10 + variables: { start: 10 }, + updateQuery: (prev, options) => { + expect(options.variables).toEqual(variablesMore); + + const state = cloneDeep(prev) as any; + state.entry.comments = [ + ...state.entry.comments, + ...(options.fetchMoreResult as any).entry.comments, + ]; + return state; + }, + }).then(data => { + // This is the server result + expect(data.data.entry.comments).toHaveLength(10); + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toEqual(`comment ${i}`); + } + }).then(resolve, reject); + }); - itAsync('basic fetchMore results merging', (resolve, reject) => { - const observable = setup(reject, { - request: { - query, - variables: variablesMore, - }, - result: resultMore, + itAsync('field policy', (resolve, reject) => { + const observable = setupWithCacheConfig(reject, { + typePolicies: { + Entry: { + fields: { + comments: concatPagination(), + }, + }, + }, + }, { + request: { query, variables: variablesMore }, + result: resultMore, + }); + + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + // Rely on the fact that the original variables had limit: 10 + variables: { start: 10 }, + }).then(data => { + // This is the server result + expect(data.data.entry.comments).toHaveLength(10); + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toEqual(`comment ${i}`); + } + }).then(resolve, reject); }); + }); - let latestResult: any; - observable.subscribe({ - next(result: any) { - latestResult = result; - }, + describe('basic fetchMore results merging', () => { + itAsync('updateQuery', (resolve, reject) => { + const observable = setup(reject, { + request: { + query, + variables: variablesMore, + }, + result: resultMore, + }); + + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 + updateQuery: (prev, options) => { + const state = cloneDeep(prev) as any; + state.entry.comments = [ + ...state.entry.comments, + ...(options.fetchMoreResult as any).entry.comments, + ]; + return state; + }, + }).then(data => { + expect(data.data.entry.comments).toHaveLength(10); // this is the server result + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toEqual(`comment ${i}`); + } + }).then(resolve, reject); }); - return observable.fetchMore({ - variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 - updateQuery: (prev, options) => { - const state = cloneDeep(prev) as any; - state.entry.comments = [ - ...state.entry.comments, - ...(options.fetchMoreResult as any).entry.comments, - ]; - return state; - }, - }).then(data => { - expect(data.data.entry.comments).toHaveLength(10); // this is the server result - expect(data.loading).toBe(false); - const comments = latestResult.data.entry.comments; - expect(comments).toHaveLength(20); - for (let i = 1; i <= 20; i++) { - expect(comments[i - 1].text).toEqual(`comment ${i}`); - } - }).then(resolve, reject); + itAsync('field policy', (resolve, reject) => { + const observable = setupWithCacheConfig(reject, { + typePolicies: { + Entry: { + fields: { + comments: concatPagination(), + }, + }, + }, + }, { + request: { + query, + variables: variablesMore, + }, + result: resultMore, + }); + + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 + }).then(data => { + expect(data.data.entry.comments).toHaveLength(10); // this is the server result + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toEqual(`comment ${i}`); + } + }).then(resolve, reject); + }); }); itAsync('fetchMore passes new args to field merge function', (resolve, reject) => { @@ -513,57 +612,128 @@ describe('fetchMore on an observable query', () => { }).then(resolve, reject); }); - itAsync('will not get an error from `fetchMore` if thrown', (resolve, reject) => { - const fetchMoreError = new Error('Uh, oh!'); - const link = mockSingleLink({ - request: { query, variables }, - result, - delay: 5, - }, { - request: { query, variables: variablesMore }, - error: fetchMoreError, - delay: 5, - }).setOnError(reject); + describe('will not get an error from `fetchMore` if thrown', () => { + itAsync('updateQuery', (resolve, reject) => { + const fetchMoreError = new Error('Uh, oh!'); + const link = mockSingleLink({ + request: { query, variables }, + result, + delay: 5, + }, { + request: { query, variables: variablesMore }, + error: fetchMoreError, + delay: 5, + }).setOnError(reject); - const client = new ApolloClient({ - link, - cache: new InMemoryCache(), - }); + const client = new ApolloClient({ + link, + cache: new InMemoryCache(), + }); - const observable = client.watchQuery({ - query, - variables, - notifyOnNetworkStatusChange: true, + const observable = client.watchQuery({ + query, + variables, + notifyOnNetworkStatusChange: true, + }); + + let count = 0; + observable.subscribe({ + next: ({ data, networkStatus }) => { + switch (++count) { + case 1: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(10); + observable.fetchMore({ + variables: { start: 10 }, + updateQuery: prev => { + reject(new Error("should not have called updateQuery")); + return prev; + }, + }).catch(e => { + expect(e.networkError).toBe(fetchMoreError); + resolve(); + }); + break; + } + }, + error: () => { + reject(new Error('`error` called when it wasn’t supposed to be.')); + }, + complete: () => { + reject( + new Error('`complete` called when it wasn’t supposed to be.'), + ); + }, + }); }); - let count = 0; - observable.subscribe({ - next: ({ data, networkStatus }) => { - switch (++count) { - case 1: - expect(networkStatus).toBe(NetworkStatus.ready); - expect((data as any).entry.comments.length).toBe(10); - observable.fetchMore({ - variables: { start: 10 }, - updateQuery: prev => { - reject(new Error("should not have called updateQuery")); - return prev; + itAsync('field policy', (resolve, reject) => { + const fetchMoreError = new Error('Uh, oh!'); + const link = mockSingleLink({ + request: { query, variables }, + result, + delay: 5, + }, { + request: { query, variables: variablesMore }, + error: fetchMoreError, + delay: 5, + }).setOnError(reject); + + let calledFetchMore = false; + + const client = new ApolloClient({ + link, + cache: new InMemoryCache({ + typePolicies: { + Entry: { + fields: { + comments: { + keyArgs: false, + merge(_, incoming) { + if (calledFetchMore) { + reject(new Error("should not have called merge")); + } + return incoming; + }, + }, + }, }, - }).catch(e => { - expect(e.networkError).toBe(fetchMoreError); - resolve(); - }); - break; - } - }, - error: () => { - reject(new Error('`error` called when it wasn’t supposed to be.')); - }, - complete: () => { - reject( - new Error('`complete` called when it wasn’t supposed to be.'), - ); - }, + }, + }), + }); + + const observable = client.watchQuery({ + query, + variables, + notifyOnNetworkStatusChange: true, + }); + + let count = 0; + observable.subscribe({ + next: ({ data, networkStatus }) => { + switch (++count) { + case 1: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(10); + calledFetchMore = true; + observable.fetchMore({ + variables: { start: 10 }, + }).catch(e => { + expect(e.networkError).toBe(fetchMoreError); + resolve(); + }); + break; + } + }, + error: () => { + reject(new Error('`error` called when it wasn’t supposed to be.')); + }, + complete: () => { + reject( + new Error('`complete` called when it wasn’t supposed to be.'), + ); + }, + }); }); }); @@ -679,95 +849,213 @@ describe('fetchMore on an observable query with connection', () => { }); } - itAsync('fetchMore with connection results merging', (resolve, reject) => { - const observable = setup(reject, { - request: { - query: transformedQuery, - variables: variablesMore, - }, - result: resultMore, - }) + function setupWithCacheConfig( + reject: (reason: any) => any, + cacheConfig: InMemoryCacheConfig, + ...mockedResponses: any[] + ) { + const client = new ApolloClient({ + link: mockSingleLink({ + request: { + query: transformedQuery, + variables, + }, + result, + }, ...mockedResponses).setOnError(reject), + cache: new InMemoryCache(cacheConfig), + }); - let latestResult: any; - observable.subscribe({ - next(result: any) { - latestResult = result; - }, + return client.watchQuery({ + query, + variables, }); + } - return observable.fetchMore({ - variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 - updateQuery: (prev, options) => { - const state = cloneDeep(prev) as any; - state.entry.comments = [ - ...state.entry.comments, - ...(options.fetchMoreResult as any).entry.comments, - ]; - return state; - }, - }).then(data => { - expect(data.data.entry.comments).toHaveLength(10); // this is the server result - expect(data.loading).toBe(false); - const comments = latestResult.data.entry.comments; - expect(comments).toHaveLength(20); - for (let i = 1; i <= 20; i++) { - expect(comments[i - 1].text).toBe(`comment ${i}`); - } - }).then(resolve, reject); - }); + describe('fetchMore with connection results merging', () => { + itAsync('updateQuery', (resolve, reject) => { + const observable = setup(reject, { + request: { + query: transformedQuery, + variables: variablesMore, + }, + result: resultMore, + }) - itAsync('will set the network status to `fetchMore`', (resolve, reject) => { - const link = mockSingleLink({ - request: { query: transformedQuery, variables }, - result, - delay: 5, - }, { - request: { query: transformedQuery, variables: variablesMore }, - result: resultMore, - delay: 5, - }).setOnError(reject); + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 + updateQuery: (prev, options) => { + const state = cloneDeep(prev) as any; + state.entry.comments = [ + ...state.entry.comments, + ...(options.fetchMoreResult as any).entry.comments, + ]; + return state; + }, + }).then(data => { + expect(data.data.entry.comments).toHaveLength(10); // this is the server result + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toBe(`comment ${i}`); + } + }).then(resolve, reject); + }); - const client = new ApolloClient({ - link, - cache: new InMemoryCache(), + itAsync('field policy', (resolve, reject) => { + const observable = setupWithCacheConfig(reject, { + typePolicies: { + Entry: { + fields: { + comments: concatPagination(), + }, + }, + }, + }, { + request: { + query: transformedQuery, + variables: variablesMore, + }, + result: resultMore, + }) + + let latestResult: any; + observable.subscribe({ + next(result: any) { + latestResult = result; + }, + }); + + return observable.fetchMore({ + variables: { start: 10 }, // rely on the fact that the original variables had limit: 10 + }).then(data => { + expect(data.data.entry.comments).toHaveLength(10); // this is the server result + expect(data.loading).toBe(false); + const comments = latestResult.data.entry.comments; + expect(comments).toHaveLength(20); + for (let i = 1; i <= 20; i++) { + expect(comments[i - 1].text).toBe(`comment ${i}`); + } + }).then(resolve, reject); }); + }); - const observable = client.watchQuery({ - query, - variables, - notifyOnNetworkStatusChange: true, + describe('will set the network status to `fetchMore`', () => { + itAsync('updateQuery', (resolve, reject) => { + const link = mockSingleLink({ + request: { query: transformedQuery, variables }, + result, + delay: 5, + }, { + request: { query: transformedQuery, variables: variablesMore }, + result: resultMore, + delay: 5, + }).setOnError(reject); + + const client = new ApolloClient({ + link, + cache: new InMemoryCache(), + }); + + const observable = client.watchQuery({ + query, + variables, + notifyOnNetworkStatusChange: true, + }); + + let count = 0; + observable.subscribe({ + next: ({ data, networkStatus }) => { + switch (count++) { + case 0: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(10); + observable.fetchMore({ + variables: { start: 10 }, + updateQuery: (prev: any, options: any) => { + const state = cloneDeep(prev) as any; + state.entry.comments = [ + ...state.entry.comments, + ...(options.fetchMoreResult as any).entry.comments, + ]; + return state; + }, + }); + break; + case 1: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(20); + resolve(); + break; + default: + reject(new Error('`next` called too many times')); + } + }, + error: (error: any) => reject(error), + complete: () => reject(new Error('Should not have completed')), + }); }); - let count = 0; - observable.subscribe({ - next: ({ data, networkStatus }) => { - switch (count++) { - case 0: - expect(networkStatus).toBe(NetworkStatus.ready); - expect((data as any).entry.comments.length).toBe(10); - observable.fetchMore({ - variables: { start: 10 }, - updateQuery: (prev: any, options: any) => { - const state = cloneDeep(prev) as any; - state.entry.comments = [ - ...state.entry.comments, - ...(options.fetchMoreResult as any).entry.comments, - ]; - return state; + itAsync('field policy', (resolve, reject) => { + const link = mockSingleLink({ + request: { query: transformedQuery, variables }, + result, + delay: 5, + }, { + request: { query: transformedQuery, variables: variablesMore }, + result: resultMore, + delay: 5, + }).setOnError(reject); + + const client = new ApolloClient({ + link, + cache: new InMemoryCache({ + typePolicies: { + Entry: { + fields: { + comments: concatPagination(), }, - }); - break; - case 1: - expect(networkStatus).toBe(NetworkStatus.ready); - expect((data as any).entry.comments.length).toBe(20); - resolve(); - break; - default: - reject(new Error('`next` called too many times')); - } - }, - error: (error: any) => reject(error), - complete: () => reject(new Error('Should not have completed')), + }, + }, + }), + }); + + const observable = client.watchQuery({ + query, + variables, + notifyOnNetworkStatusChange: true, + }); + + let count = 0; + observable.subscribe({ + next: ({ data, networkStatus }) => { + switch (count++) { + case 0: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(10); + observable.fetchMore({ + variables: { start: 10 }, + }); + break; + case 1: + expect(networkStatus).toBe(NetworkStatus.ready); + expect((data as any).entry.comments.length).toBe(20); + resolve(); + break; + default: + reject(new Error('`next` called too many times')); + } + }, + error: (error: any) => reject(error), + complete: () => reject(new Error('Should not have completed')), + }); }); }); }); diff --git a/src/react/hooks/__tests__/useQuery.test.tsx b/src/react/hooks/__tests__/useQuery.test.tsx index 58c78775405..cb1cfa081f4 100644 --- a/src/react/hooks/__tests__/useQuery.test.tsx +++ b/src/react/hooks/__tests__/useQuery.test.tsx @@ -16,6 +16,7 @@ import { useMutation } from '../useMutation'; import { QueryFunctionOptions } from '../..'; import { NetworkStatus } from '../../../core/networkStatus'; import { Reference } from '../../../utilities/graphql/storeUtils'; +import { concatPagination } from '../../../utilities'; describe('useQuery Hook', () => { const CAR_QUERY: DocumentNode = gql` @@ -1117,57 +1118,55 @@ describe('useQuery Hook', () => { }); describe('Pagination', () => { - itAsync( - 'should render `fetchMore.updateQuery` updated results with proper ' + - 'loading status, when `notifyOnNetworkStatusChange` is true', - (resolve, reject) => { - const carQuery: DocumentNode = gql` - query cars($limit: Int) { - cars(limit: $limit) { - id - make - model - vin - __typename - } + describe('should render fetchMore-updated results with proper loading status, when `notifyOnNetworkStatusChange` is true', () => { + const carQuery: DocumentNode = gql` + query cars($limit: Int) { + cars(limit: $limit) { + id + make + model + vin + __typename } - `; - - const carResults = { - cars: [ - { - id: 1, - make: 'Audi', - model: 'RS8', - vin: 'DOLLADOLLABILL', - __typename: 'Car' - } - ] - }; - - const moreCarResults = { - cars: [ - { - id: 2, - make: 'Audi', - model: 'eTron', - vin: 'TREESRGOOD', - __typename: 'Car' - } - ] - }; + } + `; - const mocks = [ + const carResults = { + cars: [ { - request: { query: carQuery, variables: { limit: 1 } }, - result: { data: carResults } - }, + id: 1, + make: 'Audi', + model: 'RS8', + vin: 'DOLLADOLLABILL', + __typename: 'Car' + } + ] + }; + + const moreCarResults = { + cars: [ { - request: { query: carQuery, variables: { limit: 1 } }, - result: { data: moreCarResults } + id: 2, + make: 'Audi', + model: 'eTron', + vin: 'TREESRGOOD', + __typename: 'Car' } - ]; + ] + }; + + const mocks = [ + { + request: { query: carQuery, variables: { limit: 1 } }, + result: { data: carResults } + }, + { + request: { query: carQuery, variables: { limit: 1 } }, + result: { data: moreCarResults } + } + ]; + itAsync('updateQuery', (resolve, reject) => { let renderCount = 0; function App() { const { loading, data, fetchMore } = useQuery(carQuery, { @@ -1218,60 +1217,115 @@ describe('useQuery Hook', () => { return wait(() => { expect(renderCount).toBe(3); }).then(resolve, reject); - } - ); + }); - itAsync( - 'should render `fetchMore.updateQuery` updated results with no ' + - 'loading status, when `notifyOnNetworkStatusChange` is false', - (resolve, reject) => { - const carQuery: DocumentNode = gql` - query cars($limit: Int) { - cars(limit: $limit) { - id - make - model - vin - __typename - } + itAsync('field policy', (resolve, reject) => { + let renderCount = 0; + function App() { + const { loading, data, fetchMore } = useQuery(carQuery, { + variables: { limit: 1 }, + notifyOnNetworkStatusChange: true + }); + + switch (++renderCount) { + case 1: + expect(loading).toBeTruthy(); + break; + case 2: + expect(loading).toBeFalsy(); + expect(data).toEqual(carResults); + fetchMore({ + variables: { + limit: 1 + }, + }); + break; + case 3: + expect(loading).toBeFalsy(); + expect(data).toEqual({ + cars: [ + carResults.cars[0], + moreCarResults.cars[0], + ], + }); + break; + default: } - `; - const carResults = { - cars: [ - { - id: 1, - make: 'Audi', - model: 'RS8', - vin: 'DOLLADOLLABILL', - __typename: 'Car' - } - ] - }; + return null; + } - const moreCarResults = { - cars: [ - { - id: 2, - make: 'Audi', - model: 'eTron', - vin: 'TREESRGOOD', - __typename: 'Car' - } - ] - }; + const cache = new InMemoryCache({ + typePolicies: { + Query: { + fields: { + cars: concatPagination(), + }, + }, + }, + }); - const mocks = [ + render( + + + + ); + + return wait(() => { + expect(renderCount).toBe(3); + }).then(resolve, reject); + }); + }); + + describe('should render fetchMore-updated results with no loading status, when `notifyOnNetworkStatusChange` is false', () => { + const carQuery: DocumentNode = gql` + query cars($limit: Int) { + cars(limit: $limit) { + id + make + model + vin + __typename + } + } + `; + + const carResults = { + cars: [ { - request: { query: carQuery, variables: { limit: 1 } }, - result: { data: carResults } - }, + id: 1, + make: 'Audi', + model: 'RS8', + vin: 'DOLLADOLLABILL', + __typename: 'Car' + } + ] + }; + + const moreCarResults = { + cars: [ { - request: { query: carQuery, variables: { limit: 1 } }, - result: { data: moreCarResults } + id: 2, + make: 'Audi', + model: 'eTron', + vin: 'TREESRGOOD', + __typename: 'Car' } - ]; + ] + }; + + const mocks = [ + { + request: { query: carQuery, variables: { limit: 1 } }, + result: { data: carResults } + }, + { + request: { query: carQuery, variables: { limit: 1 } }, + result: { data: moreCarResults } + } + ]; + itAsync('updateQuery', (resolve, reject) => { let renderCount = 0; function App() { const { loading, data, fetchMore } = useQuery(carQuery, { @@ -1317,8 +1371,63 @@ describe('useQuery Hook', () => { return wait(() => { expect(renderCount).toBe(3); }).then(resolve, reject); - } - ); + }); + + itAsync('field policy', (resolve, reject) => { + let renderCount = 0; + function App() { + const { loading, data, fetchMore } = useQuery(carQuery, { + variables: { limit: 1 }, + notifyOnNetworkStatusChange: false + }); + + switch (renderCount) { + case 0: + expect(loading).toBeTruthy(); + break; + case 1: + expect(loading).toBeFalsy(); + expect(data).toEqual(carResults); + fetchMore({ + variables: { + limit: 1 + }, + }); + break; + case 2: + expect(loading).toBeFalsy(); + expect(data).toEqual({ + cars: [carResults.cars[0], moreCarResults.cars[0]] + }); + break; + default: + } + + renderCount += 1; + return null; + } + + const cache = new InMemoryCache({ + typePolicies: { + Query: { + fields: { + cars: concatPagination(), + }, + }, + }, + }); + + render( + + + + ); + + return wait(() => { + expect(renderCount).toBe(3); + }).then(resolve, reject); + }); + }); }); describe('Refetching', () => {