Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement infinite query status flags (#4771)
Browse files Browse the repository at this point in the history
* Extract InfiniteQueryDirection

* Export page param functions

* Fix useRefs with React 19

* Fix infinite query selector arg type

* Implement infinite query status flags

* Fix types and flags for infinite query hooks

* Add new error messages
markerikson authored Dec 15, 2024
1 parent a28de8f commit 87270fe
Showing 9 changed files with 319 additions and 131 deletions.
4 changes: 3 additions & 1 deletion errors.json
Original file line number Diff line number Diff line change
@@ -38,5 +38,7 @@
"36": "When using custom hooks for context, all hooks need to be provided: .\\nHook was either not provided or not a function.",
"37": "Warning: Middleware for RTK-Query API at reducerPath \"\" has not been added to the store.\n You must add the middleware for RTK-Query to function correctly!",
"38": "Cannot refetch a query that has not been started yet.",
"39": "called \\`injectEndpoints\\` to override already-existing endpointName without specifying \\`overrideExisting: true\\`"
"39": "called \\`injectEndpoints\\` to override already-existing endpointName without specifying \\`overrideExisting: true\\`",
"40": "maxPages for endpoint '' must be a number greater than 0",
"41": "getPreviousPageParam for endpoint '' must be a function if maxPages is used"
}
17 changes: 3 additions & 14 deletions packages/toolkit/src/query/core/apiState.ts
Original file line number Diff line number Diff line change
@@ -201,13 +201,6 @@ type BaseQuerySubState<
* Time that the latest query was fulfilled
*/
fulfilledTimeStamp?: number
/**
* Infinite Query Specific substate properties
*/
hasNextPage?: boolean
hasPreviousPage?: boolean
direction?: 'forward' | 'backward'
param?: QueryArgFrom<D>
}

export type QuerySubState<
@@ -238,18 +231,14 @@ export type QuerySubState<
}
>

export type InfiniteQueryDirection = 'forward' | 'backward'

export type InfiniteQuerySubState<
D extends BaseEndpointDefinition<any, any, any>,
> =
D extends InfiniteQueryDefinition<any, any, any, any, any>
? QuerySubState<D, InfiniteData<ResultTypeFrom<D>, PageParamFrom<D>>> & {
// TODO: These shouldn't be optional
hasNextPage?: boolean
hasPreviousPage?: boolean
isFetchingNextPage?: boolean
isFetchingPreviousPage?: boolean
param?: PageParamFrom<D>
direction?: 'forward' | 'backward'
direction?: InfiniteQueryDirection
}
: never

