From 986cb7178b5fe0056ebe59883926c55fac6ba219 Mon Sep 17 00:00:00 2001 From: dovvnloading <157447210+dovvnloading@users.noreply.github.com> Date: Fri, 4 Sep 2026 23:56:28 -0400 Subject: [PATCH] Stop the Document View lazy-body tests timing out under suite load PR #416 split the Document View's markdown body behind a React.lazy import and updated its tests to await the result. Those awaits use testing-library's default 1000ms, which is enough when the file runs alone and not enough when the full suite runs: measured, two full-suite runs in three failed on `findByRole("heading")` or `findByText("still here")`. CI passed on #416 and on the merge, so this was already on main and would have started failing unrelated pull requests. The wait is long for a reason that only exists in the test environment. In a built bundle the lazy body is a prebuilt chunk; under vitest it is the FIRST transform of react-markdown plus six remark/rehype plugins, and 93 test files are competing for the worker pool while it happens. Nothing about the panel is slow. So the fix is to wait properly rather than to reach for fake timers or stub the import away - stubbing it would stop the tests exercising the thing #416 actually changed. One named constant at the four call sites that await the lazy body, with the measurement written down next to it. Verified both directions, because a longer timeout is exactly the kind of change that can quietly turn a test into a no-op: - five consecutive full-suite runs, 2,197 passed every time (was 2 failures in 3 runs before) - with the panel's body wired to never render, seven tests in the file fail and the suite goes red, so the wait has not made them vacuous Test plan: npm run check green. Python suite 3,285 passed / 20 skipped. Co-Authored-By: Claude Opus 5 --- .../src/app/canvas/DocumentViewPanel.test.tsx | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/web_ui/src/app/canvas/DocumentViewPanel.test.tsx b/web_ui/src/app/canvas/DocumentViewPanel.test.tsx index 71a6138..c6fbfb7 100644 --- a/web_ui/src/app/canvas/DocumentViewPanel.test.tsx +++ b/web_ui/src/app/canvas/DocumentViewPanel.test.tsx @@ -21,6 +21,17 @@ beforeEach(() => { global.IntersectionObserver = FakeIntersectionObserver; }); +// The panel's body arrives through a React.lazy dynamic import. In a built +// bundle that is a prebuilt chunk; under vitest it is the FIRST transform of +// react-markdown plus six remark/rehype plugins, and with 93 test files +// competing for the worker pool that regularly runs past testing-library's +// 1000ms default - two full-suite runs in three, measured. The wait is long +// because the test environment is slow to compile the module graph, not +// because the panel is slow, so the right fix is to wait properly rather +// than to reach for fake timers or to stub the import away and stop testing +// the thing that broke. +const LAZY_BODY_TIMEOUT = { timeout: 15_000 }; + function renderPanel(overrides: Partial> = {}) { const props = { isOpen: true, @@ -39,7 +50,7 @@ describe("DocumentViewPanel", () => { // The title is part of the eager shell; the body arrives with the lazy // markdown chunk, hence findBy rather than getBy. expect(screen.getByText("Document View")).toBeInTheDocument(); - expect(await screen.findByRole("heading", { name: "Heading" })).toBeInTheDocument(); + expect(await screen.findByRole("heading", { name: "Heading" }, LAZY_BODY_TIMEOUT)).toBeInTheDocument(); expect(screen.getByText("A paragraph of body text.")).toBeInTheDocument(); }); @@ -91,7 +102,7 @@ describe("DocumentViewPanel", () => { it("keeps its content mounted after being closed again, so reopening does not flicker", async () => { const { rerender } = renderPanel({ isOpen: true, content: "still here" }); - expect(await screen.findByText("still here")).toBeInTheDocument(); + expect(await screen.findByText("still here", undefined, LAZY_BODY_TIMEOUT)).toBeInTheDocument(); rerender( , @@ -195,7 +206,9 @@ describe("DocumentViewPanel", () => { renderPanel({ content: "# One\n\n## Two" }); // Headings come from a dynamically imported parser, so they land a // microtask after mount rather than during it. - expect(await screen.findByRole("button", { name: "Outline" })).toBeInTheDocument(); + expect( + await screen.findByRole("button", { name: "Outline" }, LAZY_BODY_TIMEOUT), + ).toBeInTheDocument(); }); it("shows no Outline toggle when the content has fewer than 2 headings", () => { @@ -459,7 +472,7 @@ describe("DocumentViewPanel", () => { const onClose = vi.fn(); renderPanel({ onClose, content: "# One\n\n## Two" }); - await user.click(await screen.findByRole("button", { name: "Outline" })); + await user.click(await screen.findByRole("button", { name: "Outline" }, LAZY_BODY_TIMEOUT)); expect(screen.getByRole("menu", { name: "Table of contents" })).toBeInTheDocument(); await user.keyboard("{Escape}");