Skip to content

Commit

Permalink
Fix RTL errors about wrapping react state updates in act (#3239)
Browse files Browse the repository at this point in the history
* Use async method to wait for spinner

* Use act() to wrap store dispatches
  • Loading branch information
grahamalama authored May 9, 2024
1 parent bad909b commit 0eceeef
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 27 deletions.
55 changes: 30 additions & 25 deletions test/components/Layout_test.tsx
Original file line number Diff line number Diff line change
@@ -1,52 +1,54 @@
import * as sessionActions from "@src/actions/session";
import { Layout } from "@src/components/Layout";
import { renderWithProvider } from "@test/testUtils";
import { fireEvent, waitFor } from "@testing-library/react";
import { act, fireEvent, screen } from "@testing-library/react";
import React from "react";

describe("App component", () => {
let app, store;
beforeEach(() => {
vi.spyOn(sessionActions, "logout");
app = renderWithProvider(<Layout />);
store = app.store;
});

describe("Session top bar", () => {
it("should not render a session top bar when not authenticated", () => {
expect(app.queryByTestId("sessionInfo-bar")).toBeNull();
renderWithProvider(<Layout />);
expect(screen.queryByTestId("sessionInfo-bar")).toBeNull();
});

it("should render a session top bar when anonymous", async () => {
const { store, container } = renderWithProvider(<Layout />);
const serverInfo = {
url: "http://test.server/v1/",
capabilities: {},
};
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(sessionActions.setAuthenticated());
await waitFor(() => new Promise(resolve => setTimeout(resolve, 500))); // debounce wait
const content = app.container.textContent;
act(() => {
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(sessionActions.setAuthenticated());
});
const content = container.textContent;

expect(content).toContain("Anonymous");
expect(content).toContain(serverInfo.url);
});

it("should display a link to the server docs", async () => {
const { store } = renderWithProvider(<Layout />);
const serverInfo = {
url: "http://test.server/v1/",
project_docs: "https://remote-settings.readthedocs.io/",
capabilities: {},
};
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(
sessionActions.setAuthenticated({ user: { id: "fxa:abc" } })
act(() => {
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(
sessionActions.setAuthenticated({ user: { id: "fxa:abc" } })
);
});
expect(screen.getByText(/Documentation/)).toHaveAttribute(
"href",
serverInfo.project_docs
);
await waitFor(() => new Promise(resolve => setTimeout(resolve, 500))); // debounce wait

expect(app.getByText(/Documentation/).href).toBe(serverInfo.project_docs);
});

it("should render a session top bar when authenticated", async () => {
const { store } = renderWithProvider(<Layout />);
const spy = vi.spyOn(sessionActions, "logout");
const serverInfo = {
url: "http://test.server/v1/",
capabilities: {},
Expand All @@ -58,21 +60,24 @@ describe("App component", () => {
username: "user",
password: "pass",
};
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(sessionActions.setupComplete());
store.dispatch(sessionActions.setAuthenticated(credentials));
await waitFor(() => new Promise(resolve => setTimeout(resolve, 500))); // debounce wait
act(() => {
store.dispatch(sessionActions.serverInfoSuccess(serverInfo));
store.dispatch(sessionActions.setupComplete());
store.dispatch(sessionActions.setAuthenticated(credentials));
});

const infoBar = app.getByTestId("sessionInfo-bar");
const infoBar = screen.getByTestId("sessionInfo-bar");
expect(infoBar).toBeDefined();

const content = infoBar.textContent;
expect(content).toContain(serverInfo.url);
expect(content).toContain(serverInfo.user.id);
expect(content).not.toContain(credentials.password);

fireEvent.click(app.getByText(/Logout/));
fireEvent.click(screen.getByText(/Logout/));
expect(sessionActions.logout).toHaveBeenCalled();

spy.mockClear();
});
});
});
4 changes: 2 additions & 2 deletions test/components/signoff/SimpleReview/SimpleReview_test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe("SimpleTest component", () => {
renderSimpleReview({
session: sessionFactory({ authenticated: false, authenticating: true }),
});
expect(screen.queryByTestId("spinner")).toBeDefined();
expect(screen.findByTestId("spinner")).toBeDefined();
});

it("should render not authenticated", async () => {
Expand Down Expand Up @@ -208,7 +208,7 @@ describe("SimpleTest component", () => {
renderSimpleReview({ session });

// Since Simple Review is the default, this means we're in the legacy UI
expect(screen.queryByText("Switch to Default Review UI")).toBeDefined();
expect(screen.findByText("Switch to Default Review UI")).toBeDefined();
});

describe("to_review_enabled checks", () => {
Expand Down

0 comments on commit 0eceeef

Please sign in to comment.