Skip to content

test(configurator): CI-gated unit + e2e regression suites, UX/a11y polish - #313

Merged
jackgranatowski merged 4 commits into
mainfrom
claude/configurator-e2e-hardening
Jun 12, 2026
Merged

test(configurator): CI-gated unit + e2e regression suites, UX/a11y polish#313
jackgranatowski merged 4 commits into
mainfrom
claude/configurator-e2e-hardening

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Hardening follow-up to #311/#312 (both merged): the QA sweeps that found the recent configurator bugs ran on throwaway Playwright specs, and — more importantly — the configurator's 346-test unit suite (the whole sync-tripwire net) was never executed by any CI workflow. This PR makes both permanent, then ships the UX/a11y polish batch.

CI + permanent e2e suite

  • New configurator/tests-e2e/ Playwright suite (33 tests, chromium) pinning every behavior verified during the QA sweeps: shell guards & keyboard cycling, preview pane/overlay/resize round-trip, scalar-only generator writes with shared-viewport seeding, preset semantics (no cross-preset leftovers, single-undo), the garbage-import byte-exact no-op guard, hostile-input sanitisation, corrupt-storage boot, horizontal-overflow audit at 5 widths, aria state, and a 5-step mixed undo/redo chain replayed byte-for-byte. npm run test:e2e prebuilds; Playwright manages the preview server via webServer.
  • New CI job Configurator tests: configurator unit suite (npm test), svelte-check as a type gate, and the e2e suite — on every push/PR.
  • svelte-check baseline cleared to 0 errors / 0 warnings (intentional state capture annotated, diff cells rewrapped for role="cell", standard line-clamp added).

UX / a11y polish (follow-up commits on this PR)

  • Escape dismisses the preview overlay; focus moves to its close button on open and returns to the toggle on close
  • UI prefs (mode / domain / output format) persist across reloads with validated restore
  • index.html: theme-color, SVG favicon, OG/Twitter meta
  • Cleanups deferred from the review: shared clipboard helper (3 implementations → 1), DomainPanel card-header snippet (4 duplicates → 1), dead ?? d.blurb fallback removed

Testing

  • cd configurator && npm test — 346/346
  • npm run check — 0 errors / 0 warnings
  • npm run test:e2e — 33/33
  • CI: new job green on this PR

https://claude.ai/code/session_01DCCWK2EPSRdhBDZ7f25NxT


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Standardized CSS line-clamping across components for consistent text truncation
    • Improved accessibility markup in diff display with proper semantic roles
  • Tests

    • Added comprehensive end-to-end test suite covering accessibility, functionality, import/export, presets, preview behavior, navigation, and undo/redo workflows
  • Chores

    • Enhanced CI/CD pipeline with automated configurator-specific testing and Playwright E2E execution

claude added 2 commits June 11, 2026 23:54
The QA sweeps that found the recent configurator bugs ran on throwaway
specs — none of those findings had lasting coverage. This adds a
permanent chromium suite (configurator/tests-e2e, 33 tests) pinning:

- shell: Home landing, per-mode sidebar, mode/domain guards, keyboard
  cycling, console-clean on every route at 1600/1000/480px
- preview: desktop pane toggle, narrow-viewport slide-over (scrim,
  in-bar theme/motion/close controls), the matchMedia resize
  round-trip, live repaint on brand-color edits
- generators: scalar-only writes (no baked clamp() steps), shared
  viewport seeding across ramps, resets, garbage-proof edge inputs
- presets/knobs: default detection, no cross-preset leftovers,
  single-undo semantics, shadow-strength encode/decode round-trip
- import/export: layer//root round-trip and the garbage-import guard
  (byte-exact no-op), hostile-input sanitisation, corrupt-storage boot
- a11y: horizontal-overflow audit at 5 widths, accessible names,
  aria-pressed/aria-expanded state, search scoping affordance
- history: 5-step mixed chain unwinds and replays byte-for-byte