3 changes: 2 additions & 1 deletion packages/toolkit/src/query/core/buildInitiate.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ import { countObjectKeys, getOrInsert, isNotNullish } from '../utils'
import type {
InfiniteData,
InfiniteQueryConfigOptions,
InfiniteQueryDirection,
SubscriptionOptions,
} from './apiState'
import type {
@@ -73,7 +74,7 @@ export type StartInfiniteQueryActionCreatorOptions<
subscribe?: boolean
forceRefetch?: boolean | number
subscriptionOptions?: SubscriptionOptions
direction?: 'forward' | 'backward'
direction?: InfiniteQueryDirection
[forceQueryFnSymbol]?: () => QueryReturnValue
param?: unknown
previous?: boolean
82 changes: 79 additions & 3 deletions packages/toolkit/src/query/core/buildSelectors.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { InternalSerializeQueryArgs } from '../defaultSerializeQueryArgs'
import type {
EndpointDefinitions,
InfiniteQueryArgFrom,
InfiniteQueryDefinition,
MutationDefinition,
QueryArgFrom,
@@ -12,6 +13,8 @@ import type {
import { expandTagDescription } from '../endpointDefinitions'
import { flatten, isNotNullish } from '../utils'
import type {
InfiniteData,
InfiniteQueryConfigOptions,
InfiniteQuerySubState,
MutationSubState,
QueryCacheKey,
@@ -25,6 +28,7 @@ import { QueryStatus, getRequestStatusFlags } from './apiState'
import { getMutationCacheKey } from './buildSlice'
import type { createSelector as _createSelector } from './rtkImports'
import { createNextState } from './rtkImports'
import { getNextPageParam, getPreviousPageParam } from './buildThunks'

export type SkipToken = typeof skipToken
/**
@@ -108,12 +112,23 @@ type InfiniteQueryResultSelectorFactory<
Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
RootState,
> = (
queryArg: QueryArgFrom<Definition> | SkipToken,
queryArg: InfiniteQueryArgFrom<Definition> | SkipToken,
) => (state: RootState) => InfiniteQueryResultSelectorResult<Definition>

export type InfiniteQueryResultFlags = {
hasNextPage: boolean
hasPreviousPage: boolean
isFetchingNextPage: boolean
isFetchingPreviousPage: boolean
isFetchNextPageError: boolean
isFetchPreviousPageError: boolean
}

export type InfiniteQueryResultSelectorResult<
Definition extends InfiniteQueryDefinition<any, any, any, any, any>,
> = InfiniteQuerySubState<Definition> & RequestStatusFlags
> = InfiniteQuerySubState<Definition> &
RequestStatusFlags &
InfiniteQueryResultFlags

type MutationResultSelectorFactory<
Definition extends MutationDefinition<any, any, any, any>,
@@ -230,7 +245,52 @@ export function buildSelectors<
const finalSelectQuerySubState =
queryArgs === skipToken ? selectSkippedQuery : selectQuerySubstate

return createSelector(finalSelectQuerySubState, withRequestFlags)
const { infiniteQueryOptions } = endpointDefinition

function withInfiniteQueryResultFlags<T extends { status: QueryStatus }>(
substate: T,
): T & RequestStatusFlags & InfiniteQueryResultFlags {
const infiniteSubstate = substate as InfiniteQuerySubState<any>
const fetchDirection = infiniteSubstate.direction
const stateWithRequestFlags = {
...infiniteSubstate,
...getRequestStatusFlags(substate.status),
}

const { isLoading, isError } = stateWithRequestFlags

const isFetchNextPageError = isError && fetchDirection === 'forward'
const isFetchingNextPage = isLoading && fetchDirection === 'forward'

const isFetchPreviousPageError =
isError && fetchDirection === 'backward'
const isFetchingPreviousPage =
isLoading && fetchDirection === 'backward'

const hasNextPage = getHasNextPage(
infiniteQueryOptions,
stateWithRequestFlags.data,
)
const hasPreviousPage = getHasPreviousPage(
infiniteQueryOptions,
stateWithRequestFlags.data,
)

return {
...stateWithRequestFlags,
hasNextPage,
hasPreviousPage,
isFetchingNextPage,
isFetchingPreviousPage,
isFetchNextPageError,
isFetchPreviousPageError,
}
}

return createSelector(
finalSelectQuerySubState,
withInfiniteQueryResultFlags,
)
}) as InfiniteQueryResultSelectorFactory<any, RootState>
}

@@ -315,4 +375,20 @@ export function buildSelectors<
)
.map((entry) => entry.originalArgs)
}

function getHasNextPage(
options: InfiniteQueryConfigOptions<any, any>,
data?: InfiniteData<unknown, unknown>,
): boolean {
if (!data) return false
return getNextPageParam(options, data) != null
}

function getHasPreviousPage(
options: InfiniteQueryConfigOptions<any, any>,
data?: InfiniteData<unknown, unknown>,
): boolean {
if (!data || !options.getPreviousPageParam) return false
return getPreviousPageParam(options, data) != null
}
}
34 changes: 15 additions & 19 deletions packages/toolkit/src/query/core/buildSlice.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ import type {
ConfigState,
QueryKeys,
InfiniteQuerySubState,
InfiniteQueryDirection,
} from './apiState'
import { QueryStatus } from './apiState'
import type {
@@ -35,14 +36,15 @@ import type {
RejectedAction,
} from './buildThunks'
import { calculateProvidedByThunk } from './buildThunks'
import type {
AssertTagTypes,
DefinitionType,
EndpointDefinitions,
FullTagDescription,
QueryArgFrom,
QueryDefinition,
ResultTypeFrom,
import {
isInfiniteQueryDefinition,
type AssertTagTypes,
type DefinitionType,
type EndpointDefinitions,
type FullTagDescription,
type QueryArgFrom,
type QueryDefinition,
type ResultTypeFrom,
} from '../endpointDefinitions'
import type { Patch } from 'immer'
import { isDraft } from 'immer'
@@ -205,15 +207,11 @@ export function buildSlice({
}
substate.startedTimeStamp = meta.startedTimeStamp

// TODO: Awful - fix this most likely by just moving it to its own slice that only works on InfQuery's
if (
'param' in substate &&
'direction' in substate &&
'param' in arg &&
'direction' in arg
) {
substate.param = arg.param
substate.direction = arg.direction as 'forward' | 'backward' | undefined
const endpointDefinition = definitions[meta.arg.endpointName]

if (isInfiniteQueryDefinition(endpointDefinition) && 'direction' in arg) {
;(substate as InfiniteQuerySubState<any>).direction =
arg.direction as InfiniteQueryDirection
}
})
}
@@ -223,11 +221,9 @@ export function buildSlice({
meta: {
arg: QueryThunkArg
requestId: string
// requestStatus: 'fulfilled'
} & {
fulfilledTimeStamp: number
baseQueryMeta: unknown
// RTK_autoBatch: true
},
payload: unknown,
upserting: boolean,
53 changes: 27 additions & 26 deletions packages/toolkit/src/query/core/buildThunks.ts
Original file line number Diff line number Diff line change
@@ -39,6 +39,7 @@ import type {
InfiniteData,
InfiniteQueryConfigOptions,
QueryCacheKey,
InfiniteQueryDirection,
} from './apiState'
import { QueryStatus } from './apiState'
import type {
@@ -131,7 +132,7 @@ export type InfiniteQueryThunkArg<
endpointName: string
param: unknown
previous?: boolean
direction?: 'forward' | 'backward'
direction?: InfiniteQueryDirection
}

type MutationThunkArg = {
@@ -646,31 +647,6 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".`
}
}

function getNextPageParam(
options: InfiniteQueryConfigOptions<unknown, unknown>,
{ pages, pageParams }: InfiniteData<unknown, unknown>,
): unknown | undefined {
const lastIndex = pages.length - 1
return options.getNextPageParam(
pages[lastIndex],
pages,
pageParams[lastIndex],
pageParams,
)
}

function getPreviousPageParam(
options: InfiniteQueryConfigOptions<unknown, unknown>,
{ pages, pageParams }: InfiniteData<unknown, unknown>,
): unknown | undefined {
return options.getPreviousPageParam?.(
pages[0],
pages,
pageParams[0],
pageParams,
)
}

function isForcedQuery(
arg: QueryThunkArg,
state: RootState<any, string, ReducerPath>,
@@ -892,6 +868,31 @@ In the case of an unhandled error, no tags will be "provided" or "invalidated".`
}
}

export function getNextPageParam(
options: InfiniteQueryConfigOptions<unknown, unknown>,
{ pages, pageParams }: InfiniteData<unknown, unknown>,
): unknown | undefined {
const lastIndex = pages.length - 1
return options.getNextPageParam(
pages[lastIndex],
pages,
pageParams[lastIndex],
pageParams,
)
}

export function getPreviousPageParam(
options: InfiniteQueryConfigOptions<unknown, unknown>,
{ pages, pageParams }: InfiniteData<unknown, unknown>,
): unknown | undefined {
return options.getPreviousPageParam?.(
pages[0],
pages,
pageParams[0],
pageParams,
)
}

export function calculateProvidedByThunk(
action: UnwrapPromise<
ReturnType<ReturnType<QueryThunk>> | ReturnType<ReturnType<MutationThunk>>
30 changes: 13 additions & 17 deletions packages/toolkit/src/query/react/buildHooks.ts
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@ import { UNINITIALIZED_VALUE } from './constants'
import type { ReactHooksModuleOptions } from './module'
import { useStableQueryArgs } from './useSerializedStableValue'
import { useShallowStableValue } from './useShallowStableValue'
import { InfiniteQueryDirection } from '../core/apiState'

// Copy-pasted from React-Redux
const canUseDOM = () =>
@@ -786,7 +787,7 @@ export type LazyInfiniteQueryTrigger<
*/
(
arg: QueryArgFrom<D>,
direction: 'forward' | 'backward',
direction: InfiniteQueryDirection,
): InfiniteQueryActionCreatorResult<D>
}

@@ -889,15 +890,17 @@ export type UseInfiniteQuery<
arg: InfiniteQueryArgFrom<D> | SkipToken,
options?: UseInfiniteQuerySubscriptionOptions<D> &
UseInfiniteQueryStateOptions<D, R>,
) => UseInfiniteQueryHookResult<D, R>
) => UseInfiniteQueryHookResult<D, R> & {
fetchNextPage: () => InfiniteQueryActionCreatorResult<D>
fetchPreviousPage: () => InfiniteQueryActionCreatorResult<D>
}

export type UseInfiniteQueryState<
D extends InfiniteQueryDefinition<any, any, any, any, any>,
> = <R extends Record<string, any> = UseInfiniteQueryStateDefaultResult<D>>(
arg: QueryArgFrom<D> | SkipToken,
options?: UseInfiniteQueryStateOptions<D, R>,
) => UseInfiniteQueryStateResult<D, R>

export type TypedUseInfiniteQueryState<
ResultType,
QueryArg,
@@ -1039,9 +1042,6 @@ type UseInfiniteQueryStateBaseResult<
hasPreviousPage: false
isFetchingNextPage: false
isFetchingPreviousPage: false

fetchNextPage: () => Promise<InfiniteQueryActionCreatorResult<D>>
fetchPreviousPage: () => Promise<InfiniteQueryActionCreatorResult<D>>
}

