mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-01-03 14:57:22 +03:00
Migrated to testing-library/user-event for complex events in tests
This commit is contained in:
parent
686fe5abbe
commit
7f059c3f3b
6 changed files with 76 additions and 33 deletions
21
package-lock.json
generated
21
package-lock.json
generated
|
@ -57,6 +57,7 @@
|
||||||
"@stryker-mutator/typescript-checker": "^6.0.2",
|
"@stryker-mutator/typescript-checker": "^6.0.2",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.1.1",
|
"@testing-library/react": "^13.1.1",
|
||||||
|
"@testing-library/user-event": "^14.1.1",
|
||||||
"@types/classnames": "^2.3.1",
|
"@types/classnames": "^2.3.1",
|
||||||
"@types/enzyme": "^3.10.11",
|
"@types/enzyme": "^3.10.11",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
|
@ -5494,6 +5495,19 @@
|
||||||
"react-dom": "^18.0.0"
|
"react-dom": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@testing-library/user-event": {
|
||||||
|
"version": "14.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz",
|
||||||
|
"integrity": "sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12",
|
||||||
|
"npm": ">=6"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@testing-library/dom": ">=7.21.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@tootallnate/once": {
|
"node_modules/@tootallnate/once": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||||
|
@ -31968,6 +31982,13 @@
|
||||||
"@types/react-dom": "^18.0.0"
|
"@types/react-dom": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@testing-library/user-event": {
|
||||||
|
"version": "14.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.1.1.tgz",
|
||||||
|
"integrity": "sha512-XrjH/iEUqNl9lF2HX9YhPNV7Amntkcnpw0Bo1KkRzowNDcgSN9i0nm4Q8Oi5wupgdfPaJNMAWa61A+voD6Kmwg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"@tootallnate/once": {
|
"@tootallnate/once": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
"@stryker-mutator/typescript-checker": "^6.0.2",
|
"@stryker-mutator/typescript-checker": "^6.0.2",
|
||||||
"@testing-library/jest-dom": "^5.16.4",
|
"@testing-library/jest-dom": "^5.16.4",
|
||||||
"@testing-library/react": "^13.1.1",
|
"@testing-library/react": "^13.1.1",
|
||||||
|
"@testing-library/user-event": "^14.1.1",
|
||||||
"@types/classnames": "^2.3.1",
|
"@types/classnames": "^2.3.1",
|
||||||
"@types/enzyme": "^3.10.11",
|
"@types/enzyme": "^3.10.11",
|
||||||
"@types/jest": "^27.4.1",
|
"@types/jest": "^27.4.1",
|
||||||
|
|
|
@ -1,29 +1,38 @@
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { AppUpdateBanner } from '../../src/common/AppUpdateBanner';
|
import { AppUpdateBanner } from '../../src/common/AppUpdateBanner';
|
||||||
|
|
||||||
describe('<AppUpdateBanner />', () => {
|
describe('<AppUpdateBanner />', () => {
|
||||||
const toggle = jest.fn();
|
const toggle = jest.fn();
|
||||||
const forceUpdate = jest.fn();
|
const forceUpdate = jest.fn();
|
||||||
|
const setUp = () => ({
|
||||||
beforeEach(() => render(<AppUpdateBanner isOpen toggle={toggle} forceUpdate={forceUpdate} />));
|
user: userEvent.setup(),
|
||||||
|
...render(<AppUpdateBanner isOpen toggle={toggle} forceUpdate={forceUpdate} />),
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
it('renders initial state', () => {
|
it('renders initial state', () => {
|
||||||
|
setUp();
|
||||||
|
|
||||||
expect(screen.getByRole('heading')).toHaveTextContent('This app has just been updated!');
|
expect(screen.getByRole('heading')).toHaveTextContent('This app has just been updated!');
|
||||||
expect(screen.queryByText('Restarting...')).not.toBeInTheDocument();
|
expect(screen.queryByText('Restarting...')).not.toBeInTheDocument();
|
||||||
expect(screen.getByText('Restart now')).not.toHaveAttribute('disabled');
|
expect(screen.getByText('Restart now')).not.toHaveAttribute('disabled');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('invokes toggle when alert is closed', () => {
|
it('invokes toggle when alert is closed', async () => {
|
||||||
|
const { user } = setUp();
|
||||||
|
|
||||||
expect(toggle).not.toHaveBeenCalled();
|
expect(toggle).not.toHaveBeenCalled();
|
||||||
fireEvent.click(screen.getByLabelText('Close'));
|
await user.click(screen.getByLabelText('Close'));
|
||||||
expect(toggle).toHaveBeenCalled();
|
expect(toggle).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('triggers the update when clicking the button', async () => {
|
it('triggers the update when clicking the button', async () => {
|
||||||
|
const { user } = setUp();
|
||||||
|
|
||||||
expect(forceUpdate).not.toHaveBeenCalled();
|
expect(forceUpdate).not.toHaveBeenCalled();
|
||||||
fireEvent.click(screen.getByText(/^Restart now/));
|
await user.click(screen.getByText(/^Restart now/));
|
||||||
expect(forceUpdate).toHaveBeenCalled();
|
expect(forceUpdate).toHaveBeenCalled();
|
||||||
expect(await screen.findByText('Restarting...')).toBeInTheDocument();
|
expect(await screen.findByText('Restarting...')).toBeInTheDocument();
|
||||||
expect(screen.queryByText(/^Restart now/)).not.toBeInTheDocument();
|
expect(screen.queryByText(/^Restart now/)).not.toBeInTheDocument();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { DomainsList } from '../../src/domains/reducers/domainsList';
|
import { DomainsList } from '../../src/domains/reducers/domainsList';
|
||||||
import { ManageDomains } from '../../src/domains/ManageDomains';
|
import { ManageDomains } from '../../src/domains/ManageDomains';
|
||||||
|
@ -8,16 +9,19 @@ import { SelectedServer } from '../../src/servers/data';
|
||||||
describe('<ManageDomains />', () => {
|
describe('<ManageDomains />', () => {
|
||||||
const listDomains = jest.fn();
|
const listDomains = jest.fn();
|
||||||
const filterDomains = jest.fn();
|
const filterDomains = jest.fn();
|
||||||
const setUp = (domainsList: DomainsList) => render(
|
const setUp = (domainsList: DomainsList) => ({
|
||||||
<ManageDomains
|
user: userEvent.setup(),
|
||||||
listDomains={listDomains}
|
...render(
|
||||||
filterDomains={filterDomains}
|
<ManageDomains
|
||||||
editDomainRedirects={jest.fn()}
|
listDomains={listDomains}
|
||||||
checkDomainHealth={jest.fn()}
|
filterDomains={filterDomains}
|
||||||
domainsList={domainsList}
|
editDomainRedirects={jest.fn()}
|
||||||
selectedServer={Mock.all<SelectedServer>()}
|
checkDomainHealth={jest.fn()}
|
||||||
/>,
|
domainsList={domainsList}
|
||||||
);
|
selectedServer={Mock.all<SelectedServer>()}
|
||||||
|
/>,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(jest.clearAllMocks);
|
afterEach(jest.clearAllMocks);
|
||||||
|
|
||||||
|
@ -40,11 +44,11 @@ describe('<ManageDomains />', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters domains when SearchField changes', async () => {
|
it('filters domains when SearchField changes', async () => {
|
||||||
setUp(Mock.of<DomainsList>({ loading: false, error: false, filteredDomains: [] }));
|
const { user } = setUp(Mock.of<DomainsList>({ loading: false, error: false, filteredDomains: [] }));
|
||||||
|
|
||||||
expect(filterDomains).not.toHaveBeenCalled();
|
expect(filterDomains).not.toHaveBeenCalled();
|
||||||
fireEvent.change(screen.getByPlaceholderText('Search...'), { target: { value: 'Foo' } });
|
await user.type(screen.getByPlaceholderText('Search...'), 'Foo');
|
||||||
await waitFor(() => expect(filterDomains).toHaveBeenCalledTimes(1));
|
await waitFor(() => expect(filterDomains).toHaveBeenCalledWith('Foo'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows expected headers and one row when list of domains is empty', () => {
|
it('shows expected headers and one row when list of domains is empty', () => {
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { DomainStatus } from '../../../src/domains/data';
|
import { DomainStatus } from '../../../src/domains/data';
|
||||||
import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon';
|
import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon';
|
||||||
|
|
||||||
describe('<DomainStatusIcon />', () => {
|
describe('<DomainStatusIcon />', () => {
|
||||||
const matchMedia = jest.fn().mockReturnValue(Mock.of<MediaQueryList>({ matches: false }));
|
const matchMedia = jest.fn().mockReturnValue(Mock.of<MediaQueryList>({ matches: false }));
|
||||||
const setUp = (status: DomainStatus) => render(<DomainStatusIcon status={status} matchMedia={matchMedia} />);
|
const setUp = (status: DomainStatus) => ({
|
||||||
|
user: userEvent.setup(),
|
||||||
|
...render(<DomainStatusIcon status={status} matchMedia={matchMedia} />),
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(jest.clearAllMocks);
|
beforeEach(jest.clearAllMocks);
|
||||||
|
|
||||||
|
@ -22,9 +26,9 @@ describe('<DomainStatusIcon />', () => {
|
||||||
['invalid' as DomainStatus],
|
['invalid' as DomainStatus],
|
||||||
['valid' as DomainStatus],
|
['valid' as DomainStatus],
|
||||||
])('renders proper tooltip based on state', async (status) => {
|
])('renders proper tooltip based on state', async (status) => {
|
||||||
const { container } = setUp(status);
|
const { container, user } = setUp(status);
|
||||||
|
|
||||||
container.firstChild && fireEvent.mouseOver(container.firstChild);
|
container.firstElementChild && await user.hover(container.firstElementChild);
|
||||||
expect(await screen.findByRole('tooltip')).toMatchSnapshot();
|
expect(await screen.findByRole('tooltip')).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { fireEvent, render, screen } from '@testing-library/react';
|
import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
import { Mock } from 'ts-mockery';
|
import { Mock } from 'ts-mockery';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { EditServer as editServerConstruct } from '../../src/servers/EditServer';
|
import { EditServer as editServerConstruct } from '../../src/servers/EditServer';
|
||||||
|
@ -17,9 +18,10 @@ describe('<EditServer />', () => {
|
||||||
apiKey: 'the_api_key',
|
apiKey: 'the_api_key',
|
||||||
});
|
});
|
||||||
const EditServer = editServerConstruct(ServerError);
|
const EditServer = editServerConstruct(ServerError);
|
||||||
const setUp = (selectedServer: SelectedServer = defaultSelectedServer) => render(
|
const setUp = (selectedServer: SelectedServer = defaultSelectedServer) => ({
|
||||||
<EditServer editServer={editServerMock} selectedServer={selectedServer} selectServer={jest.fn()} />,
|
user: userEvent.setup(),
|
||||||
);
|
...render(<EditServer editServer={editServerMock} selectedServer={selectedServer} selectServer={jest.fn()} />),
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
(useNavigate as any).mockReturnValue(navigate);
|
(useNavigate as any).mockReturnValue(navigate);
|
||||||
|
@ -48,16 +50,18 @@ describe('<EditServer />', () => {
|
||||||
expect(screen.getByDisplayValue('the_api_key')).toBeInTheDocument();
|
expect(screen.getByDisplayValue('the_api_key')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('edits server and redirects to it when form is submitted', () => {
|
it('edits server and redirects to it when form is submitted', async () => {
|
||||||
setUp();
|
const { user } = setUp();
|
||||||
|
|
||||||
fireEvent.change(screen.getByDisplayValue('the_name'), { target: { value: 'the_new_name' } });
|
await user.type(screen.getByDisplayValue('the_name'), ' edited');
|
||||||
fireEvent.change(screen.getByDisplayValue('the_url'), { target: { value: 'the_new_url' } });
|
await user.type(screen.getByDisplayValue('the_url'), ' edited');
|
||||||
|
// TODO Using fire event because userEvent.click on the Submit button does not submit the form
|
||||||
|
// await user.click(screen.getByRole('button', { name: 'Save' }));
|
||||||
fireEvent.submit(screen.getByRole('form'));
|
fireEvent.submit(screen.getByRole('form'));
|
||||||
|
|
||||||
expect(editServerMock).toHaveBeenCalledWith('abc123', {
|
expect(editServerMock).toHaveBeenCalledWith('abc123', {
|
||||||
name: 'the_new_name',
|
name: 'the_name edited',
|
||||||
url: 'the_new_url',
|
url: 'the_url edited',
|
||||||
apiKey: 'the_api_key',
|
apiKey: 'the_api_key',
|
||||||
});
|
});
|
||||||
expect(navigate).toHaveBeenCalledWith(-1);
|
expect(navigate).toHaveBeenCalledWith(-1);
|
||||||
|
|
Loading…
Reference in a new issue