diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d69335a..5a559a2b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: node-version: "14.x" - uses: c-hive/gha-yarn-cache@v1 - run: yarn install --frozen-lockfile - - run: yarn test --coverage + - run: yarn test --coverage --runInBand - name: Coveralls uses: coverallsapp/github-action@master with: @@ -69,7 +69,7 @@ jobs: node-version: "14.x" - uses: c-hive/gha-yarn-cache@v1 - run: yarn install --frozen-lockfile - - run: yarn test --coverage --forceExit + - run: yarn test --coverage --forceExit --runInBand - name: Coveralls uses: coverallsapp/github-action@master with: @@ -104,7 +104,7 @@ jobs: node-version: "14.x" - uses: c-hive/gha-yarn-cache@v1 - run: yarn install --frozen-lockfile - - run: yarn test --coverage + - run: yarn test --coverage --runInBand - name: Coveralls uses: coverallsapp/github-action@master with: diff --git a/spotlight-client/src/App-auth.test.tsx b/spotlight-client/src/App-auth.test.tsx index e95b1be2..7db57834 100644 --- a/spotlight-client/src/App-auth.test.tsx +++ b/spotlight-client/src/App-auth.test.tsx @@ -77,14 +77,12 @@ afterEach(() => { cleanup(); }); -// TODO (#353) async specs fail intermittently -test.skip("no auth required", async () => { +test("no auth required", async () => { const App = await getApp(); render(); // site home redirects to the ND home - const websiteName = await screen.findByRole("heading", { - name: authenticatedTextMatch, - }); + const websiteName = await screen.findByTestId("PageTitle"); + expect(websiteName).toHaveTextContent(authenticatedTextMatch); expect(websiteName).toBeInTheDocument(); }); @@ -112,8 +110,7 @@ test("requires authentication", async () => { }); }); -// TODO (#353) async specs fail intermittently -test.skip("requires email verification", async () => { +test("requires email verification", async () => { // configure environment for valid authentication process.env.REACT_APP_AUTH_ENABLED = "true"; process.env.REACT_APP_AUTH_ENV = "development"; @@ -126,12 +123,10 @@ test.skip("requires email verification", async () => { render(); await waitFor(() => { // application contents should not have been rendered without verification - expect( - screen.queryByRole("heading", { name: authenticatedTextMatch }) - ).not.toBeInTheDocument(); + expect(screen.queryByTestId("PageTitle")).not.toBeInTheDocument(); // there should be a message about the verification requirement expect( - screen.getByRole("heading", { name: /verification/i }) + screen.getByRole("heading", { name: /verification/i, hidden: true }) ).toBeInTheDocument(); }); }); diff --git a/spotlight-client/src/App.test.tsx b/spotlight-client/src/App.test.tsx index 32ceeea1..60b01f38 100644 --- a/spotlight-client/src/App.test.tsx +++ b/spotlight-client/src/App.test.tsx @@ -107,8 +107,7 @@ describe("navigation", () => { expect(screen.getByRole(...lookupArgs)).toBeInTheDocument(); }); - // TODO (#353) async specs fail intermittently - test.skip("links", async () => { + test("links", async () => { renderNavigableApp(); const inNav = within(screen.getByRole("navigation")); @@ -120,38 +119,41 @@ describe("navigation", () => { }); fireEvent.click(sentencingLink); - expect( - await screen.findByRole("heading", { name: "Sentencing", level: 1 }) - ).toBeInTheDocument(); + // NOTE: *ByRole queries can be too expensive to run async with this much DOM, + // so we are using *ByTestId queries here instead + await waitFor(async () => + expect(await screen.findByTestId("PageTitle")).toHaveTextContent( + "Sentencing" + ) + ); fireEvent.click(tenantLink); - expect( - await screen.findByRole("heading", { - name: "Explore correctional data from North Dakota.", - level: 1, - }) - ).toBeInTheDocument(); + await waitFor(async () => + expect(await screen.findByTestId("PageTitle")).toHaveTextContent( + "Explore correctional data from North Dakota." + ) + ); const disparitiesLink = screen.getByRole("link", { name: "Racial Disparities", }); fireEvent.click(disparitiesLink); - expect( - await screen.findByRole("heading", { - name: "Racial Disparities", - level: 1, - }) - ).toBeInTheDocument(); + await waitFor(async () => + expect(await screen.findByTestId("PageTitle")).toHaveTextContent( + "Racial Disparities" + ) + ); fireEvent.click(homeLink); // home redirect to ND - expect( - await screen.findByRole("heading", { name: /North Dakota/, level: 1 }) - ).toBeInTheDocument(); + await waitFor(async () => + expect(await screen.findByTestId("PageTitle")).toHaveTextContent( + "North Dakota" + ) + ); }); - // TODO (#353) async specs fail intermittently - test.skip("pageview tracking", async () => { + test("pageview tracking", async () => { segmentMock.page.mockReset(); const { @@ -168,10 +170,6 @@ describe("navigation", () => { ); expect(segmentMock.page).toHaveBeenCalledTimes(2); - // in-page navigation doesn't trigger additional pageviews - await act(() => navigate(`/us-nd/${NarrativesSlug}/prison/2`)); - expect(segmentMock.page).toHaveBeenCalledTimes(2); - await act(() => navigate(`/us-nd/${NarrativesSlug}/sentencing`)); expect(document.title).toBe( diff --git a/spotlight-client/src/Loading/Loading.tsx b/spotlight-client/src/Loading/Loading.tsx index 0b276316..4ef10abc 100644 --- a/spotlight-client/src/Loading/Loading.tsx +++ b/spotlight-client/src/Loading/Loading.tsx @@ -53,7 +53,7 @@ const LoadingSpinnerText = styled.div` export default function Loading(): JSX.Element { return ( - + Data is loading diff --git a/spotlight-client/src/ModelHydrator/ModelHydrator.test.tsx b/spotlight-client/src/ModelHydrator/ModelHydrator.test.tsx index e4e03890..721ed7d7 100644 --- a/spotlight-client/src/ModelHydrator/ModelHydrator.test.tsx +++ b/spotlight-client/src/ModelHydrator/ModelHydrator.test.tsx @@ -56,14 +56,13 @@ test("hydration in progress", () => { expect(screen.queryByText("hydrated")).not.toBeInTheDocument(); }); -// TODO (#353) async specs fail intermittently -test.skip("hydrated", async () => { +test("hydrated", async () => { runInAction(() => { mockModel.isLoading = false; }); await waitFor(() => { - expect(screen.queryByRole("status")).not.toBeInTheDocument(); + expect(screen.queryByTestId("LoadingIndicator")).not.toBeInTheDocument(); expect(screen.getByText("hydrated")).toBeInTheDocument(); }); }); diff --git a/spotlight-client/src/RacialDisparitiesNarrativePage/RacialDisparitiesNarrativePage.test.tsx b/spotlight-client/src/RacialDisparitiesNarrativePage/RacialDisparitiesNarrativePage.test.tsx index 7f4d6065..b5caf97a 100644 --- a/spotlight-client/src/RacialDisparitiesNarrativePage/RacialDisparitiesNarrativePage.test.tsx +++ b/spotlight-client/src/RacialDisparitiesNarrativePage/RacialDisparitiesNarrativePage.test.tsx @@ -32,9 +32,9 @@ beforeEach(() => { }); test("renders all the sections", async () => { - expect( - await screen.findByRole("heading", { name: "Racial Disparities", level: 1 }) - ).toBeInTheDocument(); + expect(await screen.findByTestId("PageTitle")).toHaveTextContent( + "Racial Disparities" + ); return Promise.all( Object.values(narrativeContent.sections).map(async (section) => { diff --git a/spotlight-client/src/UiLibrary/PageTitle.ts b/spotlight-client/src/UiLibrary/PageTitle.ts index 94632218..94b573c9 100644 --- a/spotlight-client/src/UiLibrary/PageTitle.ts +++ b/spotlight-client/src/UiLibrary/PageTitle.ts @@ -20,7 +20,7 @@ import styled from "styled-components/macro"; import breakpoints from "./breakpoints"; import { typefaces } from "./typography"; -export default styled.h1` +export default styled.h1.attrs({ "data-testid": "PageTitle" })` font-family: ${typefaces.display}; font-size: ${rem(32)}; letter-spacing: -0.04em; diff --git a/spotlight-client/src/VizPopulationBreakdownByLocation/VizPopulationBreakdownByLocation.test.tsx b/spotlight-client/src/VizPopulationBreakdownByLocation/VizPopulationBreakdownByLocation.test.tsx index 83906ad3..f2ceb1cb 100644 --- a/spotlight-client/src/VizPopulationBreakdownByLocation/VizPopulationBreakdownByLocation.test.tsx +++ b/spotlight-client/src/VizPopulationBreakdownByLocation/VizPopulationBreakdownByLocation.test.tsx @@ -54,12 +54,11 @@ test("loading", () => { expect(screen.getByText(/loading/i)).toBeInTheDocument(); }); -// TODO (#353) async specs fail intermittently -test.skip("total counts", async () => { +test("total counts", async () => { renderWithStore(); await waitFor(() => { - const stat = screen.getByRole("figure", { name: "Total people in prison" }); + const stat = screen.getByLabelText("Total people in prison"); expect(stat).toBeVisible(); expect(within(stat).getByText("2,041")).toBeVisible(); }); @@ -140,8 +139,7 @@ test.skip("total counts", async () => { ).toHaveStyle(`fill: ${colors.dataViz[1]}`); }); -// TODO (#353) async specs fail intermittently -test.skip("counts filtered by locality", async () => { +test("counts filtered by locality", async () => { renderWithStore(); await when(() => !metric.isLoading); @@ -158,7 +156,7 @@ test.skip("counts filtered by locality", async () => { fireEvent.click(option); await waitFor(() => { - const stat = screen.getByRole("figure", { name: "Total people in prison" }); + const stat = screen.getByLabelText("Total people in prison"); expect(within(stat).getByText("413")).toBeVisible(); }); diff --git a/spotlight-client/src/VizRecidivismRateCumulative/VizRecidivismRateCumulative.test.tsx b/spotlight-client/src/VizRecidivismRateCumulative/VizRecidivismRateCumulative.test.tsx index d9d71260..3cc7b07d 100644 --- a/spotlight-client/src/VizRecidivismRateCumulative/VizRecidivismRateCumulative.test.tsx +++ b/spotlight-client/src/VizRecidivismRateCumulative/VizRecidivismRateCumulative.test.tsx @@ -88,8 +88,7 @@ test("total chart", async () => { } }); -// TODO (#353) async specs fail intermittently -test.skip("demographic charts", async () => { +test("demographic charts", async () => { renderWithStore(); await when(() => !metric.isLoading); @@ -110,10 +109,6 @@ test.skip("demographic charts", async () => { name: "5 lines in a line chart", }); - await waitFor(() => { - expect(lineChart).toBeVisible(); - }); - expect( within(lineChart).getAllByRole("img", { name: /^3 point line starting value 0% at 0 ending value \d+% at 2/, @@ -127,10 +122,6 @@ test.skip("demographic charts", async () => { name: "2 lines in a line chart", }); - await waitFor(() => { - expect(lineChart).toBeVisible(); - }); - expect( within(lineChart).getAllByRole("img", { name: /^3 point line starting value 0% at 0 ending value \d+% at 2/, @@ -146,8 +137,6 @@ test.skip("demographic charts", async () => { }); }); - expect(lineChart).toBeVisible(); - expect( within(lineChart).getAllByRole("img", { name: /^3 point line starting value 0% at 0 ending value \d+% at 2/, diff --git a/spotlight-client/src/VizRecidivismRateSingleFollowup/VizRecidivismRateSingleFollowup.test.tsx b/spotlight-client/src/VizRecidivismRateSingleFollowup/VizRecidivismRateSingleFollowup.test.tsx index 961237f1..f00770f8 100644 --- a/spotlight-client/src/VizRecidivismRateSingleFollowup/VizRecidivismRateSingleFollowup.test.tsx +++ b/spotlight-client/src/VizRecidivismRateSingleFollowup/VizRecidivismRateSingleFollowup.test.tsx @@ -102,8 +102,7 @@ test("total chart", async () => { ).toBeInTheDocument(); }); -// TODO (#353) async specs fail intermittently -test.skip("demographic charts", async () => { +test("demographic charts", async () => { renderWithStore(); await when(() => !metric.isLoading); @@ -159,8 +158,9 @@ test("followup period filter", async () => { fireEvent.click(menuButton); fireEvent.click(screen.getByRole("option", { name: "1 Year" })); - const oneYearChart = screen.getByRole("group", { + const oneYearChart = await screen.findByRole("group", { name: "10 bars in a bar chart", + hidden: true, }); expect(oneYearChart).toBeVisible();