type UseInfiniteQueryStateDefaultResult<
@@ -1346,21 +1346,13 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
// isSuccess = true when data is present
const isSuccess = currentState.isSuccess || (isFetching && hasData)

const isFetchingNextPage =
isFetching && currentState.direction === 'forward'

const isFetchingPreviousPage =
isFetching && currentState.direction === 'backward'

return {
...currentState,
data,
currentData: currentState.data,
isFetching,
isLoading,
isSuccess,
isFetchingNextPage,
isFetchingPreviousPage,
} as UseInfiniteQueryStateDefaultResult<any>
}

@@ -1767,7 +1759,9 @@ export function buildHooks<Definitions extends EndpointDefinitions>({
Definitions
>
const dispatch = useDispatch<ThunkDispatch<any, any, UnknownAction>>()
const subscriptionSelectorsRef = useRef<SubscriptionSelectors>()
const subscriptionSelectorsRef = useRef<
SubscriptionSelectors | undefined
>(undefined)
if (!subscriptionSelectorsRef.current) {
const returnedValue = dispatch(
api.internalActions.internal_getRTKQSubscriptions(),
@@ -1808,7 +1802,9 @@ export function buildHooks<Definitions extends EndpointDefinitions>({

const lastRenderHadSubscription = useRef(false)

const promiseRef = useRef<InfiniteQueryActionCreatorResult<any>>()
const promiseRef = useRef<
InfiniteQueryActionCreatorResult<any> | undefined
>(undefined)

let { queryCacheKey, requestId } = promiseRef.current || {}

@@ -1932,7 +1928,7 @@ export function buildHooks<Definitions extends EndpointDefinitions>({

type ApiRootState = Parameters<ReturnType<typeof select>>[0]

const lastValue = useRef<any>()
const lastValue = useRef<any>(undefined)

const selectDefaultResult: Selector<ApiRootState, any, [any]> = useMemo(
() =>
55 changes: 55 additions & 0 deletions packages/toolkit/src/query/tests/buildHooks.test.tsx
Original file line number Diff line number Diff line change
@@ -36,6 +36,7 @@ import type { SyncScreen } from '@testing-library/react-render-stream/pure'
import { createRenderStream } from '@testing-library/react-render-stream/pure'
import { HttpResponse, http } from 'msw'
import { useEffect, useState } from 'react'
import type { InfiniteQueryResultFlags } from '../core/buildSelectors'

// Just setup a temporary in-memory counter for tests that `getIncrementedAmount`.
// This can be used to test how many renders happen due to data changes or
@@ -1798,6 +1799,26 @@ describe('hooks tests', () => {
expect(queries).toBe(count)
}

const checkEntryFlags = (
arg: string,
expectedFlags: Partial<InfiniteQueryResultFlags>,
) => {
const selector = pokemonApi.endpoints.getInfinitePokemon.select(arg)
const entry = selector(storeRef.store.getState())

const actualFlags: InfiniteQueryResultFlags = {
hasNextPage: false,
hasPreviousPage: false,
isFetchingNextPage: false,
isFetchingPreviousPage: false,
isFetchNextPageError: false,
isFetchPreviousPageError: false,
...expectedFlags,
}

expect(entry).toMatchObject(actualFlags)
}

const checkPageRows = (
withinDOM: () => SyncScreen,
type: string,
@@ -1836,30 +1857,64 @@ describe('hooks tests', () => {

const utils = render(<PokemonList />, { wrapper: storeRef.wrapper })
checkNumQueries(1)
checkEntryFlags('fire', {})
await waitForFetch(true)
checkNumQueries(1)
checkPageRows(getCurrentRender().withinDOM, 'fire', [0])
checkEntryFlags('fire', {
hasNextPage: true,
})

fireEvent.click(screen.getByTestId('nextPage'), {})
checkEntryFlags('fire', {
hasNextPage: true,
isFetchingNextPage: true,
})
await waitForFetch()
checkPageRows(getCurrentRender().withinDOM, 'fire', [0, 1])
checkEntryFlags('fire', {
hasNextPage: true,
})

fireEvent.click(screen.getByTestId('nextPage'))
await waitForFetch()
checkPageRows(getCurrentRender().withinDOM, 'fire', [0, 1, 2])

utils.rerender(<PokemonList arg="water" initialPageParam={3} />)
checkEntryFlags('water', {})
await waitForFetch(true)
checkNumQueries(2)
checkPageRows(getCurrentRender().withinDOM, 'water', [3])
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
})

fireEvent.click(screen.getByTestId('nextPage'))
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
isFetchingNextPage: true,
})
await waitForFetch()
checkPageRows(getCurrentRender().withinDOM, 'water', [3, 4])
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
})

fireEvent.click(screen.getByTestId('prevPage'))
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
isFetchingPreviousPage: true,
})
await waitForFetch()
checkPageRows(getCurrentRender().withinDOM, 'water', [2, 3, 4])
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
})
})
})

