diff --git a/frontend/src/__tests__/App.js b/frontend/src/__tests__/App.js index 8dfb71c95b..944d4444e1 100644 --- a/frontend/src/__tests__/App.js +++ b/frontend/src/__tests__/App.js @@ -15,11 +15,12 @@ describe('App', () => { const logoutUrl = join('api', 'logout'); describe('when authenticated', () => { - beforeEach(() => { + beforeEach(async () => { const user = { name: 'name' }; fetchMock.get(userUrl, { ...user }); fetchMock.get(logoutUrl, 200); render(); + await screen.findByText('Activity Reports'); }); it('displays the logout button', async () => { @@ -35,23 +36,17 @@ describe('App', () => { }); describe('when unauthenticated', () => { - beforeEach(() => { + it('displays the login button', async () => { fetchMock.get(userUrl, 401); render(); - }); - - it('displays the login button', async () => { expect(await screen.findByText(loginText)).toBeVisible(); }); }); describe('when user is locked', () => { - beforeEach(() => { + it('displays the "request permissions" page', async () => { fetchMock.get(userUrl, 403); render(); - }); - - it('displays the "request permissions" page', async () => { expect(await screen.findByText('You need permission to access the TTA Smart Hub.')).toBeVisible(); expect(await screen.findByText('Request Permission')).toBeVisible(); }); diff --git a/frontend/src/components/ContextMenu.js b/frontend/src/components/ContextMenu.js index d80ee705f5..ce5ed92758 100644 --- a/frontend/src/components/ContextMenu.js +++ b/frontend/src/components/ContextMenu.js @@ -32,6 +32,7 @@ function ContextMenu({ document.addEventListener('keydown', onEscape, false); return () => { document.removeEventListener('keydown', onEscape, false); + updateShown(false); }; }, [onEscape]); diff --git a/frontend/src/components/Navigator/__tests__/index.js b/frontend/src/components/Navigator/__tests__/index.js index 48604e8ca7..d1f68f37cd 100644 --- a/frontend/src/components/Navigator/__tests__/index.js +++ b/frontend/src/components/Navigator/__tests__/index.js @@ -84,6 +84,10 @@ describe('Navigator', () => { updatePage={updatePage} onSave={onSave} updateErrorMessage={() => {}} + onResetToDraft={() => {}} + updateLastSaveTime={() => {}} + showValidationErrors={false} + updateShowValidationErrors={() => {}} />, ); }; diff --git a/frontend/src/components/__tests__/DatePicker.js b/frontend/src/components/__tests__/DatePicker.js index 72a97993e0..45bde3263e 100644 --- a/frontend/src/components/__tests__/DatePicker.js +++ b/frontend/src/components/__tests__/DatePicker.js @@ -37,6 +37,7 @@ describe('DatePicker', () => { label="label" name="picker" disabled={disabled} + ariaName="datepicker" /> ); diff --git a/frontend/src/components/__tests__/MutliSelect.js b/frontend/src/components/__tests__/MutliSelect.js index 73abf56c46..1de7c304e2 100644 --- a/frontend/src/components/__tests__/MutliSelect.js +++ b/frontend/src/components/__tests__/MutliSelect.js @@ -16,9 +16,9 @@ const options = [ describe('MultiSelect', () => { // eslint-disable-next-line react/prop-types - const TestMultiSelect = ({ onSubmit, defaultValues }) => { + const TestMultiSelect = ({ onSubmit }) => { const { control, handleSubmit } = useForm({ - defaultValues, + defaultValues: { name: [] }, mode: 'all', }); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Approver/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Approver/__tests__/index.js index f056ffd7ca..e93fa83c4b 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Approver/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Approver/__tests__/index.js @@ -1,6 +1,8 @@ /* eslint-disable react/jsx-props-no-spreading */ import '@testing-library/jest-dom'; -import { render, screen } from '@testing-library/react'; +import { + render, screen, waitFor, +} from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React from 'react'; import { Router } from 'react-router'; @@ -24,7 +26,11 @@ const RenderApprover = ({ onFormReview={onFormReview} reviewed={reviewed} formData={formData} - /> + > +
+ test +
+ ); }; @@ -63,12 +69,12 @@ describe('Approver review page', () => { it('allows the approver to submit a review and redirects them after', async () => { const mockSubmit = jest.fn(); - const history = renderReview(REPORT_STATUSES.SUBMITTED, mockSubmit, true, true); + const history = renderReview(REPORT_STATUSES.SUBMITTED, mockSubmit, true); const dropdown = await screen.findByTestId('dropdown'); userEvent.selectOptions(dropdown, 'approved'); const button = await screen.findByRole('button'); userEvent.click(button); - expect(history.location.pathname).toBe('/activity-reports'); + await waitFor(() => expect(history.location.pathname).toBe('/activity-reports')); }); it('handles empty notes', async () => { diff --git a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js index 0d1767f810..115174e59b 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/Submitter/__tests__/index.js @@ -58,6 +58,8 @@ const renderReview = ( approvingManager: { name: 'name' }, approvingManagerId: 1, status, + displayId: '1', + id: 1, }; const history = createMemoryHistory(); @@ -148,7 +150,7 @@ describe('Submitter review page', () => { it('the reset to draft button works', async () => { const onReset = jest.fn(); - renderReview(REPORT_STATUSES.SUBMITTED, false, true, () => {}, onReset); + renderReview(REPORT_STATUSES.SUBMITTED, () => {}, true, () => {}, onReset); const button = await screen.findByRole('button', { name: 'Reset to Draft' }); userEvent.click(button); await waitFor(() => expect(onReset).toHaveBeenCalled()); diff --git a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js index 144907a718..cd5b1a8328 100644 --- a/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js +++ b/frontend/src/pages/ActivityReport/Pages/Review/__tests__/index.js @@ -79,7 +79,9 @@ const renderReview = ( {}, onUpdateObjectives = () => {}, objectives = [], - createObjective = () => ({ title: '', ttaProvided: '' }), + createObjective = () => { + id += 1; + return { key: id.toString(DECIMAL_BASE), title: '', ttaProvided: '' }; + }, }) => { const hookForm = useForm(); return ( @@ -56,24 +62,37 @@ describe('Goal', () => { describe('with objectives', () => { it('can be removed', async () => { const onUpdate = jest.fn(); - const objectives = [{ title: 'first', ttaProvided: '', status: 'Not Started' }, { title: '', ttaProvided: '', status: 'Not Started' }]; + const objectives = [ + { + id: 'a', title: 'first', ttaProvided: '', status: 'Not Started', + }, + { + id: 'b', title: '', ttaProvided: '', status: 'Not Started', + }, + ]; render(); const remove = await screen.findByRole('button', { name: 'Cancel update of objective 2 on goal 1' }); userEvent.click(remove); - expect(onUpdate).toHaveBeenCalledWith([{ title: 'first', ttaProvided: '', status: 'Not Started' }]); + expect(onUpdate).toHaveBeenCalledWith([{ + id: 'a', title: 'first', ttaProvided: '', status: 'Not Started', + }]); }); it('can be updated', async () => { const onUpdate = jest.fn(); - const objectives = [{ title: '', ttaProvided: 'test', status: 'Not Started' }]; + const objectives = [{ + id: 'a', title: '', ttaProvided: 'test', status: 'Not Started', + }]; render(); const title = await screen.findByRole('textbox', { name: 'title for objective 1 on goal 1' }); userEvent.type(title, 'title'); const button = await screen.findByRole('button', { name: 'Save objective 1 on goal 1' }); userEvent.click(button); - expect(onUpdate).toHaveBeenCalledWith([{ title: 'title', ttaProvided: 'test', status: 'Not Started' }]); + expect(onUpdate).toHaveBeenCalledWith([{ + id: 'a', title: 'title', ttaProvided: 'test', status: 'Not Started', + }]); }); }); }); diff --git a/frontend/src/pages/ActivityReport/Pages/components/__tests__/Objective.js b/frontend/src/pages/ActivityReport/Pages/components/__tests__/Objective.js index f842a5ca4b..404d006386 100644 --- a/frontend/src/pages/ActivityReport/Pages/components/__tests__/Objective.js +++ b/frontend/src/pages/ActivityReport/Pages/components/__tests__/Objective.js @@ -9,7 +9,12 @@ const RenderObjective = ({ // eslint-disable-next-line react/prop-types objective, onRemove = () => {}, onUpdate = () => {}, }) => { - const hookForm = useForm(); + const hookForm = useForm({ + defaultValues: { goals: [] }, + }); + + hookForm.register('goals'); + return ( // eslint-disable-next-line react/jsx-props-no-spreading @@ -130,6 +135,7 @@ describe('Objective', () => { userEvent.click(edit); const save = await screen.findByText('Save Objective'); expect(save).toBeVisible(); + await screen.findByText('Cancel'); }); }); }); diff --git a/frontend/src/pages/Admin/__tests__/index.js b/frontend/src/pages/Admin/__tests__/index.js index fe1ffb9b16..358c22b3b0 100644 --- a/frontend/src/pages/Admin/__tests__/index.js +++ b/frontend/src/pages/Admin/__tests__/index.js @@ -75,11 +75,12 @@ describe('Admin Page', () => { }); describe('with no user selected', () => { - beforeEach(() => { + const renderAdmin = () => { render(); - }); + }; it('user list is filterable by name', async () => { + renderAdmin(); const filter = await screen.findByLabelText('Filter Users'); userEvent.type(filter, 'Harry'); const sideNav = screen.getByTestId('sidenav'); @@ -89,6 +90,7 @@ describe('Admin Page', () => { }); it('User list is filterable by email', async () => { + renderAdmin(); const filter = await screen.findByLabelText('Filter Users'); userEvent.type(filter, '@hogwarts.com'); const sideNav = screen.getByTestId('sidenav'); @@ -97,6 +99,7 @@ describe('Admin Page', () => { }); it('user filtering is case-insentive', async () => { + renderAdmin(); const filter = await screen.findByLabelText('Filter Users'); userEvent.type(filter, 'harry'); const sideNav = screen.getByTestId('sidenav'); @@ -106,6 +109,7 @@ describe('Admin Page', () => { }); it('user list is filterable by users to lock', async () => { + renderAdmin(); const radio = await screen.findByRole('radio', { name: 'Show users to lock' }); userEvent.click(radio); const sideNav = screen.getByTestId('sidenav'); @@ -115,6 +119,7 @@ describe('Admin Page', () => { }); it('user list is filterable by users to disable', async () => { + renderAdmin(); const radio = await screen.findByRole('radio', { name: 'Show users to disable' }); userEvent.click(radio); const sideNav = screen.getByTestId('sidenav'); @@ -124,6 +129,7 @@ describe('Admin Page', () => { }); it('allows a user to be selected', async () => { + renderAdmin(); const button = await screen.findByText('Harry Potter'); userEvent.click(button); expect(history.location.pathname).toBe('/admin/3'); diff --git a/frontend/src/pages/Landing/__tests__/index.js b/frontend/src/pages/Landing/__tests__/index.js index 2a226be864..c62ceb870a 100644 --- a/frontend/src/pages/Landing/__tests__/index.js +++ b/frontend/src/pages/Landing/__tests__/index.js @@ -21,7 +21,7 @@ const renderLanding = (user) => { }; describe('Landing Page', () => { - beforeEach(() => { + beforeEach(async () => { fetchMock.get( '/api/activity-reports?sortBy=updatedAt&sortDir=desc&offset=0&limit=10', { count: 2, rows: activityReports }, @@ -39,6 +39,7 @@ describe('Landing Page', () => { }; renderLanding(user); + await screen.findByText('Activity Reports'); }); afterEach(() => fetchMock.restore()); @@ -169,7 +170,7 @@ describe('Landing Page', () => { describe('Landing Page sorting', () => { afterEach(() => fetchMock.restore()); - beforeEach(() => { + beforeEach(async () => { fetchMock.get('/api/activity-reports/alerts?sortBy=startDate&sortDir=desc&offset=0&limit=10', { alertsCount: 0, alerts: [] }); fetchMock.get( @@ -187,6 +188,7 @@ describe('Landing Page sorting', () => { }; renderLanding(user); + await screen.findByText('Activity Reports'); }); it('clicking status column header will sort by status', async () => { @@ -379,7 +381,7 @@ describe('Landing Page sorting', () => { describe('My alerts sorting', () => { afterEach(() => fetchMock.restore()); - beforeEach(() => { + beforeEach(async () => { fetchMock.get('/api/activity-reports/alerts?sortBy=startDate&sortDir=desc&offset=0&limit=10', { alertsCount: 2, alerts: activityReports }); fetchMock.get('/api/activity-reports?sortBy=updatedAt&sortDir=desc&offset=0&limit=10', @@ -395,6 +397,7 @@ describe('My alerts sorting', () => { }; renderLanding(user); + await screen.findByText('Activity Reports'); }); it('is enabled for Status', async () => {