diff --git a/frontend/src/app/ReportingApp.test.tsx b/frontend/src/app/ReportingApp.test.tsx index 798e48fcd7..cd22b8e23b 100644 --- a/frontend/src/app/ReportingApp.test.tsx +++ b/frontend/src/app/ReportingApp.test.tsx @@ -3,6 +3,7 @@ import { Provider } from "react-redux"; import createMockStore, { MockStoreEnhanced } from "redux-mock-store"; import { MockedProvider, MockedResponse } from "@apollo/client/testing"; import { + act, render, screen, waitFor, @@ -252,8 +253,11 @@ describe("App", () => { await waitForElementToBeRemoved(() => screen.queryByText("Loading account information...") ); - await userEvent.click( - screen.getAllByText("Testing Site", { exact: false })[0] + await act( + async () => + await userEvent.click( + screen.getAllByText("Testing Site", { exact: false })[0] + ) ); expect( await screen.findByText("COVID-19 testing data") @@ -280,7 +284,10 @@ describe("App", () => { exact: false, }); expect(trainingWelcome).toBeInTheDocument(); - await userEvent.click(screen.getByText("Got it", { exact: false })); + await act( + async () => + await userEvent.click(screen.getByText("Got it", { exact: false })) + ); expect(trainingWelcome).not.toBeInTheDocument(); }); diff --git a/frontend/src/app/Settings/Facility/Components/ManageDevices.test.tsx b/frontend/src/app/Settings/Facility/Components/ManageDevices.test.tsx index 581f87503c..cd7477b433 100644 --- a/frontend/src/app/Settings/Facility/Components/ManageDevices.test.tsx +++ b/frontend/src/app/Settings/Facility/Components/ManageDevices.test.tsx @@ -1,5 +1,6 @@ import { useState } from "react"; import { + act, fireEvent, render, screen, @@ -105,8 +106,11 @@ describe("ManageDevices", () => { const deviceInput = screen.getByTestId("multi-select-toggle"); const deviceList = screen.getByTestId("multi-select-option-list"); - await userEvent.click(deviceInput); - await userEvent.click(within(deviceList).getByText("Device C")); + await act(async () => await userEvent.click(deviceInput)); + await act( + async () => + await userEvent.click(within(deviceList).getByText("Device C")) + ); expect(await screen.findByTestId("pill-container")); expect( diff --git a/frontend/src/app/Settings/Facility/FacilityFormContainer.test.tsx b/frontend/src/app/Settings/Facility/FacilityFormContainer.test.tsx index 5f093adf5d..6571fe8261 100644 --- a/frontend/src/app/Settings/Facility/FacilityFormContainer.test.tsx +++ b/frontend/src/app/Settings/Facility/FacilityFormContainer.test.tsx @@ -1,4 +1,5 @@ import { + act, render, screen, waitForElementToBeRemoved, @@ -226,7 +227,10 @@ describe("FacilityFormContainer", () => { it("redirects on successful facility update", async () => { await waitForElementToBeRemoved(() => screen.queryByText("Loading...")); - await userEvent.click(screen.getByRole("button", { name: /submit/i })); + await act( + async () => + await userEvent.click(screen.getByRole("button", { name: /submit/i })) + ); expect(await screen.findByText("Redirected")).toBeInTheDocument(); }); @@ -235,7 +239,10 @@ describe("FacilityFormContainer", () => { trackEvent: trackEventMock, })); await waitForElementToBeRemoved(() => screen.queryByText("Loading...")); - await userEvent.click(screen.getByRole("button", { name: /submit/i })); + await act( + async () => + await userEvent.click(screen.getByRole("button", { name: /submit/i })) + ); expect(trackEventMock).toBeCalledWith({ name: "Save Settings" }); }); }); @@ -247,7 +254,10 @@ describe("FacilityFormContainer", () => { it("creates a new facility", async () => { expect(await screen.findByRole("button", { name: /submit/i })); - await userEvent.click(screen.getByRole("button", { name: /submit/i })); + await act( + async () => + await userEvent.click(screen.getByRole("button", { name: /submit/i })) + ); expect(await screen.findByText("Redirected")).toBeInTheDocument(); }); }); diff --git a/frontend/src/app/Settings/ManageSelfRegistrationLinks.test.tsx b/frontend/src/app/Settings/ManageSelfRegistrationLinks.test.tsx index fbd586ff6d..a93baf7410 100644 --- a/frontend/src/app/Settings/ManageSelfRegistrationLinks.test.tsx +++ b/frontend/src/app/Settings/ManageSelfRegistrationLinks.test.tsx @@ -1,5 +1,5 @@ import { MockedProvider } from "@apollo/client/testing"; -import { render, screen, waitFor } from "@testing-library/react"; +import { act, render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { @@ -64,7 +64,7 @@ describe("ManageSelfRegistrationLinks", () => { it("copies the org link", async () => { const orgUrl = `${process.env.REACT_APP_BASE_URL}/register/${expectedOrgSlug}`; const [orgBtn] = screen.getAllByRole("button"); - await userEvent.click(orgBtn); + await act(async () => await userEvent.click(orgBtn)); await waitFor(async () => expect(orgBtn).toBeEnabled()); expect(navigator.clipboard.writeText).toBeCalledWith(orgUrl); }); @@ -72,7 +72,7 @@ describe("ManageSelfRegistrationLinks", () => { it("copies a facility link", async () => { const facilityUrl = `${process.env.REACT_APP_BASE_URL}/register/${expectedFacilitySlug}`; const btns = screen.getAllByRole("button"); - await userEvent.click(btns[2]); + await act(async () => await userEvent.click(btns[2])); await waitFor(async () => expect(btns[2]).toBeEnabled()); expect(navigator.clipboard.writeText).toBeCalledWith(facilityUrl); }); diff --git a/frontend/src/app/VersionEnforcer.test.tsx b/frontend/src/app/VersionEnforcer.test.tsx index 8d84154afd..e613f0a38d 100644 --- a/frontend/src/app/VersionEnforcer.test.tsx +++ b/frontend/src/app/VersionEnforcer.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { Link, MemoryRouter, Outlet, Route, Routes } from "react-router-dom"; @@ -61,8 +61,11 @@ describe("VersionEnforcer", () => { expect(await screen.findByText("This is the first page", { exact: false })); // WHEN - await userEvent.click( - screen.getByText("Go to a new page", { exact: false }) + await act( + async () => + await userEvent.click( + screen.getByText("Go to a new page", { exact: false }) + ) ); // THEN diff --git a/frontend/src/app/accountCreation/MfaPhone/MfaPhone.test.tsx b/frontend/src/app/accountCreation/MfaPhone/MfaPhone.test.tsx index e979c53d87..6c2696b6c8 100644 --- a/frontend/src/app/accountCreation/MfaPhone/MfaPhone.test.tsx +++ b/frontend/src/app/accountCreation/MfaPhone/MfaPhone.test.tsx @@ -1,4 +1,5 @@ import { + act, render, screen, waitForElementToBeRemoved, @@ -39,11 +40,17 @@ describe("Phone call MFA", () => { }); it("can enter a valid phone number", async () => { - await userEvent.type( - screen.getByLabelText("Phone number", { exact: false }), - "(910) 867-5309" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Phone number", { exact: false }), + "(910) 867-5309" + ) + ); + await act( + async () => + await userEvent.click(screen.getByText("Send code", { exact: false })) ); - await userEvent.click(screen.getByText("Send code", { exact: false })); await waitForElementToBeRemoved(() => screen.queryByText("Validating phone number …") ); @@ -53,18 +60,27 @@ describe("Phone call MFA", () => { }); it("requires a phone number", async () => { - await userEvent.click(screen.getByText("Send code", { exact: false })); + await act( + async () => + await userEvent.click(screen.getByText("Send code", { exact: false })) + ); expect( await screen.findByText("Enter your phone number", { exact: false }) ); }); it("requires a valid phone number", async () => { - await userEvent.type( - screen.getByLabelText("Phone number", { exact: false }), - "(555) 555-5555" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Phone number", { exact: false }), + "(555) 555-5555" + ) + ); + await act( + async () => + await userEvent.click(screen.getByText("Send code", { exact: false })) ); - await userEvent.click(screen.getByText("Send code", { exact: false })); expect( await screen.findByText("Enter a valid phone number", { exact: false }) ); diff --git a/frontend/src/app/accountCreation/MfaSelect/MfaSelect.test.tsx b/frontend/src/app/accountCreation/MfaSelect/MfaSelect.test.tsx index db3cbca3b9..4edfd9fc69 100644 --- a/frontend/src/app/accountCreation/MfaSelect/MfaSelect.test.tsx +++ b/frontend/src/app/accountCreation/MfaSelect/MfaSelect.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, waitFor } from "@testing-library/react"; +import { act, render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { MemoryRouter, Route, Routes } from "react-router-dom"; @@ -34,7 +34,7 @@ jest.mock("../AccountCreationApiService", () => ({ })); describe("MfaSelect", () => { - beforeEach(() => { + beforeEach(async () => { render(); }); @@ -42,12 +42,12 @@ describe("MfaSelect", () => { const smsRadio = screen.getByLabelText("Text message (SMS)", { exact: false, }); - await userEvent.click(smsRadio); + await act(async () => await userEvent.click(smsRadio)); expect(smsRadio).toBeChecked(); }); it("requires an mfa option", async () => { - await userEvent.click(screen.getByText("Continue")); + await act(async () => await userEvent.click(screen.getByText("Continue"))); expect( screen.getByText("Select an authentication option") ).toBeInTheDocument(); @@ -95,9 +95,9 @@ describe("MfaSelect routing", () => { const smsRadio = screen.getByLabelText("Text message (SMS)", { exact: false, }); - await userEvent.click(smsRadio); + await act(async () => await userEvent.click(smsRadio)); expect(smsRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); await waitFor(() => { expect( screen.getByText("Get your security code via text message (SMS).") @@ -109,9 +109,9 @@ describe("MfaSelect routing", () => { const googleRadio = screen.getByLabelText("Google Authenticator", { exact: false, }); - await userEvent.click(googleRadio); + await act(async () => await userEvent.click(googleRadio)); expect(googleRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); expect( await screen.findByText( "Get your security code via the Google Authenticator application." @@ -123,9 +123,9 @@ describe("MfaSelect routing", () => { const oktaRadio = screen.getByLabelText("Okta Verify", { exact: false, }); - await userEvent.click(oktaRadio); + await act(async () => await userEvent.click(oktaRadio)); expect(oktaRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); expect( await screen.findByText( "Get your security code via the Okta Verify application." @@ -141,9 +141,9 @@ describe("MfaSelect routing", () => { } ); - await userEvent.click(securityKeyRadio); + await act(async () => await userEvent.click(securityKeyRadio)); expect(securityKeyRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); await waitFor(() => { expect( @@ -158,9 +158,9 @@ describe("MfaSelect routing", () => { const emailRadio = screen.getByLabelText("Email", { exact: false, }); - await userEvent.click(emailRadio); + await act(async () => await userEvent.click(emailRadio)); expect(emailRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); await waitFor(() => { expect( screen.getByText( @@ -175,9 +175,9 @@ describe("MfaSelect routing", () => { const phoneRadio = screen.getByLabelText("Phone call", { exact: false, }); - await userEvent.click(phoneRadio); + await act(async () => await userEvent.click(phoneRadio)); expect(phoneRadio).toBeChecked(); - await userEvent.click(continueButton); + await act(async () => await userEvent.click(continueButton)); await waitFor(() => { expect( screen.getByText("Get your security code via a phone call") diff --git a/frontend/src/app/accountCreation/MfaSms/MfaSms.test.tsx b/frontend/src/app/accountCreation/MfaSms/MfaSms.test.tsx index f6a17e5745..36112bebcd 100644 --- a/frontend/src/app/accountCreation/MfaSms/MfaSms.test.tsx +++ b/frontend/src/app/accountCreation/MfaSms/MfaSms.test.tsx @@ -1,4 +1,5 @@ import { + act, render, screen, waitForElementToBeRemoved, @@ -39,11 +40,14 @@ describe("SMS MFA", () => { }); it("can enter a valid phone number", async () => { - await userEvent.type( - screen.getByLabelText("Phone number", { exact: false }), - "(910) 867-5309" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Phone number", { exact: false }), + "(910) 867-5309" + ) ); - await userEvent.click(screen.getByText("Send code")); + await act(async () => await userEvent.click(screen.getByText("Send code"))); await waitForElementToBeRemoved(() => screen.queryByText("Validating phone number …") ); @@ -54,16 +58,19 @@ describe("SMS MFA", () => { }); it("requires a phone number", async () => { - await userEvent.click(screen.getByText("Send code")); + await act(async () => await userEvent.click(screen.getByText("Send code"))); expect(screen.getByText("Enter your phone number")).toBeInTheDocument(); }); it("requires a valid phone number", async () => { - await userEvent.type( - screen.getByLabelText("Phone number", { exact: false }), - "(555) 555-5555" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Phone number", { exact: false }), + "(555) 555-5555" + ) ); - await userEvent.click(screen.getByText("Send code")); + await act(async () => await userEvent.click(screen.getByText("Send code"))); expect(screen.getByText("Enter a valid phone number")).toBeInTheDocument(); }); }); diff --git a/frontend/src/app/analytics/Analytics.test.tsx b/frontend/src/app/analytics/Analytics.test.tsx index cfa2664221..959f2d9773 100644 --- a/frontend/src/app/analytics/Analytics.test.tsx +++ b/frontend/src/app/analytics/Analytics.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen } from "@testing-library/react"; +import { act, fireEvent, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { MockedProvider } from "@apollo/client/testing"; import createMockStore from "redux-mock-store"; @@ -234,9 +234,13 @@ describe("Analytics", () => { }); it("allows filtering by Lincoln Middle School", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Testing facility"), [ - "Lincoln Middle School", - ]); + await act( + async () => + await userEvent.selectOptions( + screen.getByLabelText("Testing facility"), + ["Lincoln Middle School"] + ) + ); expect(await screen.findByText("72341")).toBeInTheDocument(); expect(await screen.findByText("1000")).toBeInTheDocument(); expect(await screen.findByText("71341")).toBeInTheDocument(); @@ -244,9 +248,13 @@ describe("Analytics", () => { }); it("allows filtering by Rosa Parks High School", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Testing facility"), [ - "Rosa Parks High School", - ]); + await act( + async () => + await userEvent.selectOptions( + screen.getByLabelText("Testing facility"), + ["Rosa Parks High School"] + ) + ); expect(await screen.findByText("52479")).toBeInTheDocument(); expect(await screen.findByText("1270")).toBeInTheDocument(); expect(await screen.findByText("51209")).toBeInTheDocument(); @@ -254,9 +262,12 @@ describe("Analytics", () => { }); it("allows filtering by last day", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Date range"), [ - "Last day (24 hours)", - ]); + await act( + async () => + await userEvent.selectOptions(screen.getByLabelText("Date range"), [ + "Last day (24 hours)", + ]) + ); expect(await screen.findByText("120")).toBeInTheDocument(); expect(await screen.findByText("11")).toBeInTheDocument(); expect(await screen.findByText("109")).toBeInTheDocument(); @@ -264,16 +275,22 @@ describe("Analytics", () => { }); it("allows filtering by last week", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Date range"), [ - "Last week (7 days)", - ]); + await act( + async () => + await userEvent.selectOptions(screen.getByLabelText("Date range"), [ + "Last week (7 days)", + ]) + ); expect(await screen.findByText("124820")).toBeInTheDocument(); }); it("allows filtering by last month", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Date range"), [ - "Last month (30 days)", - ]); + await act( + async () => + await userEvent.selectOptions(screen.getByLabelText("Date range"), [ + "Last month (30 days)", + ]) + ); expect(await screen.findByText("623492")).toBeInTheDocument(); expect(await screen.findByText("34971")).toBeInTheDocument(); expect(await screen.findByText("588521")).toBeInTheDocument(); @@ -281,9 +298,12 @@ describe("Analytics", () => { }); it("allows filtering by a custom date range", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Date range"), [ - "Custom date range", - ]); + await act( + async () => + await userEvent.selectOptions(screen.getByLabelText("Date range"), [ + "Custom date range", + ]) + ); await screen.findByText("COVID-19 testing data"); const startDate = screen.getByTestId("startDate") as HTMLInputElement; const endDate = screen.getByTestId("endDate") as HTMLInputElement; @@ -302,20 +322,31 @@ describe("Analytics", () => { }); it("shows N/A for positivity rate at Empty School", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Testing facility"), [ - "Empty School", - ]); + await act( + async () => + await userEvent.selectOptions( + screen.getByLabelText("Testing facility"), + ["Empty School"] + ) + ); expect(await screen.findByText("N/A")).toBeInTheDocument(); }); it("shows 0% for positivity rate at Empty School over last month", async () => { await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Testing facility"), [ - "Empty School", - ]); + await act( + async () => + await userEvent.selectOptions( + screen.getByLabelText("Testing facility"), + ["Empty School"] + ) + ); await screen.findByText("COVID-19 testing data"); - await userEvent.selectOptions(screen.getByLabelText("Date range"), [ - "Last month (30 days)", - ]); + await act( + async () => + await userEvent.selectOptions(screen.getByLabelText("Date range"), [ + "Last month (30 days)", + ]) + ); expect(await screen.findByText("0.0%")).toBeInTheDocument(); }); }); diff --git a/frontend/src/app/commonComponents/ActionsMenu.test.tsx b/frontend/src/app/commonComponents/ActionsMenu.test.tsx index 7d840aeb7f..6a10ad4512 100644 --- a/frontend/src/app/commonComponents/ActionsMenu.test.tsx +++ b/frontend/src/app/commonComponents/ActionsMenu.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { ActionsMenu } from "./ActionsMenu"; @@ -24,7 +24,9 @@ describe("action menu", () => { "action_1234" ); - await userEvent.click(screen.getByText("More actions")); + await act( + async () => await userEvent.click(screen.getByText("More actions")) + ); expect(screen.getByText("Print action")).toHaveAttribute( "id", "print_1234" diff --git a/frontend/src/app/commonComponents/MultiSelect/MultiSelect.test.tsx b/frontend/src/app/commonComponents/MultiSelect/MultiSelect.test.tsx index 4ba83ed6ca..6c2907f406 100644 --- a/frontend/src/app/commonComponents/MultiSelect/MultiSelect.test.tsx +++ b/frontend/src/app/commonComponents/MultiSelect/MultiSelect.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, within } from "@testing-library/react"; +import { act, render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import MultiSelect from "./MultiSelect"; @@ -89,10 +89,19 @@ describe("Multi Select", () => { }); describe("when selecting an item", () => { beforeEach(async () => { - await userEvent.click(screen.getByTestId("multi-select-input")); + await act( + async () => + await userEvent.click(screen.getByTestId("multi-select-input")) + ); const optionList = screen.getByTestId("multi-select-option-list"); - await userEvent.click(within(optionList).getByText("Apples")); - await userEvent.click(within(optionList).getByText("Oranges")); + await act( + async () => + await userEvent.click(within(optionList).getByText("Apples")) + ); + await act( + async () => + await userEvent.click(within(optionList).getByText("Oranges")) + ); }); it("should show the pill with the selected item's label", () => { @@ -120,10 +129,16 @@ describe("Multi Select", () => { beforeEach(async () => { const pillContainer = screen.getByTestId("pill-container"); expect(pillContainer).toBeInTheDocument(); - await userEvent.click( - within(pillContainer).getAllByRole("button")[0] + await act( + async () => + await userEvent.click( + within(pillContainer).getAllByRole("button")[0] + ) + ); + await act( + async () => + await userEvent.click(screen.getByTestId("multi-select-input")) ); - await userEvent.click(screen.getByTestId("multi-select-input")); }); it("should remove the pill ", () => { diff --git a/frontend/src/app/commonComponents/SingleFileInput.test.tsx b/frontend/src/app/commonComponents/SingleFileInput.test.tsx index b0c43d391e..2e9505bbc2 100644 --- a/frontend/src/app/commonComponents/SingleFileInput.test.tsx +++ b/frontend/src/app/commonComponents/SingleFileInput.test.tsx @@ -1,4 +1,4 @@ -import { fireEvent, render, screen } from "@testing-library/react"; +import { act, fireEvent, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import SingleFileInput from "./SingleFileInput"; @@ -52,7 +52,9 @@ describe("Single File Input", () => { /> ); const fileInput = screen.getByTestId("testId"); - await userEvent.upload(fileInput, file("test content")); + await act( + async () => await userEvent.upload(fileInput, file("test content")) + ); expect( await screen.findByText( "Drag file here or choose from folder to change file" @@ -88,7 +90,9 @@ describe("Single File Input", () => { /> ); const fileInput = screen.getByTestId("testId"); - await userEvent.upload(fileInput, file("test content")); + await act( + async () => await userEvent.upload(fileInput, file("test content")) + ); expect( await screen.findByText( "Drag file here or choose from folder to change file" diff --git a/frontend/src/app/commonComponents/__test__/Header.test.tsx b/frontend/src/app/commonComponents/__test__/Header.test.tsx index d39656b707..48d3584f0a 100644 --- a/frontend/src/app/commonComponents/__test__/Header.test.tsx +++ b/frontend/src/app/commonComponents/__test__/Header.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { Provider } from "react-redux"; import { MemoryRouter } from "react-router-dom"; @@ -62,17 +62,29 @@ describe("Header.tsx", () => { it("displays the support link correctly", async () => { process.env.REACT_APP_IS_TRAINING_SITE = "false"; render(); - await userEvent.click(screen.getByTestId("desktop-user-button")); + await act( + async () => + await userEvent.click(screen.getByTestId("desktop-user-button")) + ); expect(screen.getByTestId("desktop-support-link")).toBeVisible(); - await userEvent.click(screen.getByTestId("desktop-support-link")); + await act( + async () => + await userEvent.click(screen.getByTestId("desktop-support-link")) + ); expect(trackEventMock).toHaveBeenCalledWith({ name: "Support" }); }); it("displays new feature link correctly", async () => { process.env.REACT_APP_IS_TRAINING_SITE = "false"; render(); - await userEvent.click(screen.getByTestId("desktop-user-button")); + await act( + async () => + await userEvent.click(screen.getByTestId("desktop-user-button")) + ); expect(screen.getByTestId("desktop-whats-new-link")).toBeVisible(); - await userEvent.click(screen.getByTestId("desktop-whats-new-link")); + await act( + async () => + await userEvent.click(screen.getByTestId("desktop-whats-new-link")) + ); expect(trackEventMock).toHaveBeenCalledWith({ name: "What's new" }); }); it("it does not render login links", () => { @@ -88,7 +100,10 @@ describe("Header.tsx", () => { ); const dropdown = await screen.findAllByRole("option"); - await userEvent.selectOptions(dropdown[1].closest("select")!, "2"); + await act( + async () => + await userEvent.selectOptions(dropdown[1].closest("select")!, "2") + ); expect( await screen.findByText("Facility 2 is selected") ).toBeInTheDocument(); diff --git a/frontend/src/app/patients/UploadPatients.test.tsx b/frontend/src/app/patients/UploadPatients.test.tsx index 07a90c69fc..6a55247cf7 100644 --- a/frontend/src/app/patients/UploadPatients.test.tsx +++ b/frontend/src/app/patients/UploadPatients.test.tsx @@ -1,11 +1,11 @@ -import { render, screen, waitFor } from "@testing-library/react"; +import { act, render, screen, waitFor } from "@testing-library/react"; import { Provider } from "react-redux"; import createMockStore from "redux-mock-store"; import { MemoryRouter } from "react-router-dom"; import React from "react"; import userEvent from "@testing-library/user-event"; -import { file } from "../testResults/uploads/Uploads.test"; +import { file } from "../utils/file"; import { FileUploadService } from "../../fileUploadService/FileUploadService"; import * as AppInsightsMock from "../TelemetryService"; @@ -55,9 +55,11 @@ const successResponseBody = { async function userEventUpload(uploadFile: File, facility: string) { const input = screen.getByTestId("upload-patients-file-input"); - await userEvent.upload(input, uploadFile); - await userEvent.click(screen.getByText(facility)); - await userEvent.click(screen.getByText("Upload CSV file")); + await act(async () => await userEvent.upload(input, uploadFile)); + await act(async () => await userEvent.click(screen.getByText(facility))); + await act( + async () => await userEvent.click(screen.getByText("Upload CSV file")) + ); } const submitCSVFile = async ( @@ -71,26 +73,6 @@ const submitCSVFile = async ( }; describe("Upload Patient", () => { - const trackEventMock = jest.fn(); - const trackMetricMock = jest.fn(); - const trackExceptionMock = jest.fn(); - const getAppInsightsSpy = jest.spyOn(AppInsightsMock, "getAppInsights"); - - beforeEach(() => { - getAppInsightsSpy.mockImplementation( - () => - ({ - trackEvent: trackEventMock, - trackMetric: trackMetricMock, - trackException: trackExceptionMock, - } as jest.MockedObject) - ); - }); - - afterEach(() => { - getAppInsightsSpy.mockRestore(); - }); - afterAll(() => { jest.clearAllMocks(); }); @@ -102,16 +84,19 @@ describe("Upload Patient", () => { describe("facility selector", () => { it("should add facility name to label when one facility is selected", async () => { renderUploadPatients(); - expect( - await screen.findByText("3. Upload your spreadsheet.") - ).toBeInTheDocument(); + expect(await screen.findByText("3. Upload your spreadsheet.")); - await userEvent.click(screen.getByText("One facility")); + await act( + async () => await userEvent.click(screen.getByText("One facility")) + ); expect(await screen.findByText("Which facility?")).toBeInTheDocument(); - await userEvent.selectOptions( - screen.getByRole("combobox", { name: /select facility/i }), - "2" + await act( + async () => + await userEvent.selectOptions( + screen.getByRole("combobox", { name: /select facility/i }), + "2" + ) ); expect( await screen.findByText( @@ -124,9 +109,13 @@ describe("Upload Patient", () => { expect( await screen.findByText("3. Upload your spreadsheet.") ).toBeInTheDocument(); - await userEvent.click(screen.getByText("One facility")); + await act( + async () => await userEvent.click(screen.getByText("One facility")) + ); - await userEvent.click(screen.getByText("All facilities")); + await act( + async () => await userEvent.click(screen.getByText("All facilities")) + ); expect( await screen.findByText("3. Upload your spreadsheet.") ).toBeInTheDocument(); @@ -137,11 +126,13 @@ describe("Upload Patient", () => { renderUploadPatients(); expect(await screen.findByText("Upload CSV file")).toBeDisabled(); - await userEvent.click(screen.getByText("One facility")); + await act( + async () => await userEvent.click(screen.getByText("One facility")) + ); expect(await screen.findByText("Upload CSV file")).toBeDisabled(); const uploadFile = file("someText"); const input = screen.getByTestId("upload-patients-file-input"); - await userEvent.upload(input, uploadFile); + await act(async () => await userEvent.upload(input, uploadFile)); expect(await screen.findByText("Upload CSV file")).toBeEnabled(); }); @@ -151,9 +142,11 @@ describe("Upload Patient", () => { const uploadFile = file("someText"); const input = screen.getByTestId("upload-patients-file-input"); - await userEvent.upload(input, uploadFile); + await act(async () => await userEvent.upload(input, uploadFile)); expect(await screen.findByText("Upload CSV file")).toBeDisabled(); - await userEvent.click(screen.getByText("One facility")); + await act( + async () => await userEvent.click(screen.getByText("One facility")) + ); expect(await screen.findByText("Upload CSV file")).toBeEnabled(); }); @@ -315,7 +308,7 @@ describe("Upload Patient", () => { const emptyFile = file(""); await userEventUpload(emptyFile, "One facility"); - expect(await screen.findByText("Error: Invalid file")).toBeInTheDocument(); + expect(await screen.findByText("Error: Invalid file")); expect(screen.getByText("File is missing or empty.")).toBeInTheDocument(); expect(screen.getByLabelText("Choose CSV file")).toHaveAttribute( "aria-invalid", @@ -369,7 +362,9 @@ describe("Upload Patient", () => { await screen.findByText("Success: Data confirmed") ).toBeInTheDocument(); - await userEvent.click(screen.getByLabelText("close")); + await act( + async () => await userEvent.click(screen.getByLabelText("close")) + ); expect( screen.queryByText("Success: Data confirmed") @@ -387,7 +382,9 @@ describe("Upload Patient", () => { ).toBeInTheDocument(); expect(await screen.findByText("bad zipcode")).toBeInTheDocument(); - await userEvent.click(screen.getByLabelText("close")); + await act( + async () => await userEvent.click(screen.getByLabelText("close")) + ); expect( screen.queryByText("Error: File not accepted") ).not.toBeInTheDocument(); @@ -452,7 +449,7 @@ describe("Upload Patient", () => { renderUploadPatients(); const input = screen.getByTestId("upload-patients-file-input"); - await userEvent.upload(input, []); + await act(async () => await userEvent.upload(input, [])); expect( screen.getByRole("button", { name: /upload csv file/i }) ).toBeDisabled(); @@ -469,7 +466,7 @@ describe("Upload Patient", () => { renderUploadPatients(); const input = screen.getByTestId("upload-patients-file-input"); - await userEvent.upload(input, file("someText")); + await act(async () => await userEvent.upload(input, file("someText"))); expect( screen.getByText("Drag file here or choose from folder to change file") ).toBeInTheDocument(); @@ -480,10 +477,31 @@ describe("Upload Patient", () => { }); }); describe("telemetry", () => { + const trackEventMock = jest.fn(); + const trackMetricMock = jest.fn(); + const trackExceptionMock = jest.fn(); + const getAppInsightsSpy = jest.spyOn(AppInsightsMock, "getAppInsights"); + beforeEach(() => { + getAppInsightsSpy.mockImplementation( + () => + ({ + trackEvent: trackEventMock, + trackMetric: trackMetricMock, + trackException: trackExceptionMock, + } as jest.MockedObject) + ); + }); + + afterEach(() => { + getAppInsightsSpy.mockClear(); + }); it("checks user click on guidelines gets tracked", async () => { renderUploadPatients(); - await userEvent.click( - screen.getByText(/View patient bulk upload guide/i) + await act( + async () => + await userEvent.click( + screen.getByText(/View patient bulk upload guide/i) + ) ); await waitFor(() => expect(trackEventMock).toHaveBeenCalledWith({ @@ -491,9 +509,15 @@ describe("Upload Patient", () => { }) ); }); + it("checks user download of csv sample gets tracked", async () => { renderUploadPatients(); - await userEvent.click(screen.getByText(/Download spreadsheet template/i)); + await act( + async () => + await userEvent.click( + screen.getByText(/Download spreadsheet template/i) + ) + ); await waitFor(() => expect(trackEventMock).toHaveBeenCalledWith({ name: "downloadPatientBulkUploadSample", diff --git a/frontend/src/app/signUp/Organization/OrganizationForm.test.tsx b/frontend/src/app/signUp/Organization/OrganizationForm.test.tsx index 11ebc6e24c..1951356d42 100644 --- a/frontend/src/app/signUp/Organization/OrganizationForm.test.tsx +++ b/frontend/src/app/signUp/Organization/OrganizationForm.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import OrganizationForm, { @@ -20,7 +20,7 @@ const getPhoneInput = () => screen.getByLabelText("Work phone number *"); const getSubmitButton = () => screen.getByText("Continue"); const fillInDropDown = async (input: any, text: string) => - await userEvent.selectOptions(input, [text]); + await act(async () => await userEvent.selectOptions(input, [text])); jest.mock("../SignUpApi", () => ({ SignUpApi: { @@ -79,8 +79,8 @@ describe("OrganizationForm", () => { it("displays form errors when submitting invalid input", async () => { await fillInDropDown(getOrgStateDropdown(), "VI"); - await userEvent.tab(); - getSubmitButton().click(); + await act(async () => await userEvent.tab()); + await act(async () => getSubmitButton().click()); expect(await screen.findByText("Organization name is required")); @@ -101,7 +101,7 @@ describe("OrganizationForm", () => { it("clears input when escaping out of modal", async () => { await fillInDropDown(getOrgStateDropdown(), "VI"); expect(getOrgStateDropdown().value).toEqual("VI"); - await userEvent.tab(); + await act(async () => await userEvent.tab()); expect( screen.getByText( "U.S. Virgin Islands isn't connected to SimpleReport yet.", @@ -111,14 +111,14 @@ describe("OrganizationForm", () => { ) ).toBeInTheDocument(); - await userEvent.keyboard("{Escape}"); + await act(async () => await userEvent.keyboard("{Escape}")); expect(getOrgStateDropdown().value).toBeFalsy(); }); it("does not clear input when continuing through modal", async () => { await fillInDropDown(getOrgStateDropdown(), "VI"); expect(getOrgStateDropdown().value).toEqual("VI"); - await userEvent.tab(); + await act(async () => await userEvent.tab()); expect( screen.getByText( "U.S. Virgin Islands isn't connected to SimpleReport yet.", @@ -128,22 +128,26 @@ describe("OrganizationForm", () => { ) ).toBeInTheDocument(); - screen.getByLabelText("acknowledged").click(); - screen.getByText("Continue sign up").click(); + await act(async () => screen.getByLabelText("acknowledged").click()); + await act(async () => screen.getByText("Continue sign up").click()); expect(getOrgStateDropdown().value).toEqual("VI"); }); it("redirects to identity verification when submitting valid input", async () => { - await userEvent.type(getOrgNameInput(), "Drake"); + await act(async () => await userEvent.type(getOrgNameInput(), "Drake")); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "ever@greatest.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "ever@greatest.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText("Redirected to /sign-up/identity-verification") @@ -151,15 +155,19 @@ describe("OrganizationForm", () => { }); it("displays a duplicate org error when submitting a duplicate org", async () => { - await userEvent.type(getOrgNameInput(), "Duplicate"); + await act(async () => await userEvent.type(getOrgNameInput(), "Duplicate")); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "ever@greatest.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "ever@greatest.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText( @@ -170,15 +178,19 @@ describe("OrganizationForm", () => { }); it("displays a duplicate email error when submitting a duplicate email", async () => { - await userEvent.type(getOrgNameInput(), "Foo"); + await act(async () => await userEvent.type(getOrgNameInput(), "Foo")); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "duplicate@test.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "duplicate@test.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText( @@ -189,15 +201,21 @@ describe("OrganizationForm", () => { }); it("displays a duplicate org error and id verification link for an admin re-signing up", async () => { - await userEvent.type(getOrgNameInput(), "DuplicateAdmin"); + await act( + async () => await userEvent.type(getOrgNameInput(), "DuplicateAdmin") + ); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "admin@example.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "admin@example.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText( @@ -208,15 +226,22 @@ describe("OrganizationForm", () => { }); it("displays a duplicate org error and instructions for admin user who has finished id verification", async () => { - await userEvent.type(getOrgNameInput(), "IdentityVerificationComplete"); + await act( + async () => + await userEvent.type(getOrgNameInput(), "IdentityVerificationComplete") + ); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "admin@example.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "admin@example.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText( @@ -227,15 +252,21 @@ describe("OrganizationForm", () => { }); it("displays a generic error message for Okta internal errors", async () => { - await userEvent.type(getOrgNameInput(), "InternalError"); + await act( + async () => await userEvent.type(getOrgNameInput(), "InternalError") + ); await fillInDropDown(getOrgStateDropdown(), "TX"); await fillInDropDown(getOrgTypeDropdown(), "Employer"); - await userEvent.type(getFirstNameInput(), "Greatest"); - await userEvent.type(getMiddleNameInput(), "OG"); - await userEvent.type(getLastNameInput(), "Ever"); - await userEvent.type(getEmailInput(), "admin@example.com"); - await userEvent.type(getPhoneInput(), "8008675309"); - getSubmitButton().click(); + await act( + async () => await userEvent.type(getFirstNameInput(), "Greatest") + ); + await act(async () => await userEvent.type(getMiddleNameInput(), "OG")); + await act(async () => await userEvent.type(getLastNameInput(), "Ever")); + await act( + async () => await userEvent.type(getEmailInput(), "admin@example.com") + ); + await act(async () => await userEvent.type(getPhoneInput(), "8008675309")); + await act(async () => getSubmitButton().click()); expect( await screen.findByText( diff --git a/frontend/src/app/signUp/Organization/UnsupportedStateModal.test.tsx b/frontend/src/app/signUp/Organization/UnsupportedStateModal.test.tsx index a3b2913f6a..a02c071ee4 100644 --- a/frontend/src/app/signUp/Organization/UnsupportedStateModal.test.tsx +++ b/frontend/src/app/signUp/Organization/UnsupportedStateModal.test.tsx @@ -1,4 +1,4 @@ -import { render, RenderResult, screen } from "@testing-library/react"; +import { act, render, RenderResult, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { UnsupportedStateModal } from "./UnsupportedStateModal"; @@ -20,20 +20,20 @@ describe("UnsupportedStateModal", () => { expect(component).toMatchSnapshot(); }); - it("closes on continue", () => { + it("closes on continue", async () => { const continueButton = screen.getByText("Continue sign up"); expect(continueButton).toBeDisabled(); - screen.getByLabelText("acknowledged").click(); + await act(async () => screen.getByLabelText("acknowledged").click()); expect(continueButton).toBeEnabled(); - continueButton.click(); + await act(async () => continueButton.click()); expect(mockOnClose).toBeCalledWith(false); }); it("closes on esc key", async () => { expect(mockOnClose).not.toHaveBeenCalled(); - await userEvent.keyboard("{Escape}"); + await act(async () => await userEvent.keyboard("{Escape}")); expect(mockOnClose).toHaveBeenCalledWith(true); }); }); diff --git a/frontend/src/app/supportAdmin/DeviceType/ManageDeviceTypeFormContainer.test.tsx b/frontend/src/app/supportAdmin/DeviceType/ManageDeviceTypeFormContainer.test.tsx index 6e6da8f675..8143a392a3 100644 --- a/frontend/src/app/supportAdmin/DeviceType/ManageDeviceTypeFormContainer.test.tsx +++ b/frontend/src/app/supportAdmin/DeviceType/ManageDeviceTypeFormContainer.test.tsx @@ -11,7 +11,10 @@ import mockSupportedDiseaseTestPerformedCovid from "./mocks/mockSupportedDisease const mockUpdateDeviceType = jest.fn(); const addValue = async (name: string, value: string) => { - await userEvent.type(screen.getByLabelText(name, { exact: false }), value); + await act( + async () => + await userEvent.type(screen.getByLabelText(name, { exact: false }), value) + ); }; jest.mock("../../../generated/graphql", () => { @@ -162,24 +165,41 @@ describe("ManageDeviceTypeFormContainer", () => { await addValue("Manufacturer", " LLC"); await addValue("Model", "D"); - await userEvent.selectOptions( - screen.getByLabelText("Supported disease *"), - "COVID-19" + await act( + async () => + await userEvent.selectOptions( + screen.getByLabelText("Supported disease *"), + "COVID-19" + ) ); - await userEvent.clear(screen.getByLabelText("Test performed code *")); - await userEvent.type( - screen.getByLabelText("Test performed code *"), - "LP 123" + await act( + async () => + await userEvent.clear(screen.getByLabelText("Test performed code *")) + ); + await act( + async () => + await userEvent.type( + screen.getByLabelText("Test performed code *"), + "LP 123" + ) ); - await userEvent.clear(screen.getByLabelText("Test ordered code *")); - await userEvent.type( - screen.getByLabelText("Test ordered code *"), - "LP 321" + await act( + async () => + await userEvent.clear(screen.getByLabelText("Test ordered code *")) + ); + await act( + async () => + await userEvent.type( + screen.getByLabelText("Test ordered code *"), + "LP 321" + ) ); expect(screen.getByText("Save changes")).toBeEnabled(); - await userEvent.click(screen.getByText("Save changes")); + await act( + async () => await userEvent.click(screen.getByText("Save changes")) + ); await waitFor(() => expect(mockUpdateDeviceType).toHaveBeenCalledWith({ diff --git a/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessForm.test.tsx b/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessForm.test.tsx index f75bb1f36d..53141192b6 100644 --- a/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessForm.test.tsx +++ b/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessForm.test.tsx @@ -42,17 +42,29 @@ describe("TenantDataAccessForm", () => { it("Submits a valid access form", async () => { // using the default test id that comes with the trusswork component - await userEvent.selectOptions( - screen.getByTestId("combo-box-select"), - "Org 1 Name" + await act( + async () => + await act( + async () => + await userEvent.selectOptions( + screen.getByTestId("combo-box-select"), + "Org 1 Name" + ) + ) ); - await userEvent.type( - screen.getByLabelText("Justification", { exact: false }), - "sample justification text" + await act( + async () => + await act( + async () => + await userEvent.type( + screen.getByLabelText("Justification", { exact: false }), + "sample justification text" + ) + ) ); const saveButton = screen.getAllByText("Access data")[0]; expect(saveButton).toBeEnabled(); - await userEvent.click(saveButton); + await act(async () => await userEvent.click(saveButton)); expect(saveTenantDataAccess).toBeCalledTimes(1); }); it("selecting/clearing org enables/disables access", async () => { @@ -60,12 +72,18 @@ describe("TenantDataAccessForm", () => { selectEvent.select(screen.getByLabelText(/organization/i), "Org 2 Name"); }); const saveButton = screen.getAllByText("Access data")[0]; - await userEvent.type( - screen.getByLabelText("Justification", { exact: false }), - "sample justification text" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Justification", { exact: false }), + "sample justification text" + ) ); expect(saveButton).toBeEnabled(); - await userEvent.click(screen.getByTestId("combo-box-clear-button")); + await act( + async () => + await userEvent.click(screen.getByTestId("combo-box-clear-button")) + ); await waitFor(() => { expect(saveButton).toBeDisabled(); }); @@ -73,24 +91,30 @@ describe("TenantDataAccessForm", () => { it("Submits a cancellation form", async () => { // using the default test id that comes with the trusswork component - await userEvent.selectOptions( - screen.getByTestId("combo-box-select"), - "Org 1 Name" + await act( + async () => + await userEvent.selectOptions( + screen.getByTestId("combo-box-select"), + "Org 1 Name" + ) ); - await userEvent.type( - screen.getByLabelText("Justification", { exact: false }), - "sample justification text" + await act( + async () => + await userEvent.type( + screen.getByLabelText("Justification", { exact: false }), + "sample justification text" + ) ); const cancelButton = await screen.getAllByText("Cancel access")[0]; expect(cancelButton).toBeEnabled(); - await userEvent.click(cancelButton); + await act(async () => await userEvent.click(cancelButton)); expect(saveTenantDataAccess).toBeCalledTimes(1); }); it("Cancel button always enabled", async () => { const cancelButton = await screen.getAllByText("Cancel access")[0]; expect(cancelButton).toBeEnabled(); - await userEvent.click(cancelButton); + await act(async () => await userEvent.click(cancelButton)); expect(saveTenantDataAccess).toBeCalledTimes(1); }); }); diff --git a/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessFormContainer.test.tsx b/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessFormContainer.test.tsx index 2ffcfc2de8..e835373b0b 100644 --- a/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessFormContainer.test.tsx +++ b/frontend/src/app/supportAdmin/TenantDataAccess/TenantDataAccessFormContainer.test.tsx @@ -1,4 +1,5 @@ import { + act, render, screen, waitForElementToBeRemoved, @@ -146,7 +147,7 @@ describe("TenantDataAccessFormContainer", () => { await waitForElementToBeRemoved(() => screen.queryByText("Loading Organizations …") ); - await userEvent.click(screen.getByRole("button")); + await act(async () => await userEvent.click(screen.getByRole("button"))); expect(await screen.findByText("Redirected")).toBeInTheDocument(); }); }); diff --git a/frontend/src/app/testQueue/AoEForm/AoEForm.test.tsx b/frontend/src/app/testQueue/AoEForm/AoEForm.test.tsx index 1813fd475e..d6d78a573e 100644 --- a/frontend/src/app/testQueue/AoEForm/AoEForm.test.tsx +++ b/frontend/src/app/testQueue/AoEForm/AoEForm.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import AoEForm from "./AoEForm"; @@ -227,7 +227,7 @@ describe("AoEForm", () => { }); expect(emailDeliveryRadio).toBeInTheDocument(); - await userEvent.click(emailDeliveryRadio); + await act(async () => await userEvent.click(emailDeliveryRadio)); expect(emailDeliveryRadio).toBeChecked(); }); }); diff --git a/frontend/src/app/testResults/TestResultPrintModal.test.tsx b/frontend/src/app/testResults/TestResultPrintModal.test.tsx index bf2465094d..15b99b9461 100644 --- a/frontend/src/app/testResults/TestResultPrintModal.test.tsx +++ b/frontend/src/app/testResults/TestResultPrintModal.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { cloneDeep } from "lodash"; import MockDate from "mockdate"; @@ -78,7 +78,9 @@ describe("TestResultPrintModal with only COVID results", () => { }); it("should render the test result print view", async () => { - await userEvent.click(screen.getAllByText("Print")[1]); + await act( + async () => await userEvent.click(screen.getAllByText("Print")[1]) + ); expect(printSpy).toBeCalled(); }); diff --git a/frontend/src/app/testResults/resultsTable/ResultsTable.test.tsx b/frontend/src/app/testResults/resultsTable/ResultsTable.test.tsx index 0ed217d2ce..3b8d4f1cd9 100644 --- a/frontend/src/app/testResults/resultsTable/ResultsTable.test.tsx +++ b/frontend/src/app/testResults/resultsTable/ResultsTable.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, within } from "@testing-library/react"; +import { act, render, screen, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { PATIENT_TERM_CAP } from "../../../config/constants"; @@ -166,7 +166,7 @@ describe("Component ResultsTable", () => { "button" )[1]; - await userEvent.click(moreActions); + await act(async () => await userEvent.click(moreActions)); // Action menu is open expect(screen.getByText("Print result")).toBeInTheDocument(); @@ -195,7 +195,7 @@ describe("Component ResultsTable", () => { "button" )[1]; - await userEvent.click(moreActions); + await act(async () => await userEvent.click(moreActions)); // Action menu is open expect(screen.getByText("Print result")).toBeInTheDocument(); @@ -225,7 +225,7 @@ describe("Component ResultsTable", () => { "button" )[1]; - await userEvent.click(moreActions); + await act(async () => await userEvent.click(moreActions)); // Action menu is open expect(screen.getByText("Print result")).toBeInTheDocument(); @@ -252,7 +252,7 @@ describe("Component ResultsTable", () => { "button" )[1]; - await userEvent.click(moreActions); + await act(async () => await userEvent.click(moreActions)); // Action menu is open expect(screen.getByText("Print result")).toBeInTheDocument(); diff --git a/frontend/src/app/testResults/submissions/Submission.test.tsx b/frontend/src/app/testResults/submissions/Submission.test.tsx index f9c77f5586..cb5c9ff141 100644 --- a/frontend/src/app/testResults/submissions/Submission.test.tsx +++ b/frontend/src/app/testResults/submissions/Submission.test.tsx @@ -1,5 +1,5 @@ import { MockedProvider } from "@apollo/client/testing"; -import { render, screen } from "@testing-library/react"; +import { render, screen, waitFor } from "@testing-library/react"; import { Provider } from "react-redux"; import { MemoryRouter, Route, Routes } from "react-router-dom"; import createMockStore from "redux-mock-store"; @@ -78,14 +78,10 @@ describe("Submission", () => { }); it("fetches upload submission details from GraphQL server", async () => { - await new Promise((resolve) => setTimeout(resolve, 0)); - - expect(mockIsDone).toBe(true); + await waitFor(() => expect(mockIsDone).toBe(true)); }); it("renders the bulk test result upload submission view", async () => { - await new Promise((resolve) => setTimeout(resolve, 0)); - expect(await screen.findByText("Report ID")); expect(await screen.findByText("12b86a9d-a9d6-4391-a555-6618e8ac66d9")); diff --git a/frontend/src/app/testResults/submissions/Submission.tsx b/frontend/src/app/testResults/submissions/Submission.tsx index b12e0b2348..ae05cdfd3f 100644 --- a/frontend/src/app/testResults/submissions/Submission.tsx +++ b/frontend/src/app/testResults/submissions/Submission.tsx @@ -68,7 +68,7 @@ const Submission = () => {
Report ID - {submission?.uploadSubmission.reportId} + {submission?.uploadSubmission.reportId}
Data stream diff --git a/frontend/src/app/testResults/submissions/Submissions.test.tsx b/frontend/src/app/testResults/submissions/Submissions.test.tsx index 58c1a830dc..325344f69f 100644 --- a/frontend/src/app/testResults/submissions/Submissions.test.tsx +++ b/frontend/src/app/testResults/submissions/Submissions.test.tsx @@ -1,4 +1,10 @@ -import { fireEvent, render, screen, waitFor } from "@testing-library/react"; +import { + act, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/react"; import createMockStore from "redux-mock-store"; import { MockedProvider } from "@apollo/client/testing"; import { Provider } from "react-redux"; @@ -142,7 +148,7 @@ describe("Submissions", () => { ); - await new Promise((resolve) => setTimeout(resolve, 0)); + expect(await screen.findByText("No results")); expect(screen.queryByRole("navigation")).not.toBeInTheDocument(); }); @@ -157,7 +163,6 @@ describe("Submissions", () => { ); - await new Promise((resolve) => setTimeout(resolve, 0)); expect(await screen.findByText("reportId_1")); expect(await screen.findByText("reportId_2")); @@ -186,9 +191,7 @@ describe("Submissions", () => { const startDateInput = screen.getByTestId("start-date"); fireEvent.change(startDateInput, { target: { value: "2021-01-01" } }); await waitFor(() => expect(startDateInput).toHaveValue("2021-01-01")); - await userEvent.tab(); - - await new Promise((resolve) => setTimeout(resolve, 0)); + await act(async () => await userEvent.tab()); expect(await screen.findByText("reportId_2")); expect(await screen.findByText("reportId_3")); @@ -213,7 +216,6 @@ describe("Submissions", () => { const endDateInput = screen.getByTestId("end-date"); fireEvent.change(endDateInput, { target: { value: "2022-01-01" } }); - await new Promise((resolve) => setTimeout(resolve, 0)); await waitFor(() => expect(screen.queryByText("reportId_1")).not.toBeInTheDocument() @@ -235,8 +237,6 @@ describe("Submissions", () => { ); - await new Promise((resolve) => setTimeout(resolve, 0)); - await forEach([result_1, result_2, result_3], async (result) => { await waitFor(() => expect(screen.getByText(result.reportId).closest("a")).toHaveAttribute( diff --git a/frontend/src/app/testResults/uploads/Uploads.test.tsx b/frontend/src/app/testResults/uploads/Uploads.test.tsx index 15bec5ba31..fa74594c77 100644 --- a/frontend/src/app/testResults/uploads/Uploads.test.tsx +++ b/frontend/src/app/testResults/uploads/Uploads.test.tsx @@ -1,4 +1,4 @@ -import { render, screen, waitFor } from "@testing-library/react"; +import { act, render, screen, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import createMockStore from "redux-mock-store"; import { Provider } from "react-redux"; @@ -7,6 +7,7 @@ import { ApplicationInsights } from "@microsoft/applicationinsights-web"; import React from "react"; import { MemoryRouter as Router } from "react-router"; +import { file } from "../../utils/file"; import { getAppInsights } from "../../TelemetryService"; import { FileUploadService } from "../../../fileUploadService/FileUploadService"; import SRToastContainer from "../../commonComponents/SRToastContainer"; @@ -36,13 +37,6 @@ const validFileContents = "Patient_last_name,Patient_first_name,Patient_middle_name,Patient_suffix,Patient_tribal_affiliation,Patient_ID,Ordered_test_code,Specimen_source_site_code,Specimen_type_code,Device_ID,Instrument_ID,Result_ID,Corrected_result_ID,Test_correction_reason,Test_result_status,Test_result_code,Illness_onset_date,Specimen_collection_date_time,Order_test_date,Test_date,Date_result_released,Patient_race,Patient_DOB,Patient_gender,Patient_ethnicity,Patient_preferred_language,Patient_street,Patient_street_2,Patient_city,Patient_state,Patient_zip_code,Patient_country,Patient_phone_number,Patient_county,Patient_email,Patient_role,Processing_mode_code,Employed_in_healthcare,Resident_congregate_setting,First_test,Symptomatic_for_disease,Testing_lab_name,Testing_lab_CLIA,Testing_lab_street,Testing_lab_street_2,Testing_lab_city,Testing_lab_state,Testing_lab_zip_code,Testing_lab_phone_number,Testing_lab_county,Organization_name,Ordering_facility_name,Ordering_facility_street,Ordering_facility_street_2,Ordering_facility_city,Ordering_facility_state,Ordering_facility_zip_code,Ordering_facility_phone_number,Ordering_facility_county,Ordering_provider_ID,Ordering_provider_last_name,Ordering_provider_first_name,Ordering_provider_street,Ordering_provider_street_2,Ordering_provider_city,Ordering_provider_state,Ordering_provider_zip_code,Ordering_provider_phone_number,Ordering_provider_county,Site_of_care\n" + "Alaska1,Judy,Suellen,,39,xen4p,94558-4,71836000,440500007,BD Veritor System for Rapid Detection of SARS-CoV-2,939273,Alaska1,613603,nh1rigems,F,260373001,20220225,202202201809-0500,202202261540-0500,20220221,20220220,2106-3,,F,H,Iloko,10269 Larry Villages,,Yellow jacket,AK,81335,USA,2853464789,Montezuma,lyndon.smitham@email.com,kgvmoxba,P,Y,UNK,N,Y,Any lab USA,BadCLIA,3279 Schroeder Mountain,,Yellow jacket,AK,81335,2365001476,Montezuma,see3r8,Any facility USA,35260 Dustin Crossroad,,Yellow jacket,AK,81335,2862149859,Montezuma,1368398388,Huels,Bradley,283 Runolfsson Drive,,Yellow jacket,AK,81335,2241497529,Montezuma,camp\n"; -export const file = (text: BlobPart) => { - const blob = new Blob([text]); - const file = new File([blob], "values.csv", { type: "text/csv" }); - File.prototype.text = jest.fn().mockResolvedValueOnce(text); - return file; -}; - const validFile = () => file(validFileContents); const TestContainer = () => ( @@ -70,7 +64,7 @@ describe("Uploads", () => { const emptyFile = file(""); const input = screen.getByTestId("upload-csv-input"); - await userEvent.upload(input, emptyFile); + await act(async () => await userEvent.upload(input, emptyFile)); expect( await screen.findByText( "The file 'values.csv' doesn't contain any valid data. File should have a header line and at least one line of data." @@ -88,7 +82,7 @@ describe("Uploads", () => { const tooManyRows = file("\n".repeat(10001)); const input = screen.getByTestId("upload-csv-input"); - await userEvent.upload(input, tooManyRows); + await act(async () => await userEvent.upload(input, tooManyRows)); expect( await screen.findByText( @@ -107,7 +101,7 @@ describe("Uploads", () => { const tooBig = file("0".repeat(50 * 1000 * 1000 + 1)); const input = screen.getByTestId("upload-csv-input"); - await userEvent.upload(input, tooBig); + await act(async () => await userEvent.upload(input, tooBig)); expect( await screen.findByText( @@ -126,7 +120,7 @@ describe("Uploads", () => { const tooManyColumns = file("a, ".repeat(2001) + "\n"); const input = screen.getByTestId("upload-csv-input"); - await userEvent.upload(input, tooManyColumns); + await act(async () => await userEvent.upload(input, tooManyColumns)); expect( await screen.findByText( @@ -180,7 +174,7 @@ describe("Uploads", () => { render(); const fileInput = screen.getByTestId("upload-csv-input"); - await userEvent.upload(fileInput, file); + await act(async () => await userEvent.upload(fileInput, file)); expect( screen.getByText( @@ -189,7 +183,7 @@ describe("Uploads", () => { ).toBeInTheDocument(); const submitButton = screen.getByTestId("button"); - await userEvent.click(submitButton); + await act(async () => await userEvent.click(submitButton)); await waitFor(() => { expect( screen.getByText("Success: File Accepted") @@ -233,14 +227,14 @@ describe("Uploads", () => { render(); const fileInput = screen.getByTestId("upload-csv-input"); - await userEvent.upload(fileInput, validFile()); + await act(async () => await userEvent.upload(fileInput, validFile())); expect( screen.getByText("Drag file here or choose from folder to change file") ).toBeInTheDocument(); const submitButton = screen.getByTestId("button"); - await userEvent.click(submitButton); + await act(async () => await userEvent.click(submitButton)); await waitFor(() => { expect( @@ -288,13 +282,13 @@ describe("Uploads", () => { await render(); const fileInput = screen.getByTestId("upload-csv-input"); - await userEvent.upload(fileInput, validFile()); + await act(async () => await userEvent.upload(fileInput, validFile())); expect( screen.getByText("Drag file here or choose from folder to change file") ).toBeInTheDocument(); const submitButton = screen.getByTestId("button"); - await userEvent.click(submitButton); + await act(async () => await userEvent.click(submitButton)); await waitFor(() => { expect( diff --git a/frontend/src/app/utils/Prompt.test.tsx b/frontend/src/app/utils/Prompt.test.tsx index 6791ea6e75..8c990b9b74 100644 --- a/frontend/src/app/utils/Prompt.test.tsx +++ b/frontend/src/app/utils/Prompt.test.tsx @@ -1,5 +1,5 @@ import { Link, MemoryRouter, Outlet, Route, Routes } from "react-router-dom"; -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import Prompt from "./Prompt"; @@ -42,7 +42,9 @@ describe("A ", () => { expect(screen.getByText("This is the first page")).toBeInTheDocument(); // WHEN - await userEvent.click(screen.getByText("Go to a new page")); + await act( + async () => await userEvent.click(screen.getByText("Go to a new page")) + ); // THEN expect(screen.queryByText("Went to a new page!")).not.toBeInTheDocument(); @@ -89,7 +91,9 @@ describe("A ", () => { expect(screen.getByText("This is the first page")).toBeInTheDocument(); // WHEN - await userEvent.click(screen.getByText("Go to a new page")); + await act( + async () => await userEvent.click(screen.getByText("Go to a new page")) + ); // THEN expect(confirmMock).toHaveBeenCalledWith( @@ -136,7 +140,9 @@ describe("A ", () => { expect(screen.getByText("This is the first page")).toBeInTheDocument(); // WHEN - await userEvent.click(screen.getByText("Go to a new page")); + await act( + async () => await userEvent.click(screen.getByText("Go to a new page")) + ); // THEN expect(screen.getByText("Went to a new page!")).toBeInTheDocument(); diff --git a/frontend/src/app/utils/file.ts b/frontend/src/app/utils/file.ts new file mode 100644 index 0000000000..bffd11b7f0 --- /dev/null +++ b/frontend/src/app/utils/file.ts @@ -0,0 +1,6 @@ +export const file = (text: BlobPart) => { + const blob = new Blob([text]); + const file = new File([blob], "values.csv", { type: "text/csv" }); + File.prototype.text = jest.fn().mockResolvedValueOnce(text); + return file; +}; diff --git a/frontend/src/patientApp/PatientHeader.test.tsx b/frontend/src/patientApp/PatientHeader.test.tsx index c5c16a2c5d..c910d0c4b9 100644 --- a/frontend/src/patientApp/PatientHeader.test.tsx +++ b/frontend/src/patientApp/PatientHeader.test.tsx @@ -1,4 +1,4 @@ -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { MemoryRouter } from "react-router-dom"; import configureStore from "redux-mock-store"; @@ -45,7 +45,7 @@ describe("PatientHeader", () => { expect(screen.getByText("Español")).toBeInTheDocument(); - await userEvent.click(screen.getByRole("button")); + await act(async () => await userEvent.click(screen.getByRole("button"))); expect(screen.queryByText("Español")).not.toBeInTheDocument(); expect(screen.getByText("English")).toBeInTheDocument();