Skip to content

Commit

Permalink
👽 [#724] Update tests and stories to work with Vitest
Browse files Browse the repository at this point in the history
* Replaced the jest mocks with vi mocks (which is the equivalent in
  vitest)
* Replaced useFakeTimers with just mocking the system date/time, which
  is simpler in vitest. Note that using fake timers seems to have some
  challenges, but ultimately there shouldn't really be a need for that
  anymore.
* Updated the stories to deal with the index.js -> index.jsx renames,
  which don't automatically resolve when doing directory imports
* Rewrite more tests from legacy react test utils to testing-library/
  react style tests, which are more pleasant to read and write and do
  encourage proper accessible queries
  • Loading branch information
sergei-maertens committed Nov 26, 2024
1 parent ec5a663 commit 2e4447b
Show file tree
Hide file tree
Showing 41 changed files with 384 additions and 606 deletions.
2 changes: 1 addition & 1 deletion src/components/Anchor/Anchor.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Anchor, {ANCHOR_MODIFIERS} from '.';
import Anchor, {ANCHOR_MODIFIERS} from './index';

export default {
title: 'Pure React components / Anchor',
Expand Down
12 changes: 6 additions & 6 deletions src/components/ButtonsToolbar/test.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const Wrap = ({children}) => (
);

it('Last step of submittable form, button is present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

act(() => {
root.render(
Expand Down Expand Up @@ -76,7 +76,7 @@ it('Last step of submittable form, button is present', () => {
});

it('Last step of non-submittable form with overview, button is present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

act(() => {
root.render(
Expand Down Expand Up @@ -107,7 +107,7 @@ it('Last step of non-submittable form with overview, button is present', () => {
});

it('Last step of non-submittable form without overview, button is NOT present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

act(() => {
root.render(
Expand Down Expand Up @@ -137,7 +137,7 @@ it('Last step of non-submittable form without overview, button is NOT present',
});

it('Non-last step of non-submittable form without overview, button IS present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

act(() => {
root.render(
Expand Down Expand Up @@ -168,7 +168,7 @@ it('Non-last step of non-submittable form without overview, button IS present',
});

it('Suspending form allowed, button is present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

renderTest(
<Wrap>
Expand All @@ -191,7 +191,7 @@ it('Suspending form allowed, button is present', () => {
});

it('Suspending form not allowed, button is NOT present', () => {
const mockFunction = jest.fn();
const mockFunction = vi.fn();

renderTest(
<Wrap>
Expand Down
49 changes: 13 additions & 36 deletions src/components/CoSign/test.spec.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,12 @@
import {render, screen} from '@testing-library/react';
import messagesNL from 'i18n/compiled/nl.json';
import React from 'react';
import {createRoot} from 'react-dom/client';
import {act} from 'react-dom/test-utils';
import {IntlProvider} from 'react-intl';

import {testLoginForm} from 'components/FormStart/fixtures';

import {CoSignAuthentication} from './index';

let container = null;
let root = null;
beforeEach(() => {
// setup a DOM element as a render target
container = document.createElement('div');
document.body.appendChild(container);
root = createRoot(container);
});

afterEach(() => {
// cleanup on exiting
act(() => {
root.unmount();
container.remove();
root = null;
container = null;
});
});

it('CoSign component constructs the right auth URL', () => {
// Control the location that the test will use
const {location} = window;
Expand All @@ -35,25 +15,22 @@ it('CoSign component constructs the right auth URL', () => {
href: 'https://openforms.nl/form-name/step/step-name',
};

act(() => {
root.render(
<IntlProvider locale="nl" messages={messagesNL}>
<CoSignAuthentication
form={testLoginForm}
submissionUuid="111-222-333"
authPlugin="digid"
saveStepData={() => {}}
/>
</IntlProvider>
);
});
render(
<IntlProvider locale="nl" messages={messagesNL}>
<CoSignAuthentication
form={testLoginForm}
submissionUuid="111-222-333"
authPlugin="digid"
saveStepData={() => {}}
/>
</IntlProvider>
);

// Reset location
window.location = location;

const loginButton = container.getElementsByTagName('a')[0];

expect(loginButton.textContent).toEqual('Inloggen met DigiD');
const loginButton = screen.getByRole('link', {name: 'Inloggen met DigiD'});
expect(loginButton).toBeVisible();

const loginUrl = new URL(loginButton.href);

Expand Down
2 changes: 1 addition & 1 deletion src/components/EditGrid/EditGrid.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {fn} from '@storybook/test';
import Body from 'components/Body';
import {OFButton} from 'components/Button';

import {EditGrid, EditGridButtonGroup, EditGridItem} from '.';
import {EditGrid, EditGridButtonGroup, EditGridItem} from './index';

export default {
title: 'Pure React components / EditGrid / EditGrid',
Expand Down
2 changes: 1 addition & 1 deletion src/components/EditGrid/EditGridItem.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Body from 'components/Body';
import {OFButton} from 'components/Button';

import {EditGridButtonGroup, EditGridItem as EditGridItemComponent} from '.';
import {EditGridButtonGroup, EditGridItem as EditGridItemComponent} from './index';

export default {
title: 'Pure React components / EditGrid / Item',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {withRouter} from 'storybook-addon-remix-react-router';
import {BASE_URL} from 'api-mocks';
import {ConfigDecorator} from 'story-utils/decorators';

import {EmailVerificationForm} from '.';
import {EmailVerificationForm} from './index';
import {
mockEmailVerificationErrorPost,
mockEmailVerificationPost,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {fn} from '@storybook/test';
import {BASE_URL} from 'api-mocks';
import {ConfigDecorator} from 'story-utils/decorators';

import {EmailVerificationModal} from '.';
import {EmailVerificationModal} from './index';
import {mockEmailVerificationPost, mockEmailVerificationVerifyCodePost} from './mocks';

export default {
Expand Down
6 changes: 3 additions & 3 deletions src/components/Form.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {routes} from 'components/App';

import {START_FORM_QUERY_PARAM} from './constants';

window.scrollTo = jest.fn();
window.scrollTo = vi.fn();

beforeEach(() => {
localStorage.clear();
Expand All @@ -23,7 +23,7 @@ afterEach(() => {
});

afterAll(() => {
jest.clearAllMocks();
vi.clearAllMocks();
});

const Wrapper = ({form = buildForm(), initialEntry = '/startpagina'}) => {
Expand Down Expand Up @@ -54,7 +54,7 @@ const Wrapper = ({form = buildForm(), initialEntry = '/startpagina'}) => {

test('Start form anonymously', async () => {
const user = userEvent.setup();
mswServer.use(mockSubmissionPost(), mockAnalyticsToolConfigGet(), mockSubmissionStepGet);
mswServer.use(mockSubmissionPost(), mockAnalyticsToolConfigGet(), mockSubmissionStepGet());
let startSubmissionRequest;
mswServer.events.on('request:match', async ({request}) => {
const url = new URL(request.url);
Expand Down
26 changes: 13 additions & 13 deletions src/components/FormStart/tests.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import {MemoryRouter} from 'react-router-dom';
import {buildSubmission} from 'api-mocks';
import useQuery from 'hooks/useQuery';

import FormStart from '.';
import {testForm, testLoginForm} from './fixtures';
import FormStart from './index';

jest.mock('hooks/useQuery');
let scrollIntoViewMock = jest.fn();
vi.mock('hooks/useQuery');
let scrollIntoViewMock = vi.fn();
window.HTMLElement.prototype.scrollIntoView = scrollIntoViewMock;

const Wrap = ({children}) => (
Expand All @@ -24,8 +24,8 @@ it('Form start page start if _start parameter is present', async () => {
const testLocation = new URLSearchParams('?_start=1');
useQuery.mockReturnValue(testLocation);

const onFormStart = jest.fn();
const onDestroySession = jest.fn();
const onFormStart = vi.fn();
const onDestroySession = vi.fn();

render(
<Wrap>
Expand Down Expand Up @@ -55,8 +55,8 @@ it.each([
])(
'Form start does not start if there are auth errors / %s',
async (testQuery, expectedMessage) => {
const onFormStart = jest.fn();
const onDestroySession = jest.fn();
const onFormStart = vi.fn();
const onDestroySession = vi.fn();

const testLocation = new URLSearchParams(`?_start=1&${testQuery}`);
useQuery.mockReturnValue(testLocation);
Expand All @@ -74,8 +74,8 @@ it.each([

it('Form start page does not show login buttons if an active submission is present', async () => {
useQuery.mockReturnValue(new URLSearchParams());
const onFormStart = jest.fn();
const onDestroySession = jest.fn();
const onFormStart = vi.fn();
const onDestroySession = vi.fn();

render(
<Wrap>
Expand All @@ -95,8 +95,8 @@ it('Form start page does not show login buttons if an active submission is prese

it('Form start page with initial_data_reference', async () => {
useQuery.mockReturnValue(new URLSearchParams());
const onFormStart = jest.fn();
const onDestroySession = jest.fn();
const onFormStart = vi.fn();
const onDestroySession = vi.fn();

render(
<Wrap>
Expand All @@ -118,8 +118,8 @@ it('Form start page with initial_data_reference', async () => {

it('Form start page without initial_data_reference', async () => {
useQuery.mockReturnValue(new URLSearchParams());
const onFormStart = jest.fn();
const onDestroySession = jest.fn();
const onFormStart = vi.fn();
const onDestroySession = vi.fn();

render(
<Wrap>
Expand Down
2 changes: 1 addition & 1 deletion src/components/FormStep/FormStep.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
import {AnalyticsToolsDecorator, ConfigDecorator} from 'story-utils/decorators';
import {sleep} from 'utils';

import FormStep from '.';
import FormStep from './index';
import {
getSubmissionStepDetail,
mockSubmissionLogicCheckPost,
Expand Down
2 changes: 1 addition & 1 deletion src/components/FormStepSummary/FormStepSummary.stories.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {expect, within} from '@storybook/test';
import {withRouter} from 'storybook-addon-remix-react-router';

import FormStepSummary from '.';
import FormStepSummary from './index';

export default {
title: 'Private API / FormStepSummary',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {withRouter} from 'storybook-addon-remix-react-router';
import {buildForm} from 'api-mocks';
import {withForm} from 'story-utils/decorators';

import IntroductionPage from '.';
import IntroductionPage from './index';

const DEFAULT_CONTENT = `
<h2>Voorwaarden</h2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ErrorBoundary from 'components/Errors/ErrorBoundary';
import {I18NContext} from 'i18n';
import {ConfigDecorator} from 'story-utils/decorators';

import {LanguageSelection, LanguageSelectionDisplay} from '.';
import {LanguageSelection, LanguageSelectionDisplay} from './index';
import {
DEFAULT_LANGUAGES,
mockInvalidLanguageChoicePut,
Expand Down
2 changes: 1 addition & 1 deletion src/components/LoginOptions/LoginOptions.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {withRouter} from 'storybook-addon-remix-react-router';
import {buildForm} from 'api-mocks';
import {LiteralDecorator} from 'story-utils/decorators';

import LoginOptions from '.';
import LoginOptionsDisplay from './LoginOptionsDisplay';
import LoginOptions from './index';

export default {
title: 'Composites / Login Options',
Expand Down
4 changes: 2 additions & 2 deletions src/components/LoginOptions/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ const LoginOptions = ({form, onFormStart, extraNextParams = {}, isolateCosignOpt
const containerProps = form.loginRequired
? {}
: {
onSubmit: e => {
onSubmit: async e => {
e.preventDefault();
onFormStart(e, true);
await onFormStart(e, true);
},
'data-testid': 'start-form',
};
Expand Down
6 changes: 3 additions & 3 deletions src/components/LoginOptions/tests.spec.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const Wrapper = ({form, onFormStart}) => {
it('Login not required, options wrapped in form tag', async () => {
const user = userEvent.setup();
const form = buildForm({loginRequired: false, loginOptions: [], cosignLoginOptions: []});
const onFormStart = jest.fn(e => e.preventDefault());
const onFormStart = vi.fn(e => e.preventDefault());

render(<Wrapper form={form} onFormStart={onFormStart} />);

Expand Down Expand Up @@ -69,7 +69,7 @@ it('Login required, options not wrapped in form tag', async () => {
],
cosignLoginOptions: [],
});
const onFormStart = jest.fn(e => e.preventDefault());
const onFormStart = vi.fn(e => e.preventDefault());

const {location} = window;
delete window.location;
Expand Down Expand Up @@ -112,7 +112,7 @@ it('Login button has the right URL after cancelling log in', async () => {
cosignLoginOptions: [],
});

const onFormStart = jest.fn(e => e.preventDefault());
const onFormStart = vi.fn(e => e.preventDefault());

const {location} = window;
delete window.location;
Expand Down
2 changes: 1 addition & 1 deletion src/components/Map/Map.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {userEvent, within} from '@storybook/test';

import {ConfigDecorator} from 'story-utils/decorators';

import LeafletMap from '.';
import LeafletMap from './index';
import {mockAddressSearchGet, mockLatLngSearchEmptyGet, mockLatLngSearchGet} from './mocks';

const withMapLayout = Story => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {MINIMAL_VIEWPORTS} from '@storybook/addon-viewport';
import {expect, userEvent, within} from '@storybook/test';
import {withRouter} from 'storybook-addon-remix-react-router';

import ProgressIndicator from '.';
import ProgressIndicator from './index';

export default {
title: 'Private API / ProgressIndicator',
Expand Down
Loading

0 comments on commit 2e4447b

Please sign in to comment.