import { createApi } from '@reduxjs/toolkit/query' import { actionsReducer, setupApiStore, waitMs } from './helpers' const baseQuery = (args?: any) => ({ data: args }) const api = createApi({ baseQuery, tagTypes: ['Banana', 'Bread'], endpoints: (build) => ({ getBanana: build.query({ query(id) { return { url: `banana/${id}` } }, providesTags: ['Banana'], }), getBananas: build.query({ query() { return { url: 'bananas' } }, providesTags: ['Banana'], }), getBread: build.query({ query(id) { return { url: `bread/${id}` } }, providesTags: ['Bread'], }), }), }) const { getBanana, getBread } = api.endpoints const storeRef = setupApiStore(api, { ...actionsReducer, }) it('invalidates the specified tags', async () => { await storeRef.store.dispatch(getBanana.initiate(1)) expect(storeRef.store.getState().actions).toMatchSequence( api.internalActions.middlewareRegistered.match, getBanana.matchPending, api.internalActions.subscriptionsUpdated.match, getBanana.matchFulfilled ) await storeRef.store.dispatch(api.util.invalidateTags(['Banana', 'Bread'])) // Slight pause to let the middleware run and such await waitMs(20) const firstSequence = [ api.internalActions.middlewareRegistered.match, getBanana.matchPending, api.internalActions.subscriptionsUpdated.match, getBanana.matchFulfilled, api.util.invalidateTags.match, getBanana.matchPending, getBanana.matchFulfilled, ] expect(storeRef.store.getState().actions).toMatchSequence(...firstSequence) await storeRef.store.dispatch(getBread.initiate(1)) await storeRef.store.dispatch(api.util.invalidateTags([{ type: 'Bread' }])) await waitMs(20) expect(storeRef.store.getState().actions).toMatchSequence( ...firstSequence, getBread.matchPending, api.internalActions.subscriptionsUpdated.match, getBread.matchFulfilled, api.util.invalidateTags.match, getBread.matchPending, getBread.matchFulfilled ) }) describe.skip('TS only tests', () => { it('should allow for an array of string TagTypes', () => { api.util.invalidateTags(['Banana', 'Bread']) }) it('should allow for an array of full TagTypes descriptions', () => { api.util.invalidateTags([{ type: 'Banana' }, { type: 'Bread', id: 1 }]) }) it('should allow for a mix of full descriptions as well as plain strings', () => { api.util.invalidateTags(['Banana', { type: 'Bread', id: 1 }]) }) it('should error when using non-existing TagTypes', () => { // @ts-expect-error api.util.invalidateTags(['Missing Tag']) }) it('should error when using non-existing TagTypes in the full format', () => { // @ts-expect-error api.util.invalidateTags([{ type: 'Missing' }]) }) it('should allow pre-fetching for an endpoint that takes an arg', () => { api.util.prefetch('getBanana', 5, { force: true }) api.util.prefetch('getBanana', 5, { force: false }) api.util.prefetch('getBanana', 5, { ifOlderThan: false }) api.util.prefetch('getBanana', 5, { ifOlderThan: 30 }) api.util.prefetch('getBanana', 5, {}) }) it('should error when pre-fetching with the incorrect arg type', () => { // @ts-expect-error arg should be number, not string api.util.prefetch('getBanana', '5', { force: true }) }) it('should allow pre-fetching for an endpoint with a void arg', () => { api.util.prefetch('getBananas', undefined, { force: true }) api.util.prefetch('getBananas', undefined, { force: false }) api.util.prefetch('getBananas', undefined, { ifOlderThan: false }) api.util.prefetch('getBananas', undefined, { ifOlderThan: 30 }) api.util.prefetch('getBananas', undefined, {}) }) it('should error when pre-fetching with a defined arg when expecting void', () => { // @ts-expect-error arg should be void, not number api.util.prefetch('getBananas', 5, { force: true }) }) it('should error when pre-fetching for an incorrect endpoint name', () => { // @ts-expect-error endpoint name does not exist api.util.prefetch('getPomegranates', undefined, { force: true }) }) })