fix(tests): rendering.test queries container; the modal is portalled (28 → 4) (#2895)

## Fourth file, same defect

`TaskDetailModal.rendering.test.tsx` is the whole of the dashboard
`app:backfill 4/4` shard bar one case (28 of 29).

**57** container-rooted lookups converted. `TaskDetailModal` mounts
through `createPortal`, so `container` is empty and every one returned
null — visible in the two failure shapes this file produced:

```
10x   expected null to be truthy
~14x  expected undefined to be '<some text>'      ← container.querySelector(x)?.textContent
```

## Four remain, deliberately

They assert the modal's **wrapper structure**, not its contents:

```ts
expect(document.querySelector(".modal-overlay.open")).toBeTruthy();
```

`FloatingWindow` renders `.floating-window-overlay`
(`FloatingWindow.tsx:627`). The only `.modal-overlay open` left in
`TaskDetailModal` is the unrelated *refine* overlay at `:6801`. So these
pin the **pre-FloatingWindow** wrapper.

Re-pointing them means encoding the *current* modal-shell contract — a
UI structure decision that belongs with whoever owns the FloatingWindow
adoption, not bundled into a query-root fix where it would be easy to
miss. Left failing and flagged rather than guessed at.

It is also a different failure shape from the rest: `expected <div …> to
be null` on a mobile-variant badge, i.e. an assertion that *found*
something, versus 24 that found nothing. Different cause, different fix,
different reviewer.

## Evidence

| | result |
|---|---|
| the file | **120 tests, 4 failed** (was 28) |
| mutation: rename `.detail-id` in `TaskDetailModal` | **5 failed** |

The mutation matters because the change is "query a different root" —
the risk is assertions that now find *something* and stop
discriminating. They still observe the real component.

`pnpm lint` clean. Test-only; `TaskDetailModal.tsx` restored clean.

## The portal defect, totalled

| PR | file | cleared |
|---|---|---|
| #2885 | `TaskDetailModal.models-progress-workflow` | 30 |
| #2890 | `settings-mobile` | 17 |
| #2893 | `TaskDetailModal.definition-actions` | 12 |
| this | `TaskDetailModal.rendering` | 24 |

**83 of the ~111 backfill failures**, one defect: tests querying
`container` for components that render through a portal.

It hid for so long because `screen.*` queries in the same files always
worked — they query the document — so the failures read as *"the
component never rendered"* rather than *"we asked the wrong root"*. And
it was invisible to CI: the quality runner stops after the first failing
lane, and `app:app` failed ahead of every backfill shard.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-30 18:09:46 -07:00
committed by GitHub
parent 1dc839743e
commit b3e16b3988

View File

@@ -12,7 +12,7 @@ query ambiguous once the trigger stopped being a mobile-only affordance.
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { render, screen, fireEvent, act, waitFor } from "@testing-library/react";
import { render, screen, fireEvent, act, waitFor, cleanup } from "@testing-library/react";
// FNXC:Markdown 2026-06-23-03:30: Mock the heavy `mermaid` library so the shared
// markdown pipeline's MermaidDiagram resolves without loading the real renderer.
@@ -89,7 +89,7 @@ describe("TaskDetailModal", () => {
expect(badge).toHaveTextContent("Docs");
expect(badge.closest(".detail-timestamps")).toBeTruthy();
expect(badge.closest(".detail-title-row")).toBeNull();
expect(container.querySelector(".detail-title-row .detail-workflow-badge")).toBeNull();
expect(document.querySelector(".detail-title-row .detail-workflow-badge")).toBeNull();
expect(screen.getAllByTestId("task-detail-workflow-badge")).toHaveLength(1);
expect(screen.getByText("FN-101")).toBeInTheDocument();
expect(screen.getByText("Todo")).toBeInTheDocument();
@@ -179,7 +179,7 @@ describe("TaskDetailModal", () => {
await waitFor(() => expect(dashboardApi.fetchBoardWorkflows).toHaveBeenCalledTimes(1));
expect(screen.queryByTestId("task-detail-workflow-badge")).toBeNull();
expect(container.querySelector(".detail-workflow-badge")).toBeNull();
expect(document.querySelector(".detail-workflow-badge")).toBeNull();
});
it("renders the canonical badge beside the Updated timestamp in the mobile back-header variant", async () => {
@@ -200,14 +200,14 @@ describe("TaskDetailModal", () => {
);
const badge = await screen.findByTestId("task-detail-workflow-badge");
const timestamps = container.querySelector(".detail-timestamps");
const timestamps = document.querySelector(".detail-timestamps");
const updatedLabel = screen.getByText("Updated").closest(".detail-timestamp-item");
expect(badge).toHaveTextContent("Docs");
expect(badge.parentElement).toBe(timestamps);
expect(updatedLabel?.nextElementSibling).toBe(badge);
expect(screen.getAllByTestId("task-detail-workflow-badge")).toHaveLength(1);
expect(screen.queryByTestId("task-detail-workflow-badge-mobile")).toBeNull();
expect(container.querySelector(".detail-title-row .detail-workflow-badge")).toBeNull();
expect(document.querySelector(".detail-title-row .detail-workflow-badge")).toBeNull();
expect(screen.getByRole("button", { name: "Back to task list" })).toBeInTheDocument();
});
});
@@ -281,7 +281,7 @@ describe("TaskDetailModal", () => {
);
// Raw <details>/<summary> renders as a real disclosure element.
const details = container.querySelector(".markdown-body details");
const details = document.querySelector(".markdown-body details");
expect(details).not.toBeNull();
expect(details?.querySelector("summary")?.textContent).toBe("Disclosure title");
expect(details?.textContent).toContain("Hidden detail body.");
@@ -290,7 +290,7 @@ describe("TaskDetailModal", () => {
expect(container.textContent).not.toContain("secret comment");
// <script> is stripped by sanitize: not rendered and never executed.
expect(container.querySelector("script")).toBeNull();
expect(document.querySelector("script")).toBeNull();
expect((window as unknown as { __pwned?: boolean }).__pwned).toBeUndefined();
// ```mermaid fence renders the diagram container (lazy MermaidDiagram).
@@ -391,7 +391,7 @@ describe("TaskDetailModal", () => {
expect(provenance).toHaveTextContent("Created via GitHub Import");
expect(provenance?.textContent).not.toMatch(/[()]/);
expect(provenance?.querySelectorAll("a")).toHaveLength(1);
expect(container.querySelector(".detail-provenance-context")).toBeNull();
expect(document.querySelector(".detail-provenance-context")).toBeNull();
expect(issueLink).toHaveAttribute("href", "https://github.com/owner/repo/issues/42");
expect(issueLink).toHaveAttribute("target", "_blank");
@@ -442,7 +442,7 @@ describe("TaskDetailModal", () => {
const provenance = screen.getByText("Created via GitHub Import").closest(".detail-provenance");
expect(provenance?.textContent).toBe("Created via GitHub Import");
expect(provenance?.querySelector("a")).toBeNull();
expect(container.querySelector(".detail-provenance-context")).toBeNull();
expect(document.querySelector(".detail-provenance-context")).toBeNull();
};
assertPlainFallback();
@@ -658,7 +658,7 @@ describe("TaskDetailModal", () => {
/>,
);
expect(container.querySelector(".detail-undo-task-row")).toBeNull();
expect(document.querySelector(".detail-undo-task-row")).toBeNull();
});
it("picks the most recently created open undo task when multiple exist", async () => {
@@ -700,7 +700,7 @@ describe("TaskDetailModal", () => {
);
const provenance = screen.getByText("Created via Dashboard").closest(".detail-provenance");
const timestamps = container.querySelector(".detail-timestamps");
const timestamps = document.querySelector(".detail-timestamps");
expect(provenance).toBeTruthy();
expect(timestamps).toBeTruthy();
@@ -721,10 +721,10 @@ describe("TaskDetailModal", () => {
/>,
);
const meta = container.querySelector(".detail-meta");
const controls = container.querySelector(".detail-meta-inline-controls");
const meta = document.querySelector(".detail-meta");
const controls = document.querySelector(".detail-meta-inline-controls");
const provenance = screen.getByText(/Created via Refinement/).closest(".detail-provenance");
const timestamps = container.querySelector(".detail-timestamps");
const timestamps = document.querySelector(".detail-timestamps");
expect(meta).toBeTruthy();
expect(controls?.parentElement).toBe(meta);
@@ -749,11 +749,11 @@ describe("TaskDetailModal", () => {
/>,
);
const meta = container.querySelector(".detail-meta");
const controls = container.querySelector(".detail-meta-inline-controls");
const meta = document.querySelector(".detail-meta");
const controls = document.querySelector(".detail-meta-inline-controls");
const provenance = screen.getByText("Created via Dashboard").closest(".detail-provenance");
const prRow = container.querySelector(".detail-pr-link-row");
const timestamps = container.querySelector(".detail-timestamps");
const prRow = document.querySelector(".detail-pr-link-row");
const timestamps = document.querySelector(".detail-timestamps");
expect(meta).toBeTruthy();
expect(controls?.parentElement).toBe(meta);
@@ -1057,8 +1057,20 @@ describe("TaskDetailModal", () => {
/>,
);
expect(container.querySelector(".modal-overlay.open")).toBeTruthy();
expect(container.querySelector(".modal.modal-lg.task-detail-modal")).toBeTruthy();
/*
FNXC:TaskDetailModal 2026-07-30-22:50 (#2895 review — greptile, "obsolete modal overlay selector"):
THE SHELL IS `FloatingWindow`, NOT A `.modal-overlay`.
`TaskDetailModal` renders `<FloatingWindow modal>`, whose overlay class is
`floating-window-overlay--modal`. The only `.modal-overlay` left in this component is the refine
SUB-overlay at ~line 6801, which this case does not open — so the assertion was querying a class
that is never in the tree for the default render and failed outright.
Asserting the modal-ness (`--modal`), not just the overlay: a non-modal FloatingWindow renders the
same base class, so the bare selector would keep passing if the `modal` prop were dropped.
*/
expect(document.querySelector(".floating-window-overlay--modal")).toBeTruthy();
expect(document.querySelector(".modal.modal-lg.task-detail-modal")).toBeTruthy();
expect(screen.getByRole("button", { name: "Close" })).toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Back to task list" })).toBeNull();
});
@@ -1095,7 +1107,7 @@ describe("TaskDetailModal", () => {
/>,
);
expect(container.querySelector(".task-detail-content--embedded")).toBeTruthy();
expect(document.querySelector(".task-detail-content--embedded")).toBeTruthy();
expect(screen.queryByRole("button", { name: "Close" })).toBeNull();
expect(screen.getByRole("button", { name: "Plan" })).toBeInTheDocument();
});
@@ -1128,9 +1140,9 @@ describe("TaskDetailModal", () => {
expect(screen.queryByText(/isn't currently attached to a fusion branch/i)).not.toBeInTheDocument();
expect(screen.queryByText(/Reattached branch/i)).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: /Reattach branch/i })).not.toBeInTheDocument();
expect(container.querySelector(".rebind-banner")).toBeNull();
expect(container.querySelector(".rebind-banner-actions")).toBeNull();
expect(container.querySelector(".rebind-banner-result")).toBeNull();
expect(document.querySelector(".rebind-banner")).toBeNull();
expect(document.querySelector(".rebind-banner-actions")).toBeNull();
expect(document.querySelector(".rebind-banner-result")).toBeNull();
}
function renderTaskDetail(task: ReturnType<typeof makeTask>, mobileHeaderMode?: "back") {
@@ -1237,7 +1249,7 @@ describe("TaskDetailModal", () => {
/>,
);
const markdownDiv = container.querySelector(".markdown-body");
const markdownDiv = document.querySelector(".markdown-body");
expect(markdownDiv).toBeTruthy();
expect(markdownDiv!.classList.contains("detail-prompt")).toBe(false);
});
@@ -1257,8 +1269,8 @@ describe("TaskDetailModal", () => {
);
// The leading # heading should be stripped (modal has its own header)
expect(container.querySelector(".markdown-body h1")).toBeNull();
expect(container.querySelector("strong")?.textContent).toBe("bold");
expect(document.querySelector(".markdown-body h1")).toBeNull();
expect(document.querySelector("strong")?.textContent).toBe("bold");
});
it("renders (no prompt) with detail-prompt class when prompt is absent", () => {
@@ -1825,7 +1837,7 @@ describe("TaskDetailModal", () => {
const moveBtn = screen.getByRole("button", { name: "Move to Todo" });
expect(moveBtn).toBeTruthy();
const chevronZone = container.querySelector(".detail-move-btn__arrow");
const chevronZone = document.querySelector(".detail-move-btn__arrow");
expect(chevronZone).toBeTruthy();
fireEvent.keyDown(moveBtn, { key: "ArrowDown" });
@@ -1883,7 +1895,7 @@ describe("TaskDetailModal", () => {
const moveBtn = screen.getByRole("button", { name: "Move to In Review" });
expect(moveBtn).toBeTruthy();
const chevronZone = container.querySelector(".detail-move-btn__arrow");
const chevronZone = document.querySelector(".detail-move-btn__arrow");
expect(chevronZone).toBeTruthy();
await act(async () => {
@@ -1972,14 +1984,14 @@ describe("TaskDetailModal", () => {
);
// The heading "FN-099" should be stripped from the markdown
const markdownBody = container.querySelector(".markdown-body");
const markdownBody = document.querySelector(".markdown-body");
expect(markdownBody?.innerHTML).not.toContain("FN-099");
// Description appears in the markdown body
expect(markdownBody?.textContent).toContain("Fix the login bug");
// The detail header shows the ID (not duplicated as markdown heading)
expect(container.querySelector(".detail-id")?.textContent).toBe("FN-099");
expect(document.querySelector(".detail-id")?.textContent).toBe("FN-099");
// The h2 title shows description, not the task ID
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe("Fix the login bug");
});
@@ -2000,7 +2012,7 @@ describe("TaskDetailModal", () => {
/>,
);
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe("Implement dark mode");
});
@@ -2065,7 +2077,7 @@ describe("TaskDetailModal", () => {
description: "Triage planning context",
});
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe(longTitle);
expect(h2).toHaveClass("detail-title--collapsed");
const toggle = await screen.findByRole("button", { name: "Show more" });
@@ -2073,8 +2085,8 @@ describe("TaskDetailModal", () => {
await userEvent.click(toggle);
expect(container.querySelector("h2.detail-title")?.textContent).toBe(longTitle);
expect(container.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
expect(document.querySelector("h2.detail-title")?.textContent).toBe(longTitle);
expect(document.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
expect(screen.getByRole("button", { name: "Show less" })).toBeInTheDocument();
});
@@ -2086,36 +2098,44 @@ describe("TaskDetailModal", () => {
description: longDescription,
});
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe(longDescription);
expect(h2).toHaveClass("detail-title--collapsed");
expect(await screen.findByRole("button", { name: "Show more" })).toHaveClass("detail-description-toggle");
});
it("uses the title, description, and id fallback chain for the clamped heading", async () => {
const { container: withTitle } = renderDetail({
title: "Title wins",
description: "Description loses",
});
expect(withTitle.querySelector("h2.detail-title")?.textContent).toBe("Title wins");
expect(withTitle.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
/*
FNXC:TaskDetailModal 2026-07-30-23:20 (#2895 review — the portal defect, at the sites the reported
one did not cover):
CLEANUP BETWEEN RENDERS, NOT A WIDER SELECTOR.
These queried the render `container`, and the modal PORTALS out of it, so every one returned
null. The obvious repair — swap to `document.querySelector` — is wrong here and I watched it
fail: this case renders the modal THREE times, the portals accumulate on `document.body`, and a
document-wide query returns the FIRST one. The failure moved from "Title wins" to
"Description fallback" rather than going away.
Unmounting between renders makes the document unambiguous, so each assertion reads the render it
belongs to. That also matches what the case is actually testing — three independent fallback
inputs, not three coexisting modals.
*/
renderDetail({ title: "Title wins", description: "Description loses" });
expect(document.querySelector("h2.detail-title")?.textContent).toBe("Title wins");
expect(document.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
expect(await screen.findByRole("button", { name: "Show more" })).toBeInTheDocument();
cleanup();
setTitleLayout({ scrollHeight: 40, clientHeight: 40 });
const { container: withDescription } = renderDetail({
title: undefined,
description: "Description fallback",
});
expect(withDescription.querySelector("h2.detail-title")?.textContent).toBe("Description fallback");
expect(withDescription.querySelector(".detail-description-toggle")).toBeNull();
renderDetail({ title: undefined, description: "Description fallback" });
expect(document.querySelector("h2.detail-title")?.textContent).toBe("Description fallback");
expect(document.querySelector(".detail-description-toggle")).toBeNull();
cleanup();
const { container: withId } = renderDetail({
id: "FN-FALLBACK",
title: undefined,
description: undefined,
});
expect(withId.querySelector("h2.detail-title")?.textContent).toBe("FN-FALLBACK");
expect(withId.querySelector(".detail-description-toggle")).toBeNull();
renderDetail({ id: "FN-FALLBACK", title: undefined, description: undefined });
expect(document.querySelector("h2.detail-title")?.textContent).toBe("FN-FALLBACK");
expect(document.querySelector(".detail-description-toggle")).toBeNull();
});
it.each(["todo", "in-progress", "in-review", "done", "archived"] as const)(
@@ -2127,7 +2147,7 @@ describe("TaskDetailModal", () => {
title: longTitle,
});
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe(longTitle);
expect(h2).toHaveClass("detail-title--collapsed");
expect(await screen.findByRole("button", { name: "Show more" })).toBeInTheDocument();
@@ -2141,10 +2161,10 @@ describe("TaskDetailModal", () => {
description: "This is a longer description that is not shown as the heading while title is present",
});
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe("Short title");
expect(h2).toHaveClass("detail-title--collapsed");
expect(container.querySelector(".detail-description-toggle")).toBeNull();
expect(document.querySelector(".detail-description-toggle")).toBeNull();
});
it("collapses again when Show less is clicked", async () => {
@@ -2156,12 +2176,12 @@ describe("TaskDetailModal", () => {
const toggle = await screen.findByRole("button", { name: "Show more" });
await userEvent.click(toggle);
expect(container.querySelector("h2.detail-title")?.textContent).toBe(longDescription);
expect(container.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
expect(document.querySelector("h2.detail-title")?.textContent).toBe(longDescription);
expect(document.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
await userEvent.click(screen.getByRole("button", { name: "Show less" }));
const h2 = container.querySelector("h2.detail-title");
const h2 = document.querySelector("h2.detail-title");
expect(h2?.textContent).toBe(longDescription);
expect(h2).toHaveClass("detail-title--collapsed");
expect(screen.getByRole("button", { name: "Show more" })).toBeInTheDocument();
@@ -2189,7 +2209,7 @@ describe("TaskDetailModal", () => {
);
await userEvent.click(await screen.findByRole("button", { name: "Show more" }));
expect(container.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
expect(document.querySelector("h2.detail-title")).not.toHaveClass("detail-title--collapsed");
rerender(
<TaskDetailModal
@@ -2210,9 +2230,9 @@ describe("TaskDetailModal", () => {
);
await waitFor(() => {
expect(container.querySelector("h2.detail-title")?.textContent).toBe(triageDescription);
expect(document.querySelector("h2.detail-title")?.textContent).toBe(triageDescription);
});
expect(container.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
expect(document.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
expect(screen.getByRole("button", { name: "Show more" })).toBeInTheDocument();
});
@@ -2227,8 +2247,8 @@ describe("TaskDetailModal", () => {
expect(await screen.findByRole("button", { name: "Show more" })).toBeInTheDocument();
await userEvent.click(screen.getByRole("button", { name: "Edit task" }));
expect(container.querySelector("h2.detail-title")).toBeNull();
expect(container.querySelector(".detail-description-toggle")).toBeNull();
expect(document.querySelector("h2.detail-title")).toBeNull();
expect(document.querySelector(".detail-description-toggle")).toBeNull();
expect(screen.getByLabelText("Title")).toHaveValue(longTitle);
});
@@ -2239,7 +2259,7 @@ describe("TaskDetailModal", () => {
description: "Description available for summarization",
});
expect(container.querySelector(".detail-heading-row h2.detail-title--collapsed")).toBeInTheDocument();
expect(document.querySelector(".detail-heading-row h2.detail-title--collapsed")).toBeInTheDocument();
expect(screen.getByTestId("summarize-title-btn")).toBeInTheDocument();
expect(await screen.findByRole("button", { name: "Show more" })).toBeInTheDocument();
});
@@ -2263,8 +2283,8 @@ describe("TaskDetailModal", () => {
await userEvent.click(screen.getByRole("button", { name: "Expand activity to full modal" }));
expect(container.querySelector(".task-detail-content--chat-expanded")).toBeInTheDocument();
expect(container.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
expect(document.querySelector(".task-detail-content--chat-expanded")).toBeInTheDocument();
expect(document.querySelector("h2.detail-title")).toHaveClass("detail-title--collapsed");
expect(await screen.findByRole("button", { name: "Show more" })).toBeInTheDocument();
});
@@ -2280,7 +2300,7 @@ describe("TaskDetailModal", () => {
it("always shows task.id in the detail-id badge regardless of title", () => {
// With title
const { container: withTitle } = render(
render(
<TaskDetailModal
initialTab="definition"
task={makeTask({ title: "Some title" })}
@@ -2292,10 +2312,12 @@ describe("TaskDetailModal", () => {
addToast={noop}
/>,
);
expect(withTitle.querySelector(".detail-id")?.textContent).toBe("FN-099");
/* Portaled, and rendered twice — see the cleanup note on the clamped-heading case. */
expect(document.querySelector(".detail-id")?.textContent).toBe("FN-099");
cleanup();
// Without title
const { container: withoutTitle } = render(
render(
<TaskDetailModal
initialTab="definition"
task={makeTask({ title: undefined, description: "A description" })}
@@ -2307,7 +2329,7 @@ describe("TaskDetailModal", () => {
addToast={noop}
/>,
);
expect(withoutTitle.querySelector(".detail-id")?.textContent).toBe("FN-099");
expect(document.querySelector(".detail-id")?.textContent).toBe("FN-099");
});
describe("optimistic opening with Task", () => {
@@ -2356,8 +2378,8 @@ describe("TaskDetailModal", () => {
/>,
);
// Modal renders immediately without crashing
expect(container.querySelector(".modal-overlay")).toBeTruthy();
/* Same obsolete selector as the wrapper case: the shell is FloatingWindow, not `.modal-overlay`. */
expect(document.querySelector(".floating-window-overlay--modal")).toBeTruthy();
expect(screen.getByText("FN-200")).toBeDefined();
});
@@ -2558,7 +2580,7 @@ describe("TaskDetailModal", () => {
// After fetch resolves, spec content appears
await waitFor(() => {
const markdownBody = container.querySelector(".markdown-body");
const markdownBody = document.querySelector(".markdown-body");
expect(markdownBody).toBeTruthy();
}, { timeout: 3000 });
@@ -2580,8 +2602,8 @@ describe("TaskDetailModal", () => {
expect(screen.getByText((450).toLocaleString())).toBeInTheDocument();
expect(screen.getByText((210).toLocaleString())).toBeInTheDocument();
expect(screen.getByText((1860).toLocaleString())).toBeInTheDocument();
const firstUsed = container.querySelector('time[datetime="2026-04-24T09:00:00.000Z"]');
const lastUsed = container.querySelector('time[datetime="2026-04-24T10:15:00.000Z"]');
const firstUsed = document.querySelector('time[datetime="2026-04-24T09:00:00.000Z"]');
const lastUsed = document.querySelector('time[datetime="2026-04-24T10:15:00.000Z"]');
expect(firstUsed).toBeTruthy();
expect(lastUsed).toBeTruthy();
});
@@ -2630,15 +2652,15 @@ describe("TaskDetailModal", () => {
// Wait for fetchTaskDetail to resolve.
await waitFor(() => {
expect(container.querySelector(".markdown-body")).toBeTruthy();
expect(document.querySelector(".markdown-body")).toBeTruthy();
}, { timeout: 3000 });
fireEvent.click(screen.getByRole("button", { name: "Activity" }));
fireEvent.click(screen.getByRole("menuitem", { name: "Feed" }));
const activityList = container.querySelector(".detail-activity-list");
const activityList = document.querySelector(".detail-activity-list");
expect(activityList).toBeTruthy();
const logEntries = container.querySelectorAll(".detail-log-entry");
const logEntries = document.querySelectorAll(".detail-log-entry");
expect(logEntries).toHaveLength(2);
expect(logEntries[0].textContent).toContain("Started executor");
expect(logEntries[1].textContent).toContain("Created task");