I'm migrating from jest to vitest and encountered an issue while checking if the navigate()
function returned from the useNavigate()
hook was called:
vitest setup.ts:
import matchers from '@testing-library/jest-dom/matchers';
import { expect, vi } from 'vitest';
expect.extend(matchers);
export const mockNavigate = vi.fn();
vi.mock('react-router-dom', async () => {
const router = await vi.importActual<typeof import('react-router-dom')>('react-router-dom');
return {
...router,
useNavigate: vi.fn().mockReturnValue(mockNavigate),
};
});
Component test:
import React from 'react';
import userEvent from '@testing-library/user-event';
import { screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import { SigninComponent } from '../../../../../../src/features/auth/components/signin.component';
import { renderWithProviders } from '../../../../utils';
import { mockNavigate } from '../../../../setup';
describe('Signin Component', () => {
it('navigates to signup page', async () => {
renderWithProviders(<SigninComponent />);
userEvent.click(screen.getByTestId('test-nav-btn'));
await screen.findByText('AppName');
expect(mockNavigate).toHaveBeenCalledWith('/signup');
});
});
Render with providers helper:
import React, { ReactNode } from 'react';
import { render } from '@testing-library/react';
import { gqlClient } from '../../src/common/gql/gql-auth';
import { Provider } from 'react-redux';
import { ApolloProvider } from '@apollo/client';
import { MemoryRouter } from 'react-router-dom';
import { store } from '../../src/common/state/store';
export const renderWithProviders = (component: ReactNode) => {
return render(
<Provider store={store}>
<ApolloProvider client={gqlClient}>
<MemoryRouter>{component}</MemoryRouter>
</ApolloProvider>
</Provider>,
);
};
Encountered error:
AssertionError: expected "spy" to be called with arguments: [ '/signup' ] Received: Number of calls: 0
depending on which version of user-event you are using you may need to await the click in your test. If you are using @testing-library/react v14 then you need to follow the guide here: Writing tests with userEvent @testing-library/react v14
so you import user-event as 'userEvent' and in your test setup you store the return value from userEvent.setup() init function in a variable called 'user'
then await the user.click() call in your test.
import userEvent from '@testing-library/user-event'
// inlining
test('trigger some awesome feature when clicking the button', async () => {
const user = userEvent.setup()
// Import `render` and `screen` from the framework library of your choice.
// See https://testing-library.com/docs/dom-testing-library/install#wrappers
render(<MyComponent />)
await user.click(screen.getByRole('button', {name: /click me!/i}))
// ...assertions...
})
but as Reese mentioned, you're effectively testing the RTL internal code.