npm run test:e2e builds and lets Playwright manage the preview server
(webServer). Also clears the svelte-check baseline to 0 errors /
0 warnings so it can become a CI gate: intentional state capture in
ScaleGenerator annotated, diff cells rewrapped (role=cell on spans),
standard line-clamp added alongside the -webkit- prefix.

https://claude.ai/code/session_01DCCWK2EPSRdhBDZ7f25NxT
The configurator's 346 node:test sync-tripwire tests (and svelte-check)
were only ever run locally — no workflow executed them, so a framework
token rename could land green while breaking the configurator. New
'Configurator tests' job runs the unit suite, svelte-check (now at
0 errors / 0 warnings) and the chromium e2e regression suite on every
push/PR.

https://claude.ai/code/session_01DCCWK2EPSRdhBDZ7f25NxT
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 32 minutes and 21 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b90dae4a-2e97-476b-bbfb-a45bf1416a4d

📥 Commits

Reviewing files that changed from the base of the PR and between 2f77d05 and f58a8e6.

📒 Files selected for processing (17)
  • configurator/index.html
  • configurator/src/App.svelte
  • configurator/src/components/Cheatsheet.svelte
  • configurator/src/components/DomainPanel.svelte
  • configurator/src/components/Home.svelte
  • configurator/src/components/OutputPanel.svelte
  • configurator/src/components/Preview.svelte
  • configurator/src/components/TokenRow.svelte
  • configurator/src/lib/clipboard.js
  • configurator/src/lib/store.svelte.js
  • configurator/src/lib/uiState.js
  • configurator/tests-e2e/generator.spec.js
  • configurator/tests-e2e/helpers.js
  • configurator/tests-e2e/preview.spec.js
  • configurator/tests-e2e/shell.spec.js
  • configurator/tests-e2e/undo-redo.spec.js
  • configurator/tests/ui-state.test.js
📝 Walkthrough

Walkthrough

This PR introduces comprehensive end-to-end test coverage for the configurator using Playwright. It adds test infrastructure (CI job, config, helpers), reusable test utilities, and seven test suites covering shell navigation, presets, generators, preview UI, undo/redo, import/export, and accessibility. Minor component improvements include CSS line-clamp updates and OutputPanel accessibility markup.

Changes

Configurator E2E Test Suite

Layer / File(s) Summary
Test infrastructure and helpers
.github/workflows/ci.yml, configurator/package.json, configurator/playwright.config.js, configurator/tests-e2e/helpers.js
Playwright config with test directory, timeouts, worker/retry rules, and preview server management. CI workflow job runs npm test/check and npm run test:e2e with Chromium. Package.json adds test:e2e and pretest:e2e scripts plus @playwright/test dev dependency. Helper utilities provide error watching, clean navigation with localStorage reset, sidebar item location, and override persistence reading via STORAGE_KEY.
Shell and navigation tests
configurator/tests-e2e/shell.spec.js
End-to-end tests verify Home landing and setup checklist state, console-clean navigation through sidebar destinations across three viewport widths in both basic and advanced modes, mode guard behavior between Home and Colors, keyboard [/] cycling of domains with wrap-around, and rapid mode toggling stability.
Preset and generator feature tests
configurator/tests-e2e/presets.spec.js, configurator/tests-e2e/generator.spec.js
Preset tests validate border/shadow preset activation, Pill radius override, preset switching with cleanup, manual editing deselecting presets, and power knobs isolated to Advanced mode with dark-mode calc encoding. Generator tests ensure scalar-only CSS output, viewport range inheritance across tabs, Reset controls clearing overrides, and valid edge-case persisted values.
Preview UI and state management tests
configurator/tests-e2e/preview.spec.js, configurator/tests-e2e/undo-redo.spec.js
Preview tests cover desktop default visibility, toggle behavior, narrow-viewport fixed overlay with scrim dismissal, overlay controls (theme, reduced-motion, close), resize round-trip restoration, and live preview repainting on color edits. Undo/redo tests validate five-step mixed operation snapshots with byte-exact JSON comparison for each undo/redo keystroke and override persistence across page reload.
Import/export, accessibility, and component polish
configurator/tests-e2e/import-export.spec.js, configurator/tests-e2e/a11y.spec.js, configurator/src/components/Cheatsheet.svelte, configurator/src/components/Home.svelte, configurator/src/components/OutputPanel.svelte, configurator/src/components/ScaleGenerator.svelte
Import/export tests verify CSS round-trip in layer mode, garbage-import safety, output format toggle reshaping, input sanitization stripping structural characters, and localStorage resilience with invalid/malformed JSON. Accessibility tests assert near-zero horizontal overflow across viewport widths, all buttons have accessible names, segmented-control aria-pressed counts, popover aria-expanded toggle, and search scoping with error-free navigation. Component improvements: line-clamp: 2 CSS added to Cheatsheet and Home for standard browser support, OutputPanel diff cells use semantic span with role="cell" wrapping code, and ScaleGenerator lint suppression added.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • codeslash-dev/SLASHED#312: New preview.spec.js directly tests narrow-viewport overlay and scrim behaviors implemented in PR #312.
  • codeslash-dev/SLASHED#302: New E2E suite exercises tabbed Basic/Advanced UI and header preview/theme behaviors introduced in PR #302.
  • codeslash-dev/SLASHED#303: E2E tests and OutputPanel changes validate redesigned UI/state for sidebar, header, preview, undo, and presets from PR #303.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding CI-gated unit and e2e regression test suites plus UX/a11y improvements to the configurator.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/configurator-e2e-hardening

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 and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 3