172 changes: 122 additions & 50 deletions packages/toolkit/src/query/tests/infiniteQueries.test.ts
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import {
import userEvent from '@testing-library/user-event'
import { HttpResponse, http } from 'msw'
import util from 'util'
import type { InfiniteQueryActionCreatorResult } from '@reduxjs/toolkit/query/react'
import {
QueryStatus,
createApi,
@@ -24,6 +25,7 @@ import {
} from '../../tests/utils/helpers'
import type { BaseQueryApi } from '../baseQueryTypes'
import { server } from '@internal/query/tests/mocks/server'
import type { InfiniteQueryResultFlags } from '../core/buildSelectors'

describe('Infinite queries', () => {
type Pokemon = {
@@ -139,92 +141,162 @@ describe('Infinite queries', () => {
})

test('Basic infinite query behavior', async () => {
const checkFlags = (
value: unknown,
expectedFlags: Partial<InfiniteQueryResultFlags>,
) => {
const actualFlags: InfiniteQueryResultFlags = {
hasNextPage: false,
hasPreviousPage: false,
isFetchingNextPage: false,
isFetchingPreviousPage: false,
isFetchNextPageError: false,
isFetchPreviousPageError: false,
...expectedFlags,
}

expect(value).toMatchObject(actualFlags)
}

const checkEntryFlags = (
arg: string,
expectedFlags: Partial<InfiniteQueryResultFlags>,
) => {
const selector = pokemonApi.endpoints.getInfinitePokemon.select(arg)
const entry = selector(storeRef.store.getState())

checkFlags(entry, expectedFlags)
}

type InfiniteQueryResult = Awaited<InfiniteQueryActionCreatorResult<any>>

const checkResultData = (
result: InfiniteQueryResult,
expectedValues: Pokemon[][],
) => {
expect(result.status).toBe(QueryStatus.fulfilled)
if (result.status === QueryStatus.fulfilled) {
expect(result.data.pages).toEqual(expectedValues)
}
}

const res1 = storeRef.store.dispatch(
// Should be `arg: string`
pokemonApi.endpoints.getInfinitePokemon.initiate('fire', {}),
)

checkEntryFlags('fire', {})

const entry1InitialLoad = await res1
expect(entry1InitialLoad.status).toBe(QueryStatus.fulfilled)
// console.log('Value: ', util.inspect(entry1InitialLoad, { depth: Infinity }))

if (entry1InitialLoad.status === QueryStatus.fulfilled) {
expect(entry1InitialLoad.data.pages).toEqual([
// one page, one entry
[{ id: '0', name: 'Pokemon 0' }],
])
}
checkResultData(entry1InitialLoad, [[{ id: '0', name: 'Pokemon 0' }]])
checkFlags(entry1InitialLoad, {
hasNextPage: true,
})

const entry1SecondPage = await storeRef.store.dispatch(
const res2 = storeRef.store.dispatch(
pokemonApi.endpoints.getInfinitePokemon.initiate('fire', {
direction: 'forward',
}),
)

expect(entry1SecondPage.status).toBe(QueryStatus.fulfilled)
if (entry1SecondPage.status === QueryStatus.fulfilled) {
expect(entry1SecondPage.data.pages).toEqual([
// two pages, one entry each
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])
}
checkEntryFlags('fire', {
hasNextPage: true,
isFetchingNextPage: true,
})

const entry1SecondPage = await res2

checkResultData(entry1SecondPage, [
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])
checkFlags(entry1SecondPage, {
hasNextPage: true,
})

const entry1PrevPageMissing = await storeRef.store.dispatch(
const res3 = storeRef.store.dispatch(
pokemonApi.endpoints.getInfinitePokemon.initiate('fire', {
direction: 'backward',
}),
)

if (entry1PrevPageMissing.status === QueryStatus.fulfilled) {
expect(entry1PrevPageMissing.data.pages).toEqual([
// two pages, one entry each
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])
}
checkEntryFlags('fire', {
hasNextPage: true,
isFetchingPreviousPage: true,
})

const entry1PrevPageMissing = await res3

checkResultData(entry1PrevPageMissing, [
[{ id: '0', name: 'Pokemon 0' }],
[{ id: '1', name: 'Pokemon 1' }],
])
checkFlags(entry1PrevPageMissing, {
hasNextPage: true,
})

const entry2InitialLoad = await storeRef.store.dispatch(
const res4 = storeRef.store.dispatch(
pokemonApi.endpoints.getInfinitePokemon.initiate('water', {
initialPageParam: 3,
}),
)

if (entry2InitialLoad.status === QueryStatus.fulfilled) {
expect(entry2InitialLoad.data.pages).toEqual([
// one page, one entry
[{ id: '3', name: 'Pokemon 3' }],
])
}
checkEntryFlags('water', {})

const entry2InitialLoad = await res4

const entry2NextPage = await storeRef.store.dispatch(
checkResultData(entry2InitialLoad, [[{ id: '3', name: 'Pokemon 3' }]])
checkFlags(entry2InitialLoad, {
hasNextPage: true,
hasPreviousPage: true,
})

const res5 = storeRef.store.dispatch(
pokemonApi.endpoints.getInfinitePokemon.initiate('water', {
direction: 'forward',
}),
)

if (entry2NextPage.status === QueryStatus.fulfilled) {
expect(entry2NextPage.data.pages).toEqual([
// two pages, one entry each
[{ id: '3', name: 'Pokemon 3' }],
[{ id: '4', name: 'Pokemon 4' }],
])
}
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
isFetchingNextPage: true,
})

const entry2NextPage = await res5

const entry2PrevPage = await storeRef.store.dispatch(
checkResultData(entry2NextPage, [
[{ id: '3', name: 'Pokemon 3' }],
[{ id: '4', name: 'Pokemon 4' }],
])
checkFlags(entry2NextPage, {
hasNextPage: true,
hasPreviousPage: true,
})

const res6 = storeRef.store.dispatch(
pokemonApi.endpoints.getInfinitePokemon.initiate('water', {
direction: 'backward',
}),
)

if (entry2PrevPage.status === QueryStatus.fulfilled) {
expect(entry2PrevPage.data.pages).toEqual([
// three pages, one entry each
[{ id: '2', name: 'Pokemon 2' }],
[{ id: '3', name: 'Pokemon 3' }],
[{ id: '4', name: 'Pokemon 4' }],
])
}
checkEntryFlags('water', {
hasNextPage: true,
hasPreviousPage: true,
isFetchingPreviousPage: true,
})

const entry2PrevPage = await res6

checkResultData(entry2PrevPage, [
[{ id: '2', name: 'Pokemon 2' }],
[{ id: '3', name: 'Pokemon 3' }],
[{ id: '4', name: 'Pokemon 4' }],
])
checkFlags(entry2PrevPage, {
hasNextPage: true,
hasPreviousPage: true,
})
})

test.skip('does not break refetching query endpoints', async () => {

0 comments on commit 87270fe

Please sign in to comment.