Search code examples
reactjsreduxvitereact-testing-libraryrtk-query

Cannot read properties of undefined (reading 'injectEndpoints')


I recently migrated my project from Create React App to Vite and subsequently decided to switch my testing framework to Vitest while retaining React Testing Library for my tests. Post migration, I've encountered an issue where my tests are failing due to a restructuring I did with my RTK Query endpoints. Initially, all my endpoints were housed in a single file, but for better readability and maintenance, I decided to split them using injectEndpoints. However, this change has led to test failures with the error message: "Cannot read properties of undefined (reading 'injectEndpoints')".

For mocking endpoints in my tests, I'm utilizing Mock Service Worker (MSW). Everything was functioning as expected prior to the migration and the restructuring of the endpoints. Now, I'm at a loss on how to resolve this issue to get my tests passing again with the new setup. Below is a version of how I've structured my endpoints and the relevant configurations:

Test

describe('Wall of experts', () => {
const user = {
    "givenName": "XXXX",
    "familyName": "XXXXX",
    "name": "XXXXX",
    "departmentnumber": "XXX",
    "email": "XXXXXXXXXXXX",
    "sub": "XXXXX",
    "authorities": ["XXXX", 'XX']
}

beforeAll(() => {
    initI18nMock({})
    add18nResourcesMock({
        "maintenance": {
            "infoTexts": {
                "user-email-address": "User email",
            }
        },
        "expertWall": {
            "infoTexts": {
                "success-update-message": "User has been successful updated",
                "success-remove-message": "User has been successful deleted",
                "success-add-message": "User has been successful added"
            }
        }
    })

    server.listen()
    store.dispatch(setLoggedUser(user))
})

afterEach(() => {
    // Cleanup
    add18nResourcesMock({})
    server.resetHandlers()
})

afterAll(() => {
    server.close()
})

it('should display wall of experts', async () => {
    customRender(<><AppSnackbar/><ExpertWall/></>)

    await screen.findAllByTestId('user')

    const displayedUsers = screen.queryAllByTestId('user')

    // Check rendered users amount against mocked data.
    expect(displayedUsers).toHaveLength(mockWallOfExperts.length)

})

Configuration test-utils to be able to run react testing library in vite.

afterEach(() => {
    cleanup()
})

const AllTheProviders = ({ children }: {children: React.ReactElement}) => {
    return (
        <BrowserRouter basename={'/'}>
            <Provider store={store}>{children}</Provider>
        </BrowserRouter>
    );
};

function customRender(ui: React.ReactElement, options= {})  {
    return render(ui, { wrapper: AllTheProviders, ...options });
}

export * from '@testing-library/react'
export { default as userEvent } from '@testing-library/user-event'
// override render export
export { customRender as render }

A store

const store = configureStore({
    reducer: {
        [datenlandkarteApi.reducerPath]: datenlandkarteApi.reducer,
        [cloudBMWApi.reducerPath]: cloudBMWApi.reducer,
        datenTicket: datenTicketReducer,
        dataRequestWizard: dataRequestWizardReducer,
        main: mainReducer,
    },
    middleware: (getDefaultMiddleware) =>
        getDefaultMiddleware().concat(datenlandkarteApi.middleware, cloudBMWApi.middleware),
});
export type RootState = ReturnType<typeof store.getState>;

export type AppDispatch = typeof store.dispatch;

export default store;

Here is a main file where all endpoints is and I just past beggining of it.

export const apiName = createApi({
    reducerPath: 'apiName ',
    baseQuery: fetchBaseQuery({
        mode: 'cors',
        baseUrl: `${baseUrl}/api/`,
        prepareHeaders: (headers) => {
            const token = getAccessToken();
            if (token) {
                headers.set('Authorization', `Bearer ${token}`);
                // headers.set('Accept', `application/json`);
            }
            return headers;
        },
    }),
    tagTypes: rtkTagTypesValues,
    endpoints: (build) => ({
        // GETTERS i.e. RTK query
        getPerson: build.query<api.PersonDTO, string>({
            query: (email) => ({
                url: `person/getByEmail/${email}`,
                responseHandler: mapToJson,
            }),
        }),

Here is my injectedEndpoints

const useCasePurposeApi = datenlandkarteApi.injectEndpoints({
    endpoints: (build) => ({
        getUseCasePurposes: build.query<UseCasePurposesShortDto, GetUseCasePurposesRequestDto>({
            query: ({ useCaseRef, pageNumber = 0, pageSize = 5 }) => {
                return {
                    url: `sec/use-case-purposes/${useCaseRef}/short?pageNumber=${pageNumber}&pageSize=${pageSize}`,
                };
            },
            providesTags: (result) => {
                if (result) {
                    return [RtkTagTypes.ALL_PRIVACY_PURPOSE];
                }
                return [];
            },
        }),

I've followed the documentation and examples for both Vite and Vitest, and reviewed the RTK Query documentation regarding injectEndpoints, yet I'm unable to pinpoint the cause of this error. Any insights or suggestions on how to resolve this issue and get my tests running successfully with the new configuration would be greatly appreciated. Thank you!

Additional thoughts: The issue might be related to RTK Query and perhaps there's a need to mock injectEndpoints in some way, although I'm not sure how to go about this. If anyone has faced a similar issue or has experience with mocking RTK Query in this setup, your advice would be invaluable.


Solution

  • So the answer is very simple I had a Circular dependencies, To solve this I used a madge

    npx madge --circular --extensions ts,tsx,jsx ./src