🧹 Nitpick comments (1)
configurator/tests-e2e/shell.spec.js (1)

61-67: ⚡ Quick win

Strengthen the rapid-toggle assertion to validate the selected domain, not just uniqueness.

Checking only toHaveCount(1) can miss domain corruption where a wrong item is still active. Assert the active label remains expected after toggling.

Proposed fix
 test('rapid mode toggling never corrupts the active domain', async ({ page }) => {
   const errors = watchErrors(page);
   await gotoClean(page);
   await sideItem(page, 'Borders').click();
   for (let i = 0; i < 10; i++) await page.keyboard.press(i % 2 ? 'b' : 'a');
-  await expect(page.locator('.side__item.side__item--on')).toHaveCount(1);
+  const active = page.locator('.side__item.side__item--on');
+  await expect(active).toHaveCount(1);
+  await expect(active).toContainText('Borders');
   expect(errors).toEqual([]);
 });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@configurator/tests-e2e/shell.spec.js` around lines 61 - 67, After rapid
toggling, the test currently only asserts a single active side item via the
selector '.side__item.side__item--on' which can miss domain corruption; update
the assertion to also verify that the active item's label remains the expected
domain (the one clicked earlier, e.g. 'Borders'). Locate the active element (via
page.locator('.side__item.side__item--on') or by reusing sideItem helper) and
assert its text/content equals 'Borders' (or the expected label) in addition to
ensuring count is 1, keeping the existing watchErrors, gotoClean, and toggle
loop intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@configurator/tests-e2e/generator.spec.js`:
- Line 72: The current test assertion in generator.spec.js uses a regex
(/^$|NaN|undefined|null/) that can match substrings; replace it with an anchored
full-string alternation so it only matches entire garbage values. Locate the
expect(...) line in generator.spec.js and change the regex to an anchored
non-capturing group (e.g., /^(?:|NaN|undefined|null)$/) so the .not.toMatch
check rejects exactly empty, "NaN", "undefined", or "null" and not substrings of
valid values.

In `@configurator/tests-e2e/helpers.js`:
- Around line 33-37: The helper readOverrides throws on malformed JSON from
localStorage; update readOverrides to mirror the app's tolerant loader by
wrapping the JSON.parse of localStorage.getItem(STORAGE_KEY) in a try/catch (or
otherwise detect parse errors) and return an empty object {} when parsing fails
or the stored value is invalid, ensuring the function always resolves to a plain
object instead of propagating a SyntaxError.

