@marianmeres/stuic 3.113.0 → 3.115.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,38 @@
1
+ <!--
2
+ GENERATED ANALYSIS — @marianmeres/stuic real-browser component testing
3
+ Produced 2026-06-08 by multi-agent research → adversarial verify → synthesize.
4
+ Claims verified against the codebase at commit cc9958b and the live Vitest 4 /
5
+ vitest-browser-svelte docs. Planning artifact; no code was changed.
6
+ -->
7
+
8
+ # Component Testing — @marianmeres/stuic
9
+
10
+ This directory holds the plan for introducing **real-browser component tests** to STUIC
11
+ (Vitest 4 Browser Mode + `vitest-browser-svelte` + Playwright/Chromium). It was produced
12
+ 2026-06-08 from a research pass over the codebase and the current Svelte/Vitest ecosystem.
13
+ It is a **planning artifact — no code has been changed**; every claim is verified against the
14
+ repo at commit `cc9958b` or against the live docs cited in each section.
15
+
16
+ **Start here:** [`00-overview-and-roadmap.md`](./00-overview-and-roadmap.md). Then track and
17
+ resume execution from [`PROGRESS.md`](./PROGRESS.md).
18
+
19
+ ## Documents
20
+
21
+ | # | Doc | Scope | Headline |
22
+ |---|-----|-------|----------|
23
+ | 00 | [overview-and-roadmap](./00-overview-and-roadmap.md) | synthesis + roadmap | The stack is the right default; vitest 3→4 upgrade is the gating prerequisite. |
24
+ | 01 | [framework-setup](./01-framework-setup.md) | infra | Upgrade vitest 4, add a `projects` split (node `server` + browser `client`), route by filename. |
25
+ | 02 | [test-conventions](./02-test-conventions.md) | how-to | `render()` + locators + `expect.element`; events are props (spies); snippets via `createRawSnippet`. |
26
+ | 03 | [component-coverage-roadmap](./03-component-coverage-roadmap.md) | what to cover | 74 components tiered; warm up on Button/Pill/Switch, one commit per component. |
27
+ | 04 | [hard-cases-and-e2e](./04-hard-cases-and-e2e.md) | the hard 30 | Portals/focus-traps/anchor-positioning: one "hard proof" now; standalone Playwright E2E deferred. |
28
+ | 05 | [ci](./05-ci.md) | automation | One ~30-line GitHub Actions workflow; install Chromium, run `pnpm test`. |
29
+
30
+ ## How it was produced
31
+
32
+ Five parallel research agents (test-infra audit, full component inventory, multistep-format
33
+ extraction, two independent web-research angles on the stack) → synthesis → live-docs
34
+ verification of the exact Vitest 4 config syntax → this plan.
35
+
36
+ > Nothing here is decided beyond the four clarifying answers recorded in
37
+ > [`PROGRESS.md`](./PROGRESS.md) → Decisions log. Each doc's "Open questions / decisions needed"
38
+ > lists what still needs a call.
package/docs/testing.md CHANGED
@@ -11,7 +11,12 @@ This is a component library. Most of its correctness guarantees come from:
11
11
  3. **The build** — every component compiles, every export resolves.
12
12
  4. **Manual/visual review** — styling, animation, keyboard interaction, a11y cues.
13
13
 
14
- Unit tests are for what those tools can't see: **pure deterministic logic where a regression silently corrupts data**. We explicitly don't try to test everything.
14
+ Tests are for what those tools can't see. There are **two layers**, split by filename:
15
+
16
+ - **`*.test.ts` — node, fast.** Pure deterministic logic where a regression silently corrupts data.
17
+ - **`*.svelte.test.ts` — real browser (Chromium).** Component _behavior_ the build can't see: events firing, two-way `bind:`, `aria`/`disabled`/`active` state, focus traps, computed layout/positioning.
18
+
19
+ We still explicitly don't try to test everything. The browser layer targets **behavior contracts**, not "does it render" — see [`component-testing/`](./component-testing/) for the strategy, roadmap, and how-to.
15
20
 
16
21
  ## What we test
17
22
 
@@ -20,6 +25,7 @@ Unit tests are for what those tools can't see: **pure deterministic logic where
20
25
  - **Validation helpers** — `validateEmail`, `validateAddress`, `validateCustomerForm`, `validateLoginForm`, `validatePhoneNumber`, `addressesEqual`.
21
26
  - **State-machine classes** — `NotificationsStack`, `AlertConfirmPromptStack`, `SwitchState`, `InputHistory`. Tri-state transitions, dedupe, ordering, cleanup semantics.
22
27
  - **Pure utilities** — `replace-map`, `tr`, `storage-abstraction`, and anything else with non-trivial input/output logic.
28
+ - **Component behavior** (browser mode, `*.svelte.test.ts`) — prop→DOM/`aria` contracts, events firing, `bind:` updates, focus traps, viewport-clamped positioning. One component at a time, asserting contracts a consumer relies on — not every prop permutation.
23
29
 
24
30
  ### ⚠️ Maybe, if motivated by a regression
