I know that there are already questions about this but I can't find a definite answer. I am using SvelteKit and I tried to mock $app/navigation likes this in setup file.
jest.mock('$app/navigation', () => {
return {
__esModule: true,
goto: jest.fn().mockImplementation((target) => console.log(target))
};
});
I test a component that call goto. It is indeed called because there is a console.log call in the test output. When I tried to test it with expect(goto).toHaveBeenCalled(), it fails.
// SvelteKit
import * as navigations from '$app/navigation';
it('show error when account does not exists', async () => {
// render is in before Each
await fireEvent.change(screen.getByLabelText('Email'), {
target: { value: 'example@email.com' }
});
await fireEvent.change(screen.getByLabelText('Password'), {
target: { value: 'B@adPass0rd' }
});
await fireEvent.click(screen.getByRole('button'));
// There is no problem. It should redirect.
expect(navigations.goto).toHaveBeenCalled();
});
Output
console.log
/success
at log (jest-setup.js:6:58)
FAIL src/lib/routes-tests/login.test.js
Login
✕ show error when account does not exists (23 ms)
● Login › show error when account does not exists
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
24 | await fireEvent.click(screen.getByRole('button'));
25 | // expect(screen.queryByText('Account does not exist')).not.toBeNull();
> 26 | expect(navigations.goto).toHaveBeenCalled();
| ^
27 | });
28 | });
29 |
at toHaveBeenCalled (src/lib/routes-tests/login.test.js:26:28)
at tryCatch (src/lib/routes-tests/login.test.js:23:2404)
at Generator._invoke (src/lib/routes-tests/login.test.js:23:1964)
at Generator.next (src/lib/routes-tests/login.test.js:23:3255)
at asyncGeneratorStep (src/lib/routes-tests/login.test.js:25:103)
at _next (src/lib/routes-tests/login.test.js:27:194)
It turns out that I called goto in async function. I must use waitFor to expect the change.
await waitFor(() => expect(navigations.goto).toHaveBeenCalled())