diff --git a/package-lock.json b/package-lock.json index 62c93e35..29c0b87c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,6 +57,7 @@ "@stryker-mutator/typescript-checker": "^6.0.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", + "@testing-library/user-event": "^14.1.1", "@types/classnames": "^2.3.1", "@types/enzyme": "^3.10.11", "@types/jest": "^27.4.1", @@ -5494,6 +5495,19 @@ "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": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -31968,6 +31982,13 @@ "@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": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", diff --git a/package.json b/package.json index 5c259e5b..d3fc6a9e 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "@stryker-mutator/typescript-checker": "^6.0.2", "@testing-library/jest-dom": "^5.16.4", "@testing-library/react": "^13.1.1", + "@testing-library/user-event": "^14.1.1", "@types/classnames": "^2.3.1", "@types/enzyme": "^3.10.11", "@types/jest": "^27.4.1", diff --git a/test/common/AppUpdateBanner.test.tsx b/test/common/AppUpdateBanner.test.tsx index 8144be33..5e9d8d83 100644 --- a/test/common/AppUpdateBanner.test.tsx +++ b/test/common/AppUpdateBanner.test.tsx @@ -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'; describe('', () => { const toggle = jest.fn(); const forceUpdate = jest.fn(); - - beforeEach(() => render()); + const setUp = () => ({ + user: userEvent.setup(), + ...render(), + }); afterEach(jest.clearAllMocks); it('renders initial state', () => { + setUp(); + expect(screen.getByRole('heading')).toHaveTextContent('This app has just been updated!'); expect(screen.queryByText('Restarting...')).not.toBeInTheDocument(); 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(); - fireEvent.click(screen.getByLabelText('Close')); + await user.click(screen.getByLabelText('Close')); expect(toggle).toHaveBeenCalled(); }); it('triggers the update when clicking the button', async () => { + const { user } = setUp(); + expect(forceUpdate).not.toHaveBeenCalled(); - fireEvent.click(screen.getByText(/^Restart now/)); + await user.click(screen.getByText(/^Restart now/)); expect(forceUpdate).toHaveBeenCalled(); expect(await screen.findByText('Restarting...')).toBeInTheDocument(); expect(screen.queryByText(/^Restart now/)).not.toBeInTheDocument(); diff --git a/test/domains/ManageDomains.test.tsx b/test/domains/ManageDomains.test.tsx index 697334e2..85fc2e80 100644 --- a/test/domains/ManageDomains.test.tsx +++ b/test/domains/ManageDomains.test.tsx @@ -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 { DomainsList } from '../../src/domains/reducers/domainsList'; import { ManageDomains } from '../../src/domains/ManageDomains'; @@ -8,16 +9,19 @@ import { SelectedServer } from '../../src/servers/data'; describe('', () => { const listDomains = jest.fn(); const filterDomains = jest.fn(); - const setUp = (domainsList: DomainsList) => render( - ()} - />, - ); + const setUp = (domainsList: DomainsList) => ({ + user: userEvent.setup(), + ...render( + ()} + />, + ), + }); afterEach(jest.clearAllMocks); @@ -40,11 +44,11 @@ describe('', () => { }); it('filters domains when SearchField changes', async () => { - setUp(Mock.of({ loading: false, error: false, filteredDomains: [] })); + const { user } = setUp(Mock.of({ loading: false, error: false, filteredDomains: [] })); expect(filterDomains).not.toHaveBeenCalled(); - fireEvent.change(screen.getByPlaceholderText('Search...'), { target: { value: 'Foo' } }); - await waitFor(() => expect(filterDomains).toHaveBeenCalledTimes(1)); + await user.type(screen.getByPlaceholderText('Search...'), 'Foo'); + await waitFor(() => expect(filterDomains).toHaveBeenCalledWith('Foo')); }); it('shows expected headers and one row when list of domains is empty', () => { diff --git a/test/domains/helpers/DomainStatusIcon.test.tsx b/test/domains/helpers/DomainStatusIcon.test.tsx index e7e1913b..51840c1c 100644 --- a/test/domains/helpers/DomainStatusIcon.test.tsx +++ b/test/domains/helpers/DomainStatusIcon.test.tsx @@ -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 { DomainStatus } from '../../../src/domains/data'; import { DomainStatusIcon } from '../../../src/domains/helpers/DomainStatusIcon'; describe('', () => { const matchMedia = jest.fn().mockReturnValue(Mock.of({ matches: false })); - const setUp = (status: DomainStatus) => render(); + const setUp = (status: DomainStatus) => ({ + user: userEvent.setup(), + ...render(), + }); beforeEach(jest.clearAllMocks); @@ -22,9 +26,9 @@ describe('', () => { ['invalid' as DomainStatus], ['valid' as DomainStatus], ])('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(); }); }); diff --git a/test/servers/EditServer.test.tsx b/test/servers/EditServer.test.tsx index 818578bc..106fc5c0 100644 --- a/test/servers/EditServer.test.tsx +++ b/test/servers/EditServer.test.tsx @@ -1,4 +1,5 @@ import { fireEvent, render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { Mock } from 'ts-mockery'; import { useNavigate } from 'react-router-dom'; import { EditServer as editServerConstruct } from '../../src/servers/EditServer'; @@ -17,9 +18,10 @@ describe('', () => { apiKey: 'the_api_key', }); const EditServer = editServerConstruct(ServerError); - const setUp = (selectedServer: SelectedServer = defaultSelectedServer) => render( - , - ); + const setUp = (selectedServer: SelectedServer = defaultSelectedServer) => ({ + user: userEvent.setup(), + ...render(), + }); beforeEach(() => { (useNavigate as any).mockReturnValue(navigate); @@ -48,16 +50,18 @@ describe('', () => { expect(screen.getByDisplayValue('the_api_key')).toBeInTheDocument(); }); - it('edits server and redirects to it when form is submitted', () => { - setUp(); + it('edits server and redirects to it when form is submitted', async () => { + const { user } = setUp(); - fireEvent.change(screen.getByDisplayValue('the_name'), { target: { value: 'the_new_name' } }); - fireEvent.change(screen.getByDisplayValue('the_url'), { target: { value: 'the_new_url' } }); + await user.type(screen.getByDisplayValue('the_name'), ' edited'); + 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')); expect(editServerMock).toHaveBeenCalledWith('abc123', { - name: 'the_new_name', - url: 'the_new_url', + name: 'the_name edited', + url: 'the_url edited', apiKey: 'the_api_key', }); expect(navigate).toHaveBeenCalledWith(-1);