25
31
 
@@ -27,18 +33,23 @@ Unit tests are for what those tools can't see: **pure deterministic logic where
27
33
 
28
34
  ### ❌ We don't test
29
35
 
30
- - **Full component rendering** via `@testing-library/svelte`. 50+ components × prop combinations = slow suite with tiny yield. Rendering is already gated by `svelte-check` + `publint` + the build.
31
- - **Visual regression**. That's a separate project (Playwright + screenshot diffing) — not part of `vitest --dir src/`.
32
- - **Interactive behavior** (keyboard nav, drag-drop, scroll snap) unless the underlying math is extracted to a pure function.
36
+ - **Exhaustive prop-matrix / "does it render" tests.** 50+ components × every prop combination = slow suite with tiny yield. Rendering is already gated by `svelte-check` + `publint` + the build; the browser layer asserts _behavior contracts_, not coverage of every permutation.
37
+ - **Visual regression**. A separate concern (Vitest's `toMatchScreenshot` / screenshot diffing) — deferred, not part of `pnpm test` today.
38
+ - **Heavy gestures & 3rd-party editors** (drag-drop reorder, file drop, Milkdown/CodeMirror) deferred to a future standalone Playwright **E2E** layer, not the in-repo browser project. Extract and node-test their pure logic where practical.
33
39
  - **Coverage % targets**. They're the wrong goal for a component library.
34
40
 
35
41
  ## Running tests
36
42
 
37
43
  ```bash
38
- pnpm run test
44
+ pnpm test # both projects (node + browser), one-shot
45
+ pnpm test:watch # watch mode
46
+ pnpm test:ui # Vitest UI (handy for the browser project)
39
47
  ```
40
48
 
41
- Vitest is configured to run everything under `src/`. Tests live next to the code they test: `foo.ts` `foo.test.ts`.
49
+ Vitest runs **two projects**, routed by filename: a node project for `*.test.ts` and a real-browser
50
+ (Chromium, via Playwright) project for `*.svelte.test.ts`. Tests live next to the code they test:
51
+ `foo.ts` → `foo.test.ts`; `Foo.svelte` → `Foo.svelte.test.ts`. The browser binary is installed once
52
+ with `pnpm exec playwright install chromium`.
42
53
 
43
54
  ## Writing a test
44
55
 
@@ -65,8 +76,16 @@ import type { TranslateFn } from "$lib/types.js";
65
76
  const t: TranslateFn = (k) => k;
66
77
  ```
67
78
 
79
+ For **component** tests (`*.svelte.test.ts`), the patterns differ — `render()` from
80
+ `vitest-browser-svelte`, locators, and the retry-able `expect.element`; events are props (assert with
81
+ spies); snippet children come from `createRawSnippet`. See
82
+ [`component-testing/02-test-conventions.md`](./component-testing/02-test-conventions.md) for the full
83
+ how-to and the "what to assert" checklist.
84
+
68
85
  ## When in doubt
69
86
 
70
- - **Logic in a `.ts` file with clear input/output?** Write a test.
87
+ - **Logic in a `.ts` file with clear input/output?** Write a `*.test.ts`.
88
+ - **A component behavior that's a real contract** (event fires, value binds, focus traps, position
89
+ clamps)? Write a `*.svelte.test.ts`.
71
90
  - **A regression just bit you in production?** Write a test for that specific case before fixing.
72
- - **Anything else?** Probably don't bother.
91
+ - **"Does it render with these 12 props?"** Probably don't bother — the build already covers that.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.113.0",
3
+ "version": "3.115.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && pnpm run prepack",
@@ -13,7 +13,9 @@
13
13
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
14
14
  "format": "prettier --write .",
15
15
  "lint": "eslint . && prettier --check .",
16
- "test": "vitest --dir src/",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "test:ui": "vitest --ui",
17
19
  "svelte-check": "svelte-check",
18
20
  "svelte-package": "svelte-package",
19
21
  "rp": "pnpm run build && ./release.sh patch",
@@ -145,9 +147,11 @@
145
147
  "@tailwindcss/typography": "^0.5.19",
146
148
  "@tailwindcss/vite": "^4.3.0",
147
149
  "@types/node": "^25.9.2",
150
+ "@vitest/browser-playwright": "^4.1.8",
148
151
  "dotenv": "^16.6.1",
149
152
  "eslint": "^9.39.4",
150
153
  "globals": "^16.5.0",
154
+ "playwright": "^1.60.0",
151
155
  "prettier": "^3.8.3",
152
156
  "prettier-plugin-svelte": "^3.5.2",
153
157
  "publint": "^0.3.21",
@@ -158,7 +162,8 @@
158
162
  "typescript": "^5.9.3",
159
163
  "typescript-eslint": "^8.60.1",
160
164
  "vite": "^7.3.5",
161
- "vitest": "^3.2.6"
165
+ "vitest": "^4.1.8",
166
+ "vitest-browser-svelte": "^2.1.1"
162
167
  },
163
168
  "dependencies": {
164
169
  "@marianmeres/clog": "^3.21.0",