Skip to content

fix(graph): root-cause flaky Pixi canvas race; scope Mermaid e2e locators#140

Merged
helebest merged 1 commit into
mainfrom
fix/flaky-e2e-graph-mermaid
Jun 29, 2026
Merged

fix(graph): root-cause flaky Pixi canvas race; scope Mermaid e2e locators#140
helebest merged 1 commit into
mainfrom
fix/flaky-e2e-graph-mermaid

Conversation

@helebest

@helebest helebest commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What

Fixes the two documented flaky e2e tests at the source instead of leaning on CI retries.

1. graph.spec.ts > renders a nonblank Pixi graph canvas (the primary documented flake)

Root cause is a real StrictMode-only race in GraphCanvas, not test timing:

  • React StrictMode's dev double-invoke runs two createPixiGraphEngine() inits concurrently.
  • The canvas was attached via mount.replaceChildren(app.canvas) inside the async factory, i.e. outside the effect's active guard.
  • If the discarded stale init resolved after the live one, its replaceChildren clobbered the live canvas, and its subsequent destroy() then emptied the mount entirely — leaving data-ready="true" over a canvas-less stage. The one-shot page.evaluate then threw Graph Pixi stage was not rendered.
  • This was reproducible locally on a cold dev server (wide async-init window); retries: 2 masked it on CI but [occasionally still lost all 3 attempts].

Fix: GraphCanvas attaches the canvas only inside the active guard (the engine now exposes a canvas getter); the discarded init never touches the DOM. Production rendering is unchanged — no StrictMode double-invoke there, so it's a single attach as before. The spec additionally gates on data-render-count >= 1 (the reliable signal its sibling test already uses) before reading the canvas contract.

2. wiki.spec.ts + theme.spec.ts Mermaid disclosure clicks

A bare getByText("flowchart") also matched the <style> Mermaid injects (its CSS mentions flowchart). Confirmed empirically: once a diagram has rendered, the locator resolves to 2 nodes (summary + style) → .click() throws a Playwright strict-mode violation. Both specs now scope to the <summary> element (locator("summary", { hasText: "flowchart" })), which resolves to exactly 1.

The playwright.config.ts retries comment is updated (retries kept as a general backstop, no longer the primary mitigation for this test).

Verification

  • graph.spec.ts 6/6 consecutive passes + a cold-start full run green (it reproducibly failed before the fix).
  • Full e2e suite: 57 passed / 2 skipped (matches baseline).
  • vitest: 910 passed (72 files); tsc --noEmit clean; ESLint clean; Prettier clean.

Notes

  • package.json bumped 0.8.5 → 0.8.6; CHANGELOG.md entry added.
  • Change is test-infra + a contained dev-only component robustness fix; no user-facing behavior change.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where the graph canvas could appear empty even after loading completed.
    • Improved end-to-end test reliability for Mermaid diagrams by using more specific element targeting.
    • Added an extra readiness check so graph tests wait until rendering has actually occurred.
  • Chores

    • Bumped the app version to 0.8.6.
    • Updated release notes and CI comments to reflect the latest fixes.

…tors

Two documented flaky e2e tests, fixed at the source rather than absorbed
by CI retries.

graph.spec.ts "renders a nonblank Pixi graph canvas": under React
StrictMode's dev double-invoke the graph runs two createPixiGraphEngine()
inits concurrently. The canvas was attached via mount.replaceChildren()
inside the async factory — outside the effect's `active` guard — so a
slower-resolving stale init could clobber the live engine's canvas and then
empty the mount when its destroy() fired, leaving data-ready="true" over a
canvas-less stage. GraphCanvas now attaches the canvas only inside the
active guard (engine exposes a `canvas` getter); the discarded init never
touches the DOM. Production rendering is unchanged (no StrictMode there →
single attach). The spec also gates on data-render-count >= 1 before reading
the canvas contract.

wiki.spec.ts + theme.spec.ts Mermaid disclosure clicks: a bare
getByText("flowchart") also matched the <style> Mermaid injects (CSS that
mentions "flowchart"), so once a diagram had rendered the locator resolved to
two nodes and .click() threw a strict-mode violation. Both specs now scope to
the <summary> element.

Verified: graph.spec 6/6 + cold-start green (reproducibly failed before),
full e2e 57 passed / 2 skipped, vitest 910 passed, typecheck + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b05508f3-9abd-4448-aaaf-960f519a7144

📥 Commits

Reviewing files that changed from the base of the PR and between 86c429f and a16565a.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • package.json
  • playwright.config.ts
  • src/components/GraphCanvas.tsx
  • tests/e2e/graph.spec.ts
  • tests/e2e/theme.spec.ts
  • tests/e2e/wiki.spec.ts

📝 Walkthrough

Walkthrough

Version bumped to 0.8.6 with two fixes: GraphCanvas defers Pixi canvas DOM mounting into the async active-guard to prevent React StrictMode double-invoke from leaving an empty canvas, and Mermaid e2e tests scope "flowchart" clicks to <summary> elements to avoid strict-mode locator violations.

Changes

Pixi StrictMode race fix and Mermaid locator scoping

Layer / File(s) Summary
GraphCanvas StrictMode race fix
src/components/GraphCanvas.tsx, tests/e2e/graph.spec.ts
PixiEngine interface adds readonly canvas: HTMLCanvasElement; PixiGraphEngine implements a canvas getter; createPixiGraphEngine removes its direct mount.replaceChildren call; GraphCanvas calls mount.replaceChildren(engine.canvas) inside the active guard. The e2e test switches readiness gating to poll data-render-count ≥ 1.
Mermaid locator scoping, config, and release metadata
tests/e2e/theme.spec.ts, tests/e2e/wiki.spec.ts, playwright.config.ts, package.json, CHANGELOG.md
Mermaid flowchart clicks scoped to locator("summary", { hasText: "flowchart" }) in both spec files. Playwright retries comment updated to reflect the Pixi fix. Version bumped to 0.8.6 with changelog entry.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A canvas once blank in the React double-dance,
Now mounts in the guard — given only one chance!
The flowchart once fooled by Mermaid's CSS spell,
Now clicks the right <summary> — all is well!
Hop hop, 0.8.6, fixed and set free! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main changes: fixing the Pixi canvas race and scoping Mermaid e2e locators.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/flaky-e2e-graph-mermaid

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@helebest helebest merged commit 3091af2 into main Jun 29, 2026
9 checks passed
@helebest helebest deleted the fix/flaky-e2e-graph-mermaid branch June 29, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant