Skip to content

test(e2e): Playwright key-flow suite + frontend self-check batch#11

Merged
Algebraaaa merged 9 commits into
masterfrom
feat/playwright-e2e
Jul 13, 2026
Merged

test(e2e): Playwright key-flow suite + frontend self-check batch#11
Algebraaaa merged 9 commits into
masterfrom
feat/playwright-e2e

Conversation

@Algebraaaa

Copy link
Copy Markdown
Owner

What

Adds an end-to-end test layer and bundles the outstanding frontend self-check work that was sitting unpushed on master.

Headline change (9d855d3):

  • Playwright E2E suitee2e/smoke.spec.js covering key user flows, playwright.config.js.
  • CI job wiring the suite into .github/workflows/ci.yml.
  • .gitignore entries for Playwright artifacts (test-results/, playwright-report/, blob-report/, .playwright/).
  • Playwright dev dependency in package.json / package-lock.json.
  • Doc updates in CONTRIBUTING.md and docs/FRONTEND_SELF_CHECK.md.

Why

Closes the last gap in the frontend self-check series (#4 → green): the visualization key-flows had only mount/smoke coverage; this drives them end-to-end in CI.

Reviewer notes

🤖 Generated with Claude Code

RadixSortPlayground sets positiveOnly={false}, so users can type
negative numbers into the custom-input box. radixSort then crashed:
Math.floor(v/exp)%10 yields a negative bucket index for v<0, so
buckets[negative] is undefined and .push throws — the ErrorBoundary
fallback ("该模块加载失败") replaced the whole visualization. A second
mode: an all-negative array made maxVal<0 → Math.log10 → NaN → maxDigits
NaN → the distribute loop never ran, silently returning the input
unsorted.

Fix: shift every value by offset = max(0, -min) so bucketing runs on
non-negative values (shifting is monotonic, preserving order), while
buckets still store and display the original values. When the input is
already non-negative offset is 0, so behavior — and all presets/classic
examples — are byte-identical to before.

Found via a throwaway render+step smoke over all 123 algorithms plus an
edge-input correctness sweep (empty/single/dupes/reverse/negatives).
Only radixsort was user-reachable-broken (countingsort mishandles
negatives too but its playground keeps positiveOnly=true, filtering
them at input). New radixSort.test.js locks it: negatives, all-negative,
zero, 50 random signed arrays. Verified end-to-end in a real browser:
'-3 1 -1 0 2 -5' now sorts to -5,-3,-1,0,1,2 with no crash. 203 tests.
Add a subtle GitHub-linked attribution badge (github.com/roclee2692)
to the AI course hero's top-right corner, since that module was
contributed by them. External link opens in a new tab with
rel=noreferrer noopener.
…#1/#4)

Turns the throwaway bug-hunt that found the radix crash into permanent
regression guards, closing the exact coverage holes that let it hide:
- src/test/setup.js: polyfill scrollIntoView/scrollTo/ResizeObserver
  (jsdom lacks them; without these a step-through test throws before
  reaching real interaction paths)
- algorithmSmoke.test.jsx: render every one of the 123 algorithms and
  step through — catches crashes the old typeof-fn checks never could
- sortingCorrectness.test.js: every sort on its actual input domain
  asserts sorted + length-preserved — would have caught the radix bug

203 -> 403 tests.
compare/swap/sorted were distinguished only by yellow/red/green — red-
green colorblind users can't tell swap from sorted. Add a redundant
shape channel: Legend gains optional per-item symbol (compare / swap /
sorted glyphs, backward-compatible), SortingViz pointer row uses distinct
glyphs per state and marks sorted labels — legible even in grayscale.
- jsconfig.json: step 1 of type-safety migration — editor cross-file nav,
  autocomplete, JSDoc hints. checkJs stays false (flipping it floods an
  unannotated codebase); path: JSDoc on data/ -> checkJs -> TypeScript.
- docs/FRONTEND_SELF_CHECK.md: reusable 12-dimension industrial-grade
  checklist scored against this project + paste-ready red-team prompt.
Upgrades type safety from editor-only jsconfig to enforced checking:
typescript devDep + tsconfig.typecheck.json (checkJs on a curated,
currently-passing include list) + npm run typecheck (folded into
npm run check) + a Typecheck step in CI. The include set is 8 pure-logic
modules and grows over time (strangler-fig adoption).

Wiring checkJs up surfaced and fixed real gaps: import.meta.env lacked
Vite types (add src/vite-env.d.ts), SyncService options had no JSDoc,
stepProtocol accessed props on {object}, hoverStyle used undefined
CSSProperties + a stray em-dash, supabase.js set a non-standard window
flag. npm ci stays in sync; 405 tests + build green.
CONTRIBUTING.md documents the quality gate (lint/typecheck/test/build +
CI), conventions, and how to add an algorithm. docConsistency.test.js
scans living Markdown for backtick-wrapped repo paths and asserts they
exist — it immediately caught two real drifts, now fixed: AGENTS.md
referenced a gone supabase/functions path, FRONTEND_SELF_CHECK had the
wrong algorithmSmoke.test.jsx path. Archives (*_REPORT/CHANGELOG) are
excluded as point-in-time snapshots.
Extends the color-blind-safe pattern from sorting viz to the two other
main viz families:
- GraphViz: unvisited nodes get a dashed border (a 'pending' shape cue),
  visited/current stay solid — visited vs unvisited no longer relies on
  fill color alone (WCAG 1.4.1).
- SvgTreeViz: red-black nodes carry an R/B letter badge — red-vs-dark-gray
  is a pure-color semantic that red-green colorblind users can't parse.
- SvgCanvas gains an ariaLabel prop → role=img + aria-label; graph and
  tree viz emit a live state summary (e.g. '当前访问节点 A,已访问 2 个')
  so screen readers get a description instead of an opaque SVG.

Pattern is now reusable (SvgCanvas.ariaLabel + strategy badge) for the
remaining long-tail viz. Verified in browser: RB tree shows R/B badges +
aria; BFS shows 5 dashed unvisited / 2 solid visited + dynamic aria.
405 tests, typecheck, lint green.
Adds the E2E layer jsdom can't cover — real Chromium, real routing,
real persistence:
- playwright.config.js (testDir e2e/, auto webServer on 5173, chromium)
- e2e/smoke.spec.js: home loads, algorithm step-through changes the
  STEP description, theme toggle flips data-theme, and favorite
  persists across a reload + lands in localStorage.
- npm run test:e2e; a separate CI job installs the browser and runs it
  (kept off the fast lint/typecheck/test/build job so it doesn't slow
  the main gate).
- .gitignore ignores Playwright artifacts.

All 4 flows pass locally against a real dev server. Self-check doc: #4
→ green; scorecard now 12/12 green (green = a gate guards the line,
not that the work is finished — TS migration, more E2E, long-tail a11y
remain as incremental).
Copilot AI review requested due to automatic review settings July 13, 2026 14:11
@vercel

vercel Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cshub Ready Ready Preview, Comment Jul 13, 2026 2:11pm

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Playwright-based end-to-end (E2E) “key flow” smoke suite and wires it into CI, while also bundling several frontend self-check improvements (typecheck gate, stronger JS/DOM test stability, accessibility cues, and correctness regressions) to harden the app’s critical visualization and learning flows.

Changes:

  • Add Playwright E2E smoke tests + config, and run them in CI as a separate job.
  • Add a progressive tsc checkJs “typecheck subset” (script + config) and include it in npm run check and CI.
  • Strengthen frontend self-check coverage: radixSort negative-number fix + regression tests, doc drift guard, and multiple a11y improvements (non-color cues + aria summaries).

Reviewed changes

Copilot reviewed 26 out of 29 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tsconfig.typecheck.json Adds a dedicated tsc project for progressive checkJs typechecking on a curated JS subset.
src/vite-env.d.ts Adds Vite client type reference for typechecking.
src/utils/stepProtocol.js Tightens JSDoc types for step parsing parameters.
src/utils/hoverStyle.js Adjusts JSDoc types for hover style helpers.
src/test/setup.js Adds jsdom polyfills (scroll APIs + ResizeObserver) to unblock interaction-path tests.
src/styles/vizTokens.js Extends sorting legend items with non-color symbols.
src/services/storage/SyncService.js Adds JSDoc typing for DI-style deps in sync service creation.
src/pages/AIPage.jsx Adds an AI module contributor credit badge in the hero section.
src/lib/supabase.js Avoids writing non-standard window.* properties without an explicit any cast.
src/data/sortingCorrectness.test.js Adds sorting correctness regression tests across supported input domains.
src/data/docConsistency.test.js Adds a Markdown “doc drift” guard ensuring referenced repo paths exist.
src/data/algorithmSmoke.test.jsx Adds a full-playground render + step-through smoke guard for all algorithms.
src/components/svg/SvgTreeViz.jsx Adds RB-tree non-color badge cue + forwards aria labeling to the canvas.
src/components/svg/SvgCanvas.jsx Adds optional ariaLabelrole="img" + aria-label support for SVG canvases.
src/components/SortingViz.jsx Adds non-color glyph cues for compare/swap and a completion marker in the index row.
src/components/playgrounds/shared.jsx Enhances Legend to optionally render a symbol channel for a11y.
src/components/GraphViz.jsx Adds aria summary label + dashed outline cue for unvisited nodes.
src/algorithms/sorting/radixSort.test.js Adds radixSort regression tests including negative inputs.
src/algorithms/sorting/radixSort.js Fixes radixSort for negative numbers via monotonic offset shifting.
playwright.config.js Adds Playwright config with a Vite dev-server webServer integration.
package.json Adds typecheck + test:e2e scripts and Playwright/TypeScript dev dependencies; updates check.
package-lock.json Updates lockfile for new dev dependencies (Playwright + TypeScript).
jsconfig.json Adds JS project config for editor navigation + gradual typing migration.
e2e/smoke.spec.js Adds E2E smoke coverage for home, stepping, theme toggle, and favorite persistence.
docs/FRONTEND_SELF_CHECK.md Documents the self-check dimensions and newly added test/typecheck gates.
CONTRIBUTING.md Documents local dev, quality gates, and the typecheck/E2E workflows.
AGENTS.md Updates referenced Supabase documentation/schema pointers.
.gitignore Ignores Playwright artifact directories.
.github/workflows/ci.yml Adds typecheck step and a separate E2E job that installs browsers and runs Playwright.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread e2e/smoke.spec.js
// 若已是"已收藏"(历史状态),先取消,回到干净起点
if ((await favBtn.textContent())?.includes('已收藏')) {
await favBtn.click()
await expect(favBtn).toHaveText(/^收藏|收藏$/)
Comment on lines +18 to +21
if (st.isDirectory()) {
// 只递归 docs/ 与根;避免扫进 src 里的注释
if (full === path.join(ROOT, 'docs')) collectMarkdown(full, acc)
} else if (name.endsWith('.md')) {

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d855d368e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +14 to +15
const offset = minVal < 0 ? -minVal : 0
const shifted = (v) => v + offset

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update radix lesson snippets for negatives

With this offset path, the playground now accepts and correctly visualizes negative arrays, but the algorithm page still shows pseudocode/C++/Python in src/data/algorithms/sorting.js that buckets on raw v and uses raw maxVal. For inputs such as -3 1 -1, users see the visualization succeed while the displayed C++ can index negative buckets and the Python ordering is different, so the teaching snippets/pseudocode should either use the same offset or the UI should keep rejecting negatives.

Useful? React with 👍 / 👎.

@Algebraaaa
Algebraaaa merged commit 65dc4f2 into master Jul 13, 2026
3 checks passed
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.

2 participants