import { setupApiStore } from '@internal/tests/utils/helpers' import { createApi } from '../core' import type { SubscriptionSelectors } from '../core/buildMiddleware/types' import { fakeBaseQuery } from '../fakeBaseQuery' let calls = 0 const api = createApi({ baseQuery: fakeBaseQuery(), endpoints: (build) => ({ increment: build.query({ async queryFn() { const data = calls++ await Promise.resolve() return { data } }, }), failing: build.query({ async queryFn() { await Promise.resolve() return { error: { status: 500, data: 'error' } } }, }), }), }) const storeRef = setupApiStore(api) let getSubscriptions: SubscriptionSelectors['getSubscriptions'] let isRequestSubscribed: SubscriptionSelectors['isRequestSubscribed'] beforeEach(() => { ;({ getSubscriptions, isRequestSubscribed } = storeRef.store.dispatch( api.internalActions.internal_getRTKQSubscriptions(), ) as unknown as SubscriptionSelectors) }) test('multiple synchonrous initiate calls with pre-existing cache entry', async () => { const { store, api } = storeRef // seed the store const firstValue = await store.dispatch(api.endpoints.increment.initiate()) expect(firstValue).toMatchObject({ data: 0, status: 'fulfilled' }) // dispatch another increment const secondValuePromise = store.dispatch(api.endpoints.increment.initiate()) // and one with a forced refresh const thirdValuePromise = store.dispatch( api.endpoints.increment.initiate(undefined, { forceRefetch: true }), ) // and another increment const fourthValuePromise = store.dispatch(api.endpoints.increment.initiate()) const secondValue = await secondValuePromise const thirdValue = await thirdValuePromise const fourthValue = await fourthValuePromise expect(secondValue).toMatchObject({ data: firstValue.data, status: 'fulfilled', requestId: firstValue.requestId, }) expect(thirdValue).toMatchObject({ data: 1, status: 'fulfilled' }) expect(thirdValue.requestId).not.toBe(firstValue.requestId) expect(fourthValue).toMatchObject({ data: thirdValue.data, status: 'fulfilled', requestId: thirdValue.requestId, }) }) describe('calling initiate without a cache entry, with subscribe: false still returns correct values', () => { test('successful query', async () => { const { store, api } = storeRef calls = 0 const promise = store.dispatch( api.endpoints.increment.initiate(undefined, { subscribe: false }), ) expect(isRequestSubscribed('increment(undefined)', promise.requestId)).toBe( false, ) expect( isRequestSubscribed( 'increment(undefined)', `${promise.requestId}_running`, ), ).toBe(true) await expect(promise).resolves.toMatchObject({ data: 0, status: 'fulfilled', }) expect( isRequestSubscribed( 'increment(undefined)', `${promise.requestId}_running`, ), ).toBe(false) }) test('rejected query', async () => { const { store, api } = storeRef calls = 0 const promise = store.dispatch( api.endpoints.failing.initiate(undefined, { subscribe: false }), ) expect(isRequestSubscribed('failing(undefined)', promise.requestId)).toBe( false, ) expect( isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`), ).toBe(true) await expect(promise).resolves.toMatchObject({ status: 'rejected', }) expect( isRequestSubscribed('failing(undefined)', `${promise.requestId}_running`), ).toBe(false) }) }) describe('calling initiate should have resulting queryCacheKey match baseQuery queryCacheKey', () => { const baseQuery = vi.fn(() => ({ data: 'success' })) function getNewApi() { return createApi({ baseQuery, endpoints: (build) => ({ query: build.query({ query: (args) => `queryUrl/${args.arg1}/${args.arg2}`, }), mutation: build.mutation({ query: () => 'mutationUrl', }), }), }) } let api = getNewApi() beforeEach(() => { baseQuery.mockClear() api = getNewApi() }) test('should be a string and matching on queries', () => { const { store: storeApi } = setupApiStore(api, undefined, { withoutTestLifecycles: true, }) const promise = storeApi.dispatch( api.endpoints.query.initiate({ arg2: 'secondArg', arg1: 'firstArg' }), ) expect(baseQuery).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ queryCacheKey: promise.queryCacheKey, }), undefined, ) }) test('should be undefined and matching on mutations', () => { const { store: storeApi } = setupApiStore(api, undefined, { withoutTestLifecycles: true, }) storeApi.dispatch( api.endpoints.mutation.initiate({ arg2: 'secondArg', arg1: 'firstArg' }), ) expect(baseQuery).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ queryCacheKey: undefined, }), undefined, ) }) })