709 lines
22 KiB
Plaintext
709 lines
22 KiB
Plaintext
import {
|
|
DEFAULT_DELAY_MS,
|
|
fakeTimerWaitFor,
|
|
setupApiStore,
|
|
} from '@internal/tests/utils/helpers'
|
|
import type { QueryActionCreatorResult } from '@reduxjs/toolkit/query'
|
|
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query'
|
|
|
|
beforeAll(() => {
|
|
vi.useFakeTimers()
|
|
})
|
|
|
|
const api = createApi({
|
|
baseQuery: fetchBaseQuery({ baseUrl: 'https://example.com' }),
|
|
endpoints: () => ({}),
|
|
})
|
|
const storeRef = setupApiStore(api)
|
|
|
|
const onNewCacheEntry = vi.fn()
|
|
const gotFirstValue = vi.fn()
|
|
const onCleanup = vi.fn()
|
|
const onCatch = vi.fn()
|
|
|
|
beforeEach(() => {
|
|
onNewCacheEntry.mockClear()
|
|
gotFirstValue.mockClear()
|
|
onCleanup.mockClear()
|
|
onCatch.mockClear()
|
|
})
|
|
|
|
describe.each([['query'], ['mutation']] as const)(
|
|
'generic cases: %s',
|
|
(type) => {
|
|
test(`${type}: new cache entry only`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/success',
|
|
onCacheEntryAdded(arg, { dispatch, getState }) {
|
|
onNewCacheEntry(arg)
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
storeRef.store.dispatch(extended.endpoints.injected.initiate('arg'))
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
})
|
|
|
|
test(`${type}: await cacheEntryRemoved`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
// Lying to TS here
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
|
|
await promise
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(59000)
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
}
|
|
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
})
|
|
|
|
test(`${type}: await cacheDataLoaded, await cacheEntryRemoved (success)`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<number, string>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved, cacheDataLoaded },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
const firstValue = await cacheDataLoaded
|
|
gotFirstValue(firstValue)
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
|
|
expect(gotFirstValue).not.toHaveBeenCalled()
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(gotFirstValue).toHaveBeenCalled()
|
|
})
|
|
expect(gotFirstValue).toHaveBeenCalledWith({
|
|
data: { value: 'success' },
|
|
meta: {
|
|
request: expect.any(Request),
|
|
response: expect.any(Object), // Response is not available in jest env
|
|
},
|
|
})
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(59000)
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
}
|
|
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
})
|
|
|
|
test(`${type}: await cacheDataLoaded, await cacheEntryRemoved (cacheDataLoaded never resolves)`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved, cacheDataLoaded },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
// this will wait until cacheEntryRemoved, then reject => nothing past that line will execute
|
|
// but since this special "cacheEntryRemoved" rejection is handled outside, there will be no
|
|
// uncaught rejection error
|
|
const firstValue = await cacheDataLoaded
|
|
gotFirstValue(firstValue)
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(120000)
|
|
}
|
|
expect(gotFirstValue).not.toHaveBeenCalled()
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
})
|
|
|
|
test(`${type}: try { await cacheDataLoaded }, await cacheEntryRemoved (cacheDataLoaded never resolves)`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved, cacheDataLoaded },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
|
|
try {
|
|
// this will wait until cacheEntryRemoved, then reject => nothing else in this try..catch block will execute
|
|
const firstValue = await cacheDataLoaded
|
|
gotFirstValue(firstValue)
|
|
} catch (e) {
|
|
onCatch(e)
|
|
}
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
await promise
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(59000)
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
}
|
|
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
expect(gotFirstValue).not.toHaveBeenCalled()
|
|
expect(onCatch.mock.calls[0][0]).toMatchObject({
|
|
message: 'Promise never resolved before cacheEntryRemoved.',
|
|
})
|
|
})
|
|
|
|
test(`${type}: try { await cacheDataLoaded, await cacheEntryRemoved } (cacheDataLoaded never resolves)`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved, cacheDataLoaded },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
|
|
try {
|
|
// this will wait until cacheEntryRemoved, then reject => nothing else in this try..catch block will execute
|
|
const firstValue = await cacheDataLoaded
|
|
gotFirstValue(firstValue)
|
|
// cleanup in this scenario only needs to be done for stuff within this try..catch block - totally valid scenario
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
} catch (e) {
|
|
onCatch(e)
|
|
}
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
await promise
|
|
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(59000)
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
}
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
expect(gotFirstValue).not.toHaveBeenCalled()
|
|
expect(onCatch.mock.calls[0][0]).toMatchObject({
|
|
message: 'Promise never resolved before cacheEntryRemoved.',
|
|
})
|
|
})
|
|
|
|
test(`${type}: try { await cacheDataLoaded } finally { await cacheEntryRemoved } (cacheDataLoaded never resolves)`, async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build[type as 'mutation']<unknown, string>({
|
|
query: () => '/error', // we will initiate only once and that one time will be an error -> cacheDataLoaded will never resolve
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{ dispatch, getState, cacheEntryRemoved, cacheDataLoaded },
|
|
) {
|
|
onNewCacheEntry(arg)
|
|
|
|
try {
|
|
// this will wait until cacheEntryRemoved, then reject => nothing else in this try..catch block will execute
|
|
const firstValue = await cacheDataLoaded
|
|
gotFirstValue(firstValue)
|
|
} catch (e) {
|
|
onCatch(e)
|
|
} finally {
|
|
await cacheEntryRemoved
|
|
onCleanup()
|
|
}
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
|
|
expect(onNewCacheEntry).toHaveBeenCalledWith('arg')
|
|
|
|
await promise
|
|
if (type === 'mutation') {
|
|
promise.reset()
|
|
} else {
|
|
;(promise as unknown as QueryActionCreatorResult<any>).unsubscribe()
|
|
}
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
if (type === 'query') {
|
|
await vi.advanceTimersByTimeAsync(59000)
|
|
expect(onCleanup).not.toHaveBeenCalled()
|
|
await vi.advanceTimersByTimeAsync(2000)
|
|
}
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
expect(gotFirstValue).not.toHaveBeenCalled()
|
|
expect(onCatch.mock.calls[0][0]).toMatchObject({
|
|
message: 'Promise never resolved before cacheEntryRemoved.',
|
|
})
|
|
})
|
|
},
|
|
)
|
|
|
|
test(`query: getCacheEntry`, async () => {
|
|
const snapshot = vi.fn()
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.query<unknown, string>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{
|
|
dispatch,
|
|
getState,
|
|
getCacheEntry,
|
|
cacheEntryRemoved,
|
|
cacheDataLoaded,
|
|
},
|
|
) {
|
|
snapshot(getCacheEntry())
|
|
gotFirstValue(await cacheDataLoaded)
|
|
snapshot(getCacheEntry())
|
|
await cacheEntryRemoved
|
|
snapshot(getCacheEntry())
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
await promise
|
|
promise.unsubscribe()
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(gotFirstValue).toHaveBeenCalled()
|
|
})
|
|
|
|
await vi.advanceTimersByTimeAsync(120000)
|
|
|
|
expect(snapshot).toHaveBeenCalledTimes(3)
|
|
expect(snapshot.mock.calls[0][0]).toMatchObject({
|
|
endpointName: 'injected',
|
|
isError: false,
|
|
isLoading: true,
|
|
isSuccess: false,
|
|
isUninitialized: false,
|
|
originalArgs: 'arg',
|
|
requestId: promise.requestId,
|
|
startedTimeStamp: expect.any(Number),
|
|
status: 'pending',
|
|
})
|
|
expect(snapshot.mock.calls[1][0]).toMatchObject({
|
|
data: {
|
|
value: 'success',
|
|
},
|
|
endpointName: 'injected',
|
|
fulfilledTimeStamp: expect.any(Number),
|
|
isError: false,
|
|
isLoading: false,
|
|
isSuccess: true,
|
|
isUninitialized: false,
|
|
originalArgs: 'arg',
|
|
requestId: promise.requestId,
|
|
startedTimeStamp: expect.any(Number),
|
|
status: 'fulfilled',
|
|
})
|
|
expect(snapshot.mock.calls[2][0]).toMatchObject({
|
|
isError: false,
|
|
isLoading: false,
|
|
isSuccess: false,
|
|
isUninitialized: true,
|
|
status: 'uninitialized',
|
|
})
|
|
})
|
|
|
|
test(`mutation: getCacheEntry`, async () => {
|
|
const snapshot = vi.fn()
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.mutation<unknown, string>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{
|
|
dispatch,
|
|
getState,
|
|
getCacheEntry,
|
|
cacheEntryRemoved,
|
|
cacheDataLoaded,
|
|
},
|
|
) {
|
|
snapshot(getCacheEntry())
|
|
gotFirstValue(await cacheDataLoaded)
|
|
snapshot(getCacheEntry())
|
|
await cacheEntryRemoved
|
|
snapshot(getCacheEntry())
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
await fakeTimerWaitFor(() => {
|
|
expect(gotFirstValue).toHaveBeenCalled()
|
|
})
|
|
|
|
promise.reset()
|
|
await vi.advanceTimersByTimeAsync(DEFAULT_DELAY_MS)
|
|
|
|
expect(snapshot).toHaveBeenCalledTimes(3)
|
|
expect(snapshot.mock.calls[0][0]).toMatchObject({
|
|
endpointName: 'injected',
|
|
isError: false,
|
|
isLoading: true,
|
|
isSuccess: false,
|
|
isUninitialized: false,
|
|
startedTimeStamp: expect.any(Number),
|
|
status: 'pending',
|
|
})
|
|
expect(snapshot.mock.calls[1][0]).toMatchObject({
|
|
data: {
|
|
value: 'success',
|
|
},
|
|
endpointName: 'injected',
|
|
fulfilledTimeStamp: expect.any(Number),
|
|
isError: false,
|
|
isLoading: false,
|
|
isSuccess: true,
|
|
isUninitialized: false,
|
|
startedTimeStamp: expect.any(Number),
|
|
status: 'fulfilled',
|
|
})
|
|
expect(snapshot.mock.calls[2][0]).toMatchObject({
|
|
isError: false,
|
|
isLoading: false,
|
|
isSuccess: false,
|
|
isUninitialized: true,
|
|
status: 'uninitialized',
|
|
})
|
|
})
|
|
|
|
test('query: updateCachedData', async () => {
|
|
const trackCalls = vi.fn()
|
|
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.query<{ value: string }, string>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{
|
|
dispatch,
|
|
getState,
|
|
getCacheEntry,
|
|
updateCachedData,
|
|
cacheEntryRemoved,
|
|
cacheDataLoaded,
|
|
},
|
|
) {
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
// calling `updateCachedData` when there is no data yet should not do anything
|
|
updateCachedData((draft) => {
|
|
draft.value = 'TEST'
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).not.toHaveBeenCalled()
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
|
|
gotFirstValue(await cacheDataLoaded)
|
|
|
|
expect(getCacheEntry().data).toEqual({ value: 'success' })
|
|
updateCachedData((draft) => {
|
|
draft.value = 'TEST'
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).toHaveBeenCalledOnce()
|
|
expect(getCacheEntry().data).toEqual({ value: 'TEST' })
|
|
|
|
await cacheEntryRemoved
|
|
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
// calling `updateCachedData` when there is no data any more should not do anything
|
|
updateCachedData((draft) => {
|
|
draft.value = 'TEST2'
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).toHaveBeenCalledOnce()
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate('arg'),
|
|
)
|
|
await promise
|
|
promise.unsubscribe()
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(gotFirstValue).toHaveBeenCalled()
|
|
})
|
|
|
|
await vi.advanceTimersByTimeAsync(61000)
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
test('updateCachedData - infinite query', async () => {
|
|
const trackCalls = vi.fn()
|
|
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
infiniteInjected: build.infiniteQuery<{ value: string }, string, number>({
|
|
query: () => '/success',
|
|
infiniteQueryOptions: {
|
|
initialPageParam: 1,
|
|
getNextPageParam: (
|
|
lastPage,
|
|
allPages,
|
|
lastPageParam,
|
|
allPageParams,
|
|
) => lastPageParam + 1,
|
|
},
|
|
async onCacheEntryAdded(
|
|
arg,
|
|
{
|
|
dispatch,
|
|
getState,
|
|
getCacheEntry,
|
|
updateCachedData,
|
|
cacheEntryRemoved,
|
|
cacheDataLoaded,
|
|
},
|
|
) {
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
// calling `updateCachedData` when there is no data yet should not do anything
|
|
updateCachedData((draft) => {
|
|
draft.pages = [{ value: 'TEST' }]
|
|
draft.pageParams = [1]
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).not.toHaveBeenCalled()
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
|
|
gotFirstValue(await cacheDataLoaded)
|
|
|
|
expect(getCacheEntry().data).toEqual({
|
|
pages: [{ value: 'success' }],
|
|
pageParams: [1],
|
|
})
|
|
updateCachedData((draft) => {
|
|
draft.pages = [{ value: 'TEST' }]
|
|
draft.pageParams = [1]
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).toHaveBeenCalledOnce()
|
|
expect(getCacheEntry().data).toEqual({
|
|
pages: [{ value: 'TEST' }],
|
|
pageParams: [1],
|
|
})
|
|
|
|
await cacheEntryRemoved
|
|
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
// calling `updateCachedData` when there is no data any more should not do anything
|
|
updateCachedData((draft) => {
|
|
draft.pages = [{ value: 'TEST' }, { value: 'TEST2' }]
|
|
draft.pageParams = [1, 2]
|
|
trackCalls()
|
|
})
|
|
expect(trackCalls).toHaveBeenCalledOnce()
|
|
expect(getCacheEntry().data).toEqual(undefined)
|
|
|
|
onCleanup()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
const promise = storeRef.store.dispatch(
|
|
extended.endpoints.infiniteInjected.initiate('arg'),
|
|
)
|
|
await promise
|
|
promise.unsubscribe()
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(gotFirstValue).toHaveBeenCalled()
|
|
})
|
|
|
|
await vi.advanceTimersByTimeAsync(61000)
|
|
|
|
await fakeTimerWaitFor(() => {
|
|
expect(onCleanup).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
test('dispatching further actions does not trigger another lifecycle', async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.query<unknown, void>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded() {
|
|
onNewCacheEntry()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
await storeRef.store.dispatch(extended.endpoints.injected.initiate())
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
|
|
await storeRef.store.dispatch(extended.endpoints.injected.initiate())
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
|
|
await storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate(undefined, { forceRefetch: true }),
|
|
)
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
})
|
|
|
|
test('dispatching a query initializer with `subscribe: false` does also start a lifecycle', async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.query<unknown, void>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded() {
|
|
onNewCacheEntry()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
await storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate(undefined, { subscribe: false }),
|
|
)
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
|
|
// will not be called a second time though
|
|
await storeRef.store.dispatch(extended.endpoints.injected.initiate(undefined))
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
})
|
|
|
|
test('dispatching a mutation initializer with `track: false` does not start a lifecycle', async () => {
|
|
const extended = api.injectEndpoints({
|
|
overrideExisting: true,
|
|
endpoints: (build) => ({
|
|
injected: build.mutation<unknown, void>({
|
|
query: () => '/success',
|
|
async onCacheEntryAdded() {
|
|
onNewCacheEntry()
|
|
},
|
|
}),
|
|
}),
|
|
})
|
|
await storeRef.store.dispatch(
|
|
extended.endpoints.injected.initiate(undefined, { track: false }),
|
|
)
|
|
expect(onNewCacheEntry).not.toHaveBeenCalled()
|
|
|
|
await storeRef.store.dispatch(extended.endpoints.injected.initiate(undefined))
|
|
expect(onNewCacheEntry).toHaveBeenCalledOnce()
|
|
})
|