In `@configurator/tests-e2e/undo-redo.spec.js`:
- Around line 11-53: The test currently uses JSON.stringify(await
readOverrides(page)) which is order-dependent; replace those raw
stringifications with a canonicalized snapshot (e.g., a helper like
canonicalize(obj) that recursively sorts object keys and then JSON.stringify)
and call it wherever you push snapshots and in the undo/redo expect checks
(references: snapshots array, readOverrides(page), the pushes after each action,
and the expect comparisons inside the undo/redo loops). Ensure canonicalize is
used both when building snapshots and when comparing after undo/redo so key
order differences cannot cause flakes.

---

Nitpick comments:
In `@configurator/tests-e2e/shell.spec.js`:
- Around line 61-67: After rapid toggling, the test currently only asserts a
single active side item via the selector '.side__item.side__item--on' which can
miss domain corruption; update the assertion to also verify that the active
item's label remains the expected domain (the one clicked earlier, e.g.
'Borders'). Locate the active element (via
page.locator('.side__item.side__item--on') or by reusing sideItem helper) and
assert its text/content equals 'Borders' (or the expected label) in addition to
ensuring count is 1, keeping the existing watchErrors, gotoClean, and toggle
loop intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2962ce09-9111-4938-b297-fca5010239fe

📥 Commits

Reviewing files that changed from the base of the PR and between 7bc1363 and 2f77d05.

⛔ Files ignored due to path filters (1)
  • configurator/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • .github/workflows/ci.yml
  • configurator/package.json
  • configurator/playwright.config.js
  • configurator/src/components/Cheatsheet.svelte
  • configurator/src/components/Home.svelte
  • configurator/src/components/OutputPanel.svelte
  • configurator/src/components/ScaleGenerator.svelte
  • configurator/tests-e2e/a11y.spec.js
  • configurator/tests-e2e/generator.spec.js
  • configurator/tests-e2e/helpers.js
  • configurator/tests-e2e/import-export.spec.js
  • configurator/tests-e2e/presets.spec.js
  • configurator/tests-e2e/preview.spec.js
  • configurator/tests-e2e/shell.spec.js
  • configurator/tests-e2e/undo-redo.spec.js

Comment thread configurator/tests-e2e/generator.spec.js Outdated
Comment thread configurator/tests-e2e/helpers.js
Comment thread configurator/tests-e2e/undo-redo.spec.js Outdated
claude added 2 commits June 12, 2026 00:00
…meta

- Escape dismisses the slide-over preview overlay (narrow viewports
  only; the desktop pane is a layout region, not a dialog); on open the
  overlay focuses its close button and returns focus to the header
  toggle when it unmounts
- Navigation prefs (mode / domain / output format) persist across
  reloads via a new validated localStorage slot — lib/uiState.js keeps
  the validator pure and unit-tested (invalid domains for the saved
  mode are dropped before they can flash a redirect)
- index.html gains theme-color, an inline SVG favicon and basic
  OG/Twitter meta for sharing the public tool
- cleanups deferred from the QA review: shared lib/clipboard.js
  replaces three divergent copy implementations (unified 1400ms
  feedback), DomainPanel card headers collapse into one snippet
  (4 duplicates -> 1), Home rows always show the intended copy
  (intro for domains, blurb for tools)
- e2e suite extended to 36 tests (escape/focus behavior, persisted
  prefs incl. corrupt-slot fallback); unit suite to 352

https://claude.ai/code/session_01DCCWK2EPSRdhBDZ7f25NxT
- helpers.readOverrides tolerates malformed persisted JSON (mirrors the
  app's loader) so corrupt-storage scenarios fail on app behavior, not
  helper parsing
- undo/redo snapshots canonicalised via stableSnapshot (sorted keys) —
  byte-for-byte comparisons no longer depend on key insertion order
- garbage-value regex anchored to full-string matches
- rapid-toggle test also asserts the active domain stays Borders

https://claude.ai/code/session_01DCCWK2EPSRdhBDZ7f25NxT
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