fix(canvas/tests): pin Expand-to-Team absence with literal assertion

Multi-model review of #2862 caught a non-load-bearing assertion: the
test used \`expect(labels).not.toContain(expect.stringMatching(...))\`
to claim the "Expand to Team" right-click item is gone. But vitest's
toContain uses Object.is/===, so asymmetric matchers like
expect.stringMatching are plain objects that never === any string —
the assertion silently passed for ANY string array, including arrays
that DID contain "Expand to Team". The test would have green-lit the
unfixed code.

Switch to the literal substring shape the rest of this file already
uses (see lines 175/183/254 — labels.some((l) => l.includes(...))).

Verified the new assertion is load-bearing:

  1. Reintroduced \`{ label: "Expand to Team", ... }\` into the
     childless-workspace branch of ContextMenu.tsx
  2. Ran the test — failed at the new assertion line as expected
  3. Reverted the regression — test passes again

Net diff: replaces one broken expect with one correct expect + a
WHY-comment noting the toContain/asymmetric-matcher gotcha so the
next reader (or test writer) doesn't reintroduce the same shape.

Per memory feedback_assert_exact_not_substring.md: pin assertions
that fail on the old code path; this assertion never fired even on
the bug it was written to catch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hongming Wang 2026-05-05 03:05:17 -07:00
parent 25fd6b021d
commit 191ef3be91

View File

@ -240,7 +240,11 @@ describe("ContextMenu — keyboard accessibility", () => {
render(<ContextMenu />);
const items = screen.getAllByRole("menuitem");
const labels = items.map((el) => el.textContent?.trim() ?? "");
expect(labels).not.toContain(expect.stringMatching(/Expand to Team/));
// Literal absence — vitest's toContain uses Object.is/===, so the
// earlier `.not.toContain(expect.stringMatching(...))` shape passed
// for ANY string array (asymmetric matchers only work with toEqual /
// arrayContaining). Pin the production string verbatim.
expect(labels.some((l) => l.includes("Expand to Team"))).toBe(false);
// Sanity: childless menu still has the regular actions.
expect(labels.some((l) => l.includes("Delete"))).toBe(true);
expect(labels.some((l) => l.includes("Restart"))).toBe(true);