diff --git a/src/__tests__/incidents/Incidents.test.tsx b/src/__tests__/incidents/Incidents.test.tsx index 6713cfc4d3..f1de1898f4 100644 --- a/src/__tests__/incidents/Incidents.test.tsx +++ b/src/__tests__/incidents/Incidents.test.tsx @@ -1,4 +1,4 @@ -import { render as rtlRender } from '@testing-library/react' +import { render } from '@testing-library/react' import React from 'react' import type { ReactElement, ReactNode } from 'react' import { Provider } from 'react-redux' @@ -21,7 +21,7 @@ type WrapperProps = { } describe('Incidents', () => { - function render(permissions: Permissions[], path: string) { + function setup(permissions: Permissions[], path: string) { const expectedIncident = { id: '1234', code: '1234', @@ -47,55 +47,53 @@ describe('Incidents', () => { ) } - const results = rtlRender(, { wrapper: Wrapper }) - - return results + return render(, { wrapper: Wrapper }) } describe('title', () => { it('should have called the useUpdateTitle hook', () => { - render([Permissions.ViewIncidents], '/incidents') + setup([Permissions.ViewIncidents], '/incidents') expect(titleUtil.useUpdateTitle).toHaveBeenCalledTimes(1) }) }) describe('routing', () => { describe('/incidents/new', () => { - it('should render the new incident screen when /incidents/new is accessed', () => { - const { container } = render([Permissions.ReportIncident], '/incidents/new') + it('The new incident screen when /incidents/new is accessed', () => { + const { container } = setup([Permissions.ReportIncident], '/incidents/new') expect(container).toHaveTextContent('incidents.reports') }) it('should not navigate to /incidents/new if the user does not have ReportIncident permissions', () => { - const { container } = render([], '/incidents/new') + const { container } = setup([], '/incidents/new') expect(container).not.toHaveTextContent('incidents.reports') }) }) describe('/incidents/visualize', () => { - it('should render the incident visualize screen when /incidents/visualize is accessed', () => { - const { container } = render([Permissions.ViewIncidentWidgets], '/incidents/visualize') + it('The incident visualize screen when /incidents/visualize is accessed', () => { + const { container } = setup([Permissions.ViewIncidentWidgets], '/incidents/visualize') expect(container.querySelector('.chartjs-render-monitor')).toBeInTheDocument() }) it('should not navigate to /incidents/visualize if the user does not have ViewIncidentWidgets permissions', () => { - const { container } = render([], '/incidents/visualize') + const { container } = setup([], '/incidents/visualize') expect(container.querySelector('.chartjs-render-monitor')).not.toBeInTheDocument() }) }) describe('/incidents/:id', () => { - it('should render the view incident screen when /incidents/:id is accessed', () => { - const { container } = render([Permissions.ViewIncident], '/incidents/1234') + it('The view incident screen when /incidents/:id is accessed', () => { + const { container } = setup([Permissions.ViewIncident], '/incidents/1234') expect(container.querySelectorAll('div').length).toBe(3) }) it('should not navigate to /incidents/:id if the user does not have ViewIncident permissions', () => { - const { container } = render([], '/incidents/1234') + const { container } = setup([], '/incidents/1234') expect(container.querySelectorAll('div').length).not.toBe(3) }) }) diff --git a/src/__tests__/incidents/report/ReportIncident.test.tsx b/src/__tests__/incidents/report/ReportIncident.test.tsx index 6e16c55f8d..6affa03aa3 100644 --- a/src/__tests__/incidents/report/ReportIncident.test.tsx +++ b/src/__tests__/incidents/report/ReportIncident.test.tsx @@ -1,10 +1,8 @@ /* eslint-disable no-console */ - -import { Button } from '@hospitalrun/components' -import { mount, ReactWrapper } from 'enzyme' +import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import { createMemoryHistory } from 'history' import React from 'react' -import { act } from 'react-dom/test-utils' import { Provider } from 'react-redux' import { Route, Router } from 'react-router-dom' import createMockStore from 'redux-mock-store' @@ -15,8 +13,6 @@ import * as validationUtil from '../../../incidents/util/validate-incident' import * as breadcrumbUtil from '../../../page-header/breadcrumbs/useAddBreadcrumbs' import * as ButtonBarProvider from '../../../page-header/button-toolbar/ButtonBarProvider' import * as titleUtil from '../../../page-header/title/TitleContext' -import IncidentRepository from '../../../shared/db/IncidentRepository' -import Incident from '../../../shared/model/Incident' import Permissions from '../../../shared/model/Permissions' import { RootState } from '../../../shared/store' @@ -31,7 +27,7 @@ describe('Report Incident', () => { }) let setButtonToolBarSpy: any - const setup = async (permissions: Permissions[]) => { + const setup = (permissions: Permissions[]) => { jest.spyOn(breadcrumbUtil, 'default') setButtonToolBarSpy = jest.fn() jest.spyOn(titleUtil, 'useUpdateTitle').mockImplementation(() => jest.fn()) @@ -48,213 +44,142 @@ describe('Report Incident', () => { }, } as any) - let wrapper: any - await act(async () => { - wrapper = await mount( - - - - - - - - - - - , - ) - }) - wrapper.find(ReportIncident).props().updateTitle = jest.fn() - wrapper.update() - return wrapper as ReactWrapper + return render( + + + + + + + + + + + , + ) } + test('type into department field', async () => { + setup([Permissions.ViewIncident, Permissions.ResolveIncident]) + const depInput = await screen.findByPlaceholderText(/incidents\.reports\.department/i) - describe('title', () => { - it('should have called the useUpdateTitle hook', async () => { - await setup([Permissions.ReportIncident]) - expect(titleUtil.useUpdateTitle).toHaveBeenCalledTimes(1) - }) - }) - - describe('layout', () => { - it('should set the breadcrumbs properly', async () => { - await setup([Permissions.ReportIncident]) - - expect(breadcrumbUtil.default).toHaveBeenCalledWith([ - { i18nKey: 'incidents.reports.new', location: '/incidents/new' }, - ]) - }) - - it('should have a date input', async () => { - const wrapper = await setup([Permissions.ReportIncident]) - - const dateInput = wrapper.findWhere((w) => w.prop('name') === 'dateOfIncident') - - expect(dateInput).toHaveLength(1) - expect(dateInput.prop('label')).toEqual('incidents.reports.dateOfIncident') - expect(dateInput.prop('isEditable')).toBeTruthy() - expect(dateInput.prop('isRequired')).toBeTruthy() - }) - - it('should have a department input', async () => { - const wrapper = await setup([Permissions.ReportIncident]) - - const departmentInput = wrapper.findWhere((w) => w.prop('name') === 'department') + expect(depInput).toBeEnabled() + expect(depInput).toBeInTheDocument() - expect(departmentInput).toHaveLength(1) - expect(departmentInput.prop('label')).toEqual('incidents.reports.department') - expect(departmentInput.prop('isEditable')).toBeTruthy() - expect(departmentInput.prop('isRequired')).toBeTruthy() - }) + userEvent.type(depInput, 'Engineering Bay') + expect(depInput).toHaveDisplayValue('Engineering Bay') + }) - it('should have a category input', async () => { - const wrapper = await setup([Permissions.ReportIncident]) + test('type into category field', async () => { + setup([Permissions.ViewIncident, Permissions.ResolveIncident]) + const catInput = await screen.findByPlaceholderText(/incidents\.reports\.category\b/i) - const categoryInput = wrapper.findWhere((w) => w.prop('name') === 'category') + expect(catInput).toBeEnabled() + expect(catInput).toBeInTheDocument() - expect(categoryInput).toHaveLength(1) - expect(categoryInput.prop('label')).toEqual('incidents.reports.category') - expect(categoryInput.prop('isEditable')).toBeTruthy() - expect(categoryInput.prop('isRequired')).toBeTruthy() - }) + userEvent.type(catInput, 'Warp Engine') + expect(catInput).toHaveDisplayValue('Warp Engine') + }) - it('should have a category item input', async () => { - const wrapper = await setup([Permissions.ReportIncident]) + test('type into category item field', async () => { + setup([Permissions.ViewIncident, Permissions.ResolveIncident]) + const catItemInput = await screen.findByPlaceholderText(/incidents\.reports\.categoryitem/i) - const categoryInput = wrapper.findWhere((w) => w.prop('name') === 'categoryItem') + expect(catItemInput).toBeInTheDocument() + expect(catItemInput).toBeEnabled() - expect(categoryInput).toHaveLength(1) - expect(categoryInput.prop('label')).toEqual('incidents.reports.categoryItem') - expect(categoryInput.prop('isEditable')).toBeTruthy() - expect(categoryInput.prop('isRequired')).toBeTruthy() - }) + userEvent.type(catItemInput, 'Warp Coil') + expect(catItemInput).toHaveDisplayValue('Warp Coil') + }) - it('should have a description input', async () => { - const wrapper = await setup([Permissions.ReportIncident]) + test('type into description field', async () => { + setup([Permissions.ViewIncident, Permissions.ResolveIncident]) + const inputArr = await screen.findAllByRole('textbox', { name: /required/i }) + const descInput = inputArr[inputArr.length - 1] - const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description') + expect(descInput).toBeInTheDocument() + expect(descInput).toBeEnabled() - expect(descriptionInput).toHaveLength(1) - expect(descriptionInput.prop('label')).toEqual('incidents.reports.description') - expect(descriptionInput.prop('isEditable')).toBeTruthy() - expect(descriptionInput.prop('isRequired')).toBeTruthy() - }) + userEvent.type(descInput, 'Geordi requested analysis') + expect(descInput).toHaveDisplayValue('Geordi requested analysis') + }) + test('action save after all the input fields are filled out', async () => { + setup([Permissions.ViewIncident, Permissions.ResolveIncident]) + const depInput = await screen.findByPlaceholderText(/incidents\.reports\.department/i) + const catInput = await screen.findByPlaceholderText(/incidents\.reports\.category\b/i) + const catItemInput = await screen.findByPlaceholderText(/incidents\.reports\.categoryitem/i) + const inputArr = await screen.findAllByRole('textbox', { name: /required/i }) + const descInput = inputArr[inputArr.length - 1] + + userEvent.type(depInput, 'Engineering Bay') + userEvent.type(catInput, 'Warp Engine') + userEvent.type(catItemInput, 'Warp Coil') + userEvent.type(descInput, 'Geordi requested analysis') + + userEvent.click( + screen.getByRole('button', { + name: /incidents\.reports\.new/i, + }), + ) }) - describe('on save', () => { - it('should report the incident', async () => { - const wrapper = await setup([Permissions.ReportIncident]) - const expectedIncident = { - date: new Date().toISOString(), - department: 'some department', - category: 'some category', - categoryItem: 'some category item', - description: 'some description', - } as Incident - jest - .spyOn(IncidentRepository, 'save') - .mockResolvedValue({ id: 'someId', ...expectedIncident }) - - const dateInput = wrapper.findWhere((w) => w.prop('name') === 'dateOfIncident') - act(() => { - const onChange = dateInput.prop('onChange') - onChange(new Date(expectedIncident.date)) - }) - - const departmentInput = wrapper.findWhere((w) => w.prop('name') === 'department') - act(() => { - const onChange = departmentInput.prop('onChange') - onChange({ currentTarget: { value: expectedIncident.department } }) - }) - - const categoryInput = wrapper.findWhere((w) => w.prop('name') === 'category') - act(() => { - const onChange = categoryInput.prop('onChange') - onChange({ currentTarget: { value: expectedIncident.category } }) - }) - - const categoryItemInput = wrapper.findWhere((w) => w.prop('name') === 'categoryItem') - act(() => { - const onChange = categoryItemInput.prop('onChange') - onChange({ currentTarget: { value: expectedIncident.categoryItem } }) - }) - - const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description') - act(() => { - const onChange = descriptionInput.prop('onChange') - onChange({ currentTarget: { value: expectedIncident.description } }) - }) - wrapper.update() - - const saveButton = wrapper.find(Button).at(0) - await act(async () => { - const onClick = saveButton.prop('onClick') as any - onClick() - }) - - expect(IncidentRepository.save).toHaveBeenCalledTimes(1) - expect(IncidentRepository.save).toHaveBeenCalledWith( - expect.objectContaining(expectedIncident), - ) - expect(history.location.pathname).toEqual(`/incidents/someId`) - }) - - it('should display errors if validation fails', async () => { - const error = { - name: 'incident error', - message: 'something went wrong', - date: 'some date error', - department: 'some department error', - category: 'some category error', - categoryItem: 'some category item error', - description: 'some description error', - } - jest.spyOn(validationUtil, 'default').mockReturnValue(error) - - const wrapper = await setup([Permissions.ReportIncident]) - - const saveButton = wrapper.find(Button).at(0) - await act(async () => { - const onClick = saveButton.prop('onClick') as any - await onClick() - }) - wrapper.update() - - const dateInput = wrapper.findWhere((w) => w.prop('name') === 'dateOfIncident') - const departmentInput = wrapper.findWhere((w) => w.prop('name') === 'department') - const categoryInput = wrapper.findWhere((w) => w.prop('name') === 'category') - const categoryItemInput = wrapper.findWhere((w) => w.prop('name') === 'categoryItem') - const descriptionInput = wrapper.findWhere((w) => w.prop('name') === 'description') - - expect(dateInput.prop('isInvalid')).toBeTruthy() - expect(dateInput.prop('feedback')).toEqual(error.date) - - expect(departmentInput.prop('isInvalid')).toBeTruthy() - expect(departmentInput.prop('feedback')).toEqual(error.department) - - expect(categoryInput.prop('isInvalid')).toBeTruthy() - expect(categoryInput.prop('feedback')).toEqual(error.category) - - expect(categoryItemInput.prop('isInvalid')).toBeTruthy() - expect(categoryItemInput.prop('feedback')).toEqual(error.categoryItem) - - expect(descriptionInput.prop('isInvalid')).toBeTruthy() - expect(descriptionInput.prop('feedback')).toEqual(error.description) - }) + it('should display errors if validation fails', async () => { + const error = { + name: 'incident error', + message: 'something went wrong', + date: 'some date error', + department: 'some department error', + category: 'some category error', + categoryItem: 'some category item error', + description: 'some description error', + } + jest.spyOn(validationUtil, 'default').mockReturnValue(error) + const { container } = setup([Permissions.ReportIncident]) + + userEvent.click( + screen.getByRole('button', { + name: /incidents\.reports\.new/i, + }), + ) + + const depInput = await screen.findByPlaceholderText(/incidents\.reports\.department/i) + const catInput = await screen.findByPlaceholderText(/incidents\.reports\.category\b/i) + const catItemInput = await screen.findByPlaceholderText(/incidents\.reports\.categoryitem/i) + const inputArr = await screen.findAllByRole('textbox') + const descInput = inputArr[inputArr.length - 1] + const dateInput = inputArr[0] + + const invalidInputs = container.querySelectorAll('.is-invalid') + expect(invalidInputs).toHaveLength(5) + + // ! This will work under aria compliant conditions -- Aria refactor in components? + // expect(dateInput).toBeInvalid() + expect(dateInput).toHaveClass('is-invalid') + // // expect(depInput).toBeInvalid() + expect(depInput).toHaveClass('is-invalid') + + // // expect(catInput).toBeInvalid() + expect(catInput).toHaveClass('is-invalid') + + // // expect(catItemInput).toBeInvalid() + expect(catItemInput).toHaveClass('is-invalid') + + // // expect(descInput).toBeInvalid() + expect(descInput).toHaveClass('is-invalid') }) describe('on cancel', () => { it('should navigate to /incidents', async () => { - const wrapper = await setup([Permissions.ReportIncident]) + setup([Permissions.ReportIncident]) - const cancelButton = wrapper.find(Button).at(1) + expect(history.location.pathname).toBe('/incidents/new') - act(() => { - const onClick = cancelButton.prop('onClick') as any - onClick() - }) + userEvent.click( + screen.getByRole('button', { + name: /actions\.cancel/i, + }), + ) - expect(history.location.pathname).toEqual('/incidents') + expect(history.location.pathname).toBe('/incidents') }) }) }) diff --git a/src/__tests__/incidents/view/ViewIncidentDetails.test.tsx b/src/__tests__/incidents/view/ViewIncidentDetails.test.tsx index 2e7db659b6..99ffc25ed8 100644 --- a/src/__tests__/incidents/view/ViewIncidentDetails.test.tsx +++ b/src/__tests__/incidents/view/ViewIncidentDetails.test.tsx @@ -53,9 +53,13 @@ describe('View Incident Details', () => { } test('type into department field', async () => { setup(expectedIncident, [Permissions.ViewIncident, Permissions.ResolveIncident]) + expect( await screen.findByRole('textbox', { name: /incidents\.reports\.department/i }), ).toBeInTheDocument() + expect( + await screen.findByRole('textbox', { name: /incidents\.reports\.department/i }), + ).not.toBeEnabled() }) test('type into category field', async () => { @@ -65,6 +69,11 @@ describe('View Incident Details', () => { name: /incidents\.reports\.category\b/i, }), ).toBeInTheDocument() + expect( + screen.getByRole('textbox', { + name: /incidents\.reports\.category\b/i, + }), + ).not.toBeEnabled() }) test('type into category item field', () => { @@ -74,6 +83,11 @@ describe('View Incident Details', () => { name: /incidents\.reports\.categoryitem/i, }), ).toBeInTheDocument() + expect( + screen.getByRole('textbox', { + name: /incidents\.reports\.categoryitem/i, + }), + ).not.toBeEnabled() }) test('type into description field', () => { @@ -83,6 +97,11 @@ describe('View Incident Details', () => { name: /incidents\.reports\.description/i, }), ).toBeInTheDocument() + expect( + screen.getByRole('textbox', { + name: /incidents\.reports\.description/i, + }), + ).not.toBeEnabled() }) describe('on resolve', () => {