@zenuml/core 3.46.4 → 3.46.5
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.
- package/.claude/skills/babysit-pr/SKILL.md +203 -0
- package/.claude/skills/babysit-pr/agents/openai.yaml +7 -0
- package/.claude/skills/dia-scoring/SKILL.md +1 -1
- package/.claude/skills/propagate-core-release/SKILL.md +200 -0
- package/.claude/skills/propagate-core-release/agents/openai.yaml +7 -0
- package/.claude/skills/propagate-core-release/references/downstreams.md +41 -0
- package/dist/stats.html +1 -1
- package/dist/zenuml.esm.mjs +3 -3
- package/dist/zenuml.js +3 -3
- package/docs/superpowers/plans/2026-03-27-e2e-test-reorg.md +698 -0
- package/{cy → e2e/data}/compare-cases.js +70 -37
- package/{cy/smoke-editable-label.html → e2e/fixtures/editable-label.html} +1 -1
- package/{cy/editable-span-test.html → e2e/fixtures/editable-span.html} +1 -1
- package/e2e/fixtures/fixture.html +31 -0
- package/{cy → e2e/tools}/canonical-history.html +1 -1
- package/{cy → e2e/tools}/compare-case.html +3 -3
- package/{cy → e2e/tools}/compare.html +2 -2
- package/{cy → e2e/tools}/native-diff-ext/content.js +2 -2
- package/firebase-debug.log +108 -0
- package/index.html +2 -2
- package/mermaid-zenuml-async-spa-auth.png +0 -0
- package/mermaid-zenuml-async-spa-auth.snapshot.md +96 -0
- package/package.json +1 -1
- package/scripts/analyze-compare-case/collect-data.mjs +1 -1
- package/scripts/analyze-compare-case.mjs +1 -1
- package/skills/dia-scoring/SKILL.md +1 -1
- package/vite.config.ts +5 -5
- package/cy/async-message-1.html +0 -32
- package/cy/async-message-2.html +0 -46
- package/cy/async-message-3.html +0 -41
- package/cy/creation-rtl.html +0 -28
- package/cy/defect-406-alt-under-creation.html +0 -40
- package/cy/demo1.html +0 -28
- package/cy/demo3.html +0 -28
- package/cy/demo4.html +0 -28
- package/cy/element-report.html +0 -705
- package/cy/fragments-with-return.html +0 -35
- package/cy/icons-test.html +0 -29
- package/cy/if-fragment.html +0 -28
- package/cy/legacy-vs-html.html +0 -291
- package/cy/named-parameters.html +0 -30
- package/cy/nested-interaction-with-fragment.html +0 -34
- package/cy/nested-interaction-with-outbound.html +0 -34
- package/cy/parity-test.html +0 -122
- package/cy/return-in-nested-if.html +0 -29
- package/cy/return.html +0 -38
- package/cy/self-sync-message-at-root.html +0 -28
- package/cy/smoke-creation.html +0 -26
- package/cy/smoke-fragment-issue.html +0 -36
- package/cy/smoke-fragment.html +0 -42
- package/cy/smoke-interaction.html +0 -34
- package/cy/smoke.html +0 -40
- package/cy/theme-default-test.html +0 -28
- package/cy/vertical-1.html +0 -25
- package/cy/vertical-10.html +0 -33
- package/cy/vertical-11.html +0 -29
- package/cy/vertical-2.html +0 -23
- package/cy/vertical-3.html +0 -37
- package/cy/vertical-4.html +0 -42
- package/cy/vertical-5.html +0 -40
- package/cy/vertical-6.html +0 -29
- package/cy/vertical-7.html +0 -27
- package/cy/vertical-8.html +0 -32
- package/cy/vertical-9.html +0 -25
- package/cy/xss.html +0 -21
- /package/{cy → e2e/data}/diff-algorithm.js +0 -0
- /package/{cy → e2e/fixtures}/svg-test.html +0 -0
- /package/{cy → e2e/tools}/native-diff-ext/background.js +0 -0
- /package/{cy → e2e/tools}/native-diff-ext/bridge.js +0 -0
- /package/{cy → e2e/tools}/svg-preview.html +0 -0
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
# E2E Test Reorganization Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Eliminate massive duplication in E2E tests by consolidating DSL data into a single source of truth, making repetitive tests data-driven, and organizing tests into logical subdirectories.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Replace 37 near-identical HTML fixture files with a single parameterized template (`e2e/fixtures/fixture.html`) that reads DSL from a query parameter or shared data module. Consolidate all DSL test data into `e2e/data/compare-cases.js` (already exists, already has ~50 cases). Convert repetitive spec files (vertical, creation, fragment, etc.) into data-driven loops like `svg-parity.spec.ts` already does. Group spec files into subdirectories by test type.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** Playwright, TypeScript, Vite dev server, existing `cy/` HTML infrastructure
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Current State Analysis
|
|
14
|
+
|
|
15
|
+
### Problems
|
|
16
|
+
|
|
17
|
+
1. **37 near-identical HTML files** — Each `e2e/**/*.html` is the same boilerplate with different DSL in a `<pre>` tag. Example: `vertical-1.html` through `vertical-11.html` differ only by 2-3 lines of DSL code.
|
|
18
|
+
|
|
19
|
+
2. **DSL duplicated 3 times** — The same diagram code exists in:
|
|
20
|
+
- `e2e/**/*.html` files (for HTML renderer tests)
|
|
21
|
+
- `svg-parity.spec.ts` inline array (for SVG parity tests)
|
|
22
|
+
- `e2e/data/compare-cases.js` (for the compare-case viewer)
|
|
23
|
+
|
|
24
|
+
3. **Copy-paste spec files** — `vertical.spec.ts` has 11 identical test blocks differing only by number. `creation.spec.ts`, `fragment.spec.ts`, `return.spec.ts`, etc. are all the same 15-line pattern.
|
|
25
|
+
|
|
26
|
+
4. **Flat directory** — All 21 spec files sit in `tests/` with no grouping. Visual regression tests, interaction tests, and parity tests are mixed together.
|
|
27
|
+
|
|
28
|
+
5. **Inconsistent `describe` names** — "Smoke test", "Rendering", "SVG Parity Tests" — no convention.
|
|
29
|
+
|
|
30
|
+
### What Works Well (Keep)
|
|
31
|
+
|
|
32
|
+
- `svg-parity.spec.ts` — already data-driven with an inline array. Good pattern to extend.
|
|
33
|
+
- `fixtures.ts` — clean custom fixture with console logging. Keep as-is.
|
|
34
|
+
- `compare-cases.js` — central case registry. Promote to single source of truth.
|
|
35
|
+
- `editable-label.spec.ts`, `editable-span-escape.spec.ts` — interaction tests with unique logic. These stay as individual files.
|
|
36
|
+
- `width-provider-comparison.spec.ts` — measurement test with unique logic. Stays as-is.
|
|
37
|
+
|
|
38
|
+
## Target State
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
tests/
|
|
42
|
+
├── fixtures.ts # Shared fixture (unchanged)
|
|
43
|
+
├── test-cases.ts # Re-exports from e2e/data/compare-cases.js with types
|
|
44
|
+
├── visual/
|
|
45
|
+
│ ├── html-rendering.spec.ts # Data-driven: all HTML renderer screenshot tests
|
|
46
|
+
│ └── svg-parity.spec.ts # Data-driven: all SVG renderer screenshot tests (exists, move)
|
|
47
|
+
├── interaction/
|
|
48
|
+
│ ├── editable-label.spec.ts # Keep as-is (move)
|
|
49
|
+
│ └── editable-span-escape.spec.ts # Keep as-is (move)
|
|
50
|
+
├── regression/
|
|
51
|
+
│ └── defect-406.spec.ts # Keep as-is (move)
|
|
52
|
+
├── measurement/
|
|
53
|
+
│ └── width-provider-comparison.spec.ts # Keep as-is (move)
|
|
54
|
+
└── *.spec.ts-snapshots/ # Snapshot dirs (Playwright manages these)
|
|
55
|
+
|
|
56
|
+
cy/
|
|
57
|
+
├── fixture.html # Single parameterized HTML template
|
|
58
|
+
├── compare-cases.js # Single source of truth for ALL DSL cases
|
|
59
|
+
├── compare-case.html # Keep (compare viewer)
|
|
60
|
+
├── compare.html # Keep (index page)
|
|
61
|
+
├── svg-test.html # Keep (SVG render harness)
|
|
62
|
+
├── editable-span-test.html # Keep (interaction test page)
|
|
63
|
+
├── smoke-editable-label.html # Keep (interaction test page)
|
|
64
|
+
├── element-report.html # Keep (dev tool)
|
|
65
|
+
├── parity-test.html # Keep (dev tool)
|
|
66
|
+
├── legacy-vs-html.html # Keep (dev tool)
|
|
67
|
+
├── canonical-history.html # Keep (dev tool)
|
|
68
|
+
├── svg-preview.html # Keep (dev tool)
|
|
69
|
+
├── icons-test.html # Keep (dev tool)
|
|
70
|
+
├── theme-default-test.html # Keep (dev tool)
|
|
71
|
+
└── diff-algorithm.js # Keep (utility)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Deleted** (replaced by `fixture.html`): `smoke.html`, `smoke-creation.html`, `smoke-fragment.html`, `smoke-fragment-issue.html`, `smoke-interaction.html`, `creation-rtl.html`, `defect-406-alt-under-creation.html`, `fragment.html`, `fragments-with-return.html`, `if-fragment.html`, `return.html`, `self-sync-message-at-root.html`, `named-parameters.html`, `nested-interaction-with-fragment.html`, `nested-interaction-with-outbound.html`, `vertical-1.html` through `vertical-11.html`, `async-message-1.html` through `async-message-3.html`, `demo1.html`, `demo3.html`, `demo4.html`, `return-in-nested-if.html`.
|
|
75
|
+
|
|
76
|
+
**Deleted spec files** (merged into `html-rendering.spec.ts`): `smoke.spec.ts`, `creation.spec.ts`, `creation-rtl.spec.ts`, `fragment.spec.ts`, `fragments-with-return.spec.ts`, `if-fragment.spec.ts`, `interaction.spec.ts`, `nested-interactions.spec.ts`, `named-parameters.spec.ts`, `return.spec.ts`, `return-in-nested-if.spec.ts`, `self-sync-message-at-root.spec.ts`, `vertical.spec.ts`, `async-message.spec.ts`, `demo.spec.ts`, `style-panel.spec.ts`.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Task 1: Create parameterized HTML fixture template
|
|
81
|
+
|
|
82
|
+
**Files:**
|
|
83
|
+
- Create: `e2e/fixtures/fixture.html`
|
|
84
|
+
- Reference: `cy/smoke.html` (pattern to generalize)
|
|
85
|
+
|
|
86
|
+
The new template reads a `?case=<name>` query parameter and looks up the DSL from the `compare-cases.js` registry.
|
|
87
|
+
|
|
88
|
+
- [ ] **Step 1: Create `e2e/fixtures/fixture.html`**
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<!doctype html>
|
|
92
|
+
<html>
|
|
93
|
+
<head>
|
|
94
|
+
<meta charset="utf-8" />
|
|
95
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
96
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
97
|
+
<title>ZenUML Test Fixture</title>
|
|
98
|
+
<style>
|
|
99
|
+
body {
|
|
100
|
+
margin: 0;
|
|
101
|
+
}
|
|
102
|
+
</style>
|
|
103
|
+
</head>
|
|
104
|
+
<body>
|
|
105
|
+
<div id="diagram" class="diagram">
|
|
106
|
+
<pre class="zenuml" style="margin: 0" id="zenuml-code"></pre>
|
|
107
|
+
</div>
|
|
108
|
+
<script type="module">
|
|
109
|
+
import { CASES } from "./compare-cases.js";
|
|
110
|
+
const params = new URLSearchParams(window.location.search);
|
|
111
|
+
const caseName = params.get("case");
|
|
112
|
+
if (caseName && CASES[caseName]) {
|
|
113
|
+
document.getElementById("zenuml-code").textContent = CASES[caseName];
|
|
114
|
+
} else {
|
|
115
|
+
document.getElementById("zenuml-code").textContent =
|
|
116
|
+
"// Case not found: " + caseName;
|
|
117
|
+
}
|
|
118
|
+
</script>
|
|
119
|
+
<script type="module" src="/src/main-cy.ts"></script>
|
|
120
|
+
</body>
|
|
121
|
+
</html>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- [ ] **Step 2: Verify the template loads correctly**
|
|
125
|
+
|
|
126
|
+
Start the dev server (`bun dev`) and open `http://localhost:8080/cy/fixture.html?case=smoke` in a browser. Verify the diagram renders identically to `http://localhost:8080/cy/smoke.html`.
|
|
127
|
+
|
|
128
|
+
- [ ] **Step 3: Commit**
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
git add cy/fixture.html
|
|
132
|
+
git commit -m "Add parameterized HTML fixture template for E2E tests"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### Task 2: Ensure all current HTML fixture DSL is in compare-cases.js
|
|
138
|
+
|
|
139
|
+
**Files:**
|
|
140
|
+
- Modify: `e2e/data/compare-cases.js`
|
|
141
|
+
- Reference: All `e2e/**/*.html` files (to extract DSL)
|
|
142
|
+
|
|
143
|
+
Some HTML fixture files have DSL that isn't in `compare-cases.js`. We need to add any missing cases.
|
|
144
|
+
|
|
145
|
+
- [ ] **Step 1: Audit missing cases**
|
|
146
|
+
|
|
147
|
+
Write a script or manually compare. The following cases from HTML fixtures must exist in `compare-cases.js`:
|
|
148
|
+
|
|
149
|
+
Check these exist (by name): `smoke`, `creation` (from `smoke-creation.html`), `creation-rtl`, `defect-406` (from `defect-406-alt-under-creation.html`), `fragment` (from `smoke-fragment.html`), `fragment-issue` (from `smoke-fragment-issue.html`), `if-fragment`, `fragments-return` (from `fragments-with-return.html`), `interaction` (from `smoke-interaction.html`), `async-1`, `async-2`, `async-3`, `return`, `self-sync` (from `self-sync-message-at-root.html`), `named-params` (from `named-parameters.html`), `nested-fragment` (from `nested-interaction-with-fragment.html`), `nested-outbound` (from `nested-interaction-with-outbound.html`), `vertical-1` through `vertical-11`, `demo1-smoke` (from `demo1.html`), `demo3-nested-fragments` (from `demo3.html`), `demo4-fragment-span` (from `demo4.html`), `return-in-nested-if`, `style-panel` (from `smoke-fragment.html` used by `style-panel.spec.ts`).
|
|
150
|
+
|
|
151
|
+
- [ ] **Step 2: Add any missing cases to `compare-cases.js`**
|
|
152
|
+
|
|
153
|
+
Extract the DSL from each HTML file's `<pre class="zenuml">` block. Add to the `CASES` object using the same name used in `svg-parity.spec.ts` where possible (for consistency).
|
|
154
|
+
|
|
155
|
+
For each missing case, add it in the appropriate category section with a comment:
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// --- Category ---
|
|
159
|
+
"case-name": `DSL code here`,
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- [ ] **Step 3: Verify fixture.html works for all added cases**
|
|
163
|
+
|
|
164
|
+
Spot-check 3-4 newly added cases by loading `fixture.html?case=<name>` and comparing to the original HTML file.
|
|
165
|
+
|
|
166
|
+
- [ ] **Step 4: Commit**
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
git add e2e/data/compare-cases.js
|
|
170
|
+
git commit -m "Add all HTML fixture DSL cases to compare-cases.js"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Task 3: Create typed test-cases module
|
|
176
|
+
|
|
177
|
+
**Files:**
|
|
178
|
+
- Create: `tests/test-cases.ts`
|
|
179
|
+
|
|
180
|
+
A thin TypeScript wrapper that imports from `compare-cases.js` and provides typed access for spec files.
|
|
181
|
+
|
|
182
|
+
- [ ] **Step 1: Create `tests/test-cases.ts`**
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// Re-export compare-cases with type safety for use in spec files.
|
|
186
|
+
// compare-cases.js is the single source of truth for all DSL test data.
|
|
187
|
+
|
|
188
|
+
// @ts-expect-error — JS module without types
|
|
189
|
+
import { CASES } from "../e2e/data/compare-cases.js";
|
|
190
|
+
|
|
191
|
+
export const TEST_CASES: Record<string, string> = CASES;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Subset of cases used by the HTML renderer visual regression tests.
|
|
195
|
+
* Each entry maps to a fixture.html?case=<key> URL.
|
|
196
|
+
*/
|
|
197
|
+
export const HTML_VISUAL_CASES: { name: string; threshold?: number }[] = [
|
|
198
|
+
// Smoke / basics
|
|
199
|
+
{ name: "smoke", threshold: 0.012 },
|
|
200
|
+
{ name: "creation" },
|
|
201
|
+
{ name: "creation-rtl" },
|
|
202
|
+
{ name: "defect-406" },
|
|
203
|
+
|
|
204
|
+
// Fragments
|
|
205
|
+
{ name: "fragment" },
|
|
206
|
+
{ name: "fragment-issue" },
|
|
207
|
+
{ name: "if-fragment" },
|
|
208
|
+
{ name: "fragments-return" },
|
|
209
|
+
|
|
210
|
+
// Interactions
|
|
211
|
+
{ name: "interaction" },
|
|
212
|
+
{ name: "nested-fragment" },
|
|
213
|
+
{ name: "nested-outbound" },
|
|
214
|
+
|
|
215
|
+
// Async messages
|
|
216
|
+
{ name: "async-1" },
|
|
217
|
+
{ name: "async-2" },
|
|
218
|
+
{ name: "async-3" },
|
|
219
|
+
|
|
220
|
+
// Returns
|
|
221
|
+
{ name: "return" },
|
|
222
|
+
{ name: "return-in-nested-if" },
|
|
223
|
+
|
|
224
|
+
// Self-calls
|
|
225
|
+
{ name: "self-sync" },
|
|
226
|
+
|
|
227
|
+
// Named parameters
|
|
228
|
+
{ name: "named-params" },
|
|
229
|
+
|
|
230
|
+
// Vertical layout
|
|
231
|
+
{ name: "vertical-1" },
|
|
232
|
+
{ name: "vertical-2" },
|
|
233
|
+
{ name: "vertical-3" },
|
|
234
|
+
{ name: "vertical-4" },
|
|
235
|
+
{ name: "vertical-5" },
|
|
236
|
+
{ name: "vertical-6" },
|
|
237
|
+
{ name: "vertical-7" },
|
|
238
|
+
{ name: "vertical-8" },
|
|
239
|
+
{ name: "vertical-9" },
|
|
240
|
+
{ name: "vertical-10" },
|
|
241
|
+
{ name: "vertical-11" },
|
|
242
|
+
|
|
243
|
+
// Demos
|
|
244
|
+
{ name: "demo1-smoke" },
|
|
245
|
+
{ name: "demo3-nested-fragments" },
|
|
246
|
+
{ name: "demo4-fragment-span" },
|
|
247
|
+
];
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Default screenshot threshold for visual tests.
|
|
251
|
+
*/
|
|
252
|
+
export const DEFAULT_THRESHOLD = 0.02;
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
- [ ] **Step 2: Verify import works**
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
cd /Users/pengxiao/workspaces/zenuml/native-svg-renderer/zenuml-core
|
|
259
|
+
bun -e "import { TEST_CASES, HTML_VISUAL_CASES } from './tests/test-cases.ts'; console.log(Object.keys(TEST_CASES).length, 'cases'); console.log(HTML_VISUAL_CASES.length, 'html visual cases')"
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Expected: prints case counts without errors.
|
|
263
|
+
|
|
264
|
+
- [ ] **Step 3: Commit**
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
git add tests/test-cases.ts
|
|
268
|
+
git commit -m "Add typed test-cases module wrapping compare-cases.js"
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### Task 4: Create directory structure and move unique test files
|
|
274
|
+
|
|
275
|
+
**Files:**
|
|
276
|
+
- Create dirs: `tests/visual/`, `tests/interaction/`, `tests/regression/`, `tests/measurement/`
|
|
277
|
+
- Move: `tests/editable-label.spec.ts` → `tests/interaction/editable-label.spec.ts`
|
|
278
|
+
- Move: `tests/editable-span-escape.spec.ts` → `tests/interaction/editable-span-escape.spec.ts`
|
|
279
|
+
- Move: `tests/defect-406.spec.ts` → `tests/regression/defect-406.spec.ts`
|
|
280
|
+
- Move: `tests/width-provider-comparison.spec.ts` → `tests/measurement/width-provider-comparison.spec.ts`
|
|
281
|
+
- Move: `tests/svg-parity.spec.ts` → `tests/visual/svg-parity.spec.ts`
|
|
282
|
+
- Modify: `playwright.config.ts` (update testDir if needed)
|
|
283
|
+
|
|
284
|
+
- [ ] **Step 1: Create directories**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
mkdir -p tests/visual tests/interaction tests/regression tests/measurement
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
- [ ] **Step 2: Move unique test files**
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
git mv tests/editable-label.spec.ts tests/interaction/editable-label.spec.ts
|
|
294
|
+
git mv tests/editable-span-escape.spec.ts tests/interaction/editable-span-escape.spec.ts
|
|
295
|
+
git mv tests/defect-406.spec.ts tests/regression/defect-406.spec.ts
|
|
296
|
+
git mv tests/width-provider-comparison.spec.ts tests/measurement/width-provider-comparison.spec.ts
|
|
297
|
+
git mv tests/svg-parity.spec.ts tests/visual/svg-parity.spec.ts
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
- [ ] **Step 3: Update fixture imports in moved files**
|
|
301
|
+
|
|
302
|
+
Each moved file imports from `./fixtures`. Update to `../fixtures`:
|
|
303
|
+
|
|
304
|
+
In `tests/interaction/editable-label.spec.ts`:
|
|
305
|
+
```typescript
|
|
306
|
+
import { test, expect } from "../fixtures";
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
In `tests/interaction/editable-span-escape.spec.ts`:
|
|
310
|
+
```typescript
|
|
311
|
+
import { test, expect } from "../fixtures";
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
In `tests/regression/defect-406.spec.ts`:
|
|
315
|
+
```typescript
|
|
316
|
+
import { test, expect } from "../fixtures";
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
In `tests/measurement/width-provider-comparison.spec.ts`:
|
|
320
|
+
```typescript
|
|
321
|
+
import { test, expect } from "../fixtures";
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
In `tests/visual/svg-parity.spec.ts`:
|
|
325
|
+
```typescript
|
|
326
|
+
import { test, expect } from "../fixtures";
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
- [ ] **Step 4: Move snapshot directories alongside their spec files**
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
# Move snapshot dirs to match new spec locations
|
|
333
|
+
git mv tests/editable-label.spec.ts-snapshots tests/interaction/editable-label.spec.ts-snapshots
|
|
334
|
+
git mv tests/defect-406.spec.ts-snapshots tests/regression/defect-406.spec.ts-snapshots
|
|
335
|
+
git mv tests/svg-parity.spec.ts-snapshots tests/visual/svg-parity.spec.ts-snapshots
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Note: `editable-span-escape.spec.ts` and `width-provider-comparison.spec.ts` don't have snapshot dirs (they don't use `toHaveScreenshot`).
|
|
339
|
+
|
|
340
|
+
- [ ] **Step 5: Verify Playwright finds all tests**
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
bun pw --list
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Expected: All moved tests appear with their new paths. The `testDir: "./tests"` in `playwright.config.ts` already recurses into subdirectories by default, so no config change needed.
|
|
347
|
+
|
|
348
|
+
- [ ] **Step 6: Run the moved tests to verify snapshots still match**
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
bun pw tests/interaction/ tests/regression/ tests/measurement/ tests/visual/svg-parity.spec.ts
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Expected: All pass (snapshots found in new locations).
|
|
355
|
+
|
|
356
|
+
- [ ] **Step 7: Commit**
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
git add -A tests/
|
|
360
|
+
git commit -m "Organize E2E tests into subdirectories by type"
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### Task 5: Create data-driven HTML rendering test
|
|
366
|
+
|
|
367
|
+
**Files:**
|
|
368
|
+
- Create: `tests/visual/html-rendering.spec.ts`
|
|
369
|
+
|
|
370
|
+
This single file replaces 16 separate spec files by iterating over `HTML_VISUAL_CASES`.
|
|
371
|
+
|
|
372
|
+
- [ ] **Step 1: Create `tests/visual/html-rendering.spec.ts`**
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
import { test, expect } from "../fixtures";
|
|
376
|
+
import { HTML_VISUAL_CASES, DEFAULT_THRESHOLD } from "../test-cases";
|
|
377
|
+
|
|
378
|
+
test.describe("HTML Rendering", () => {
|
|
379
|
+
for (const { name, threshold } of HTML_VISUAL_CASES) {
|
|
380
|
+
test(name, async ({ page }) => {
|
|
381
|
+
await page.goto(`/cy/fixture.html?case=${name}`);
|
|
382
|
+
|
|
383
|
+
// Wait for diagram to render
|
|
384
|
+
await expect(page.locator(".privacy>span>svg")).toBeVisible({
|
|
385
|
+
timeout: 5000,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
await expect(page).toHaveScreenshot(`${name}.png`, {
|
|
389
|
+
threshold: threshold ?? DEFAULT_THRESHOLD,
|
|
390
|
+
fullPage: true,
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
- [ ] **Step 2: Run the new test to generate initial snapshots**
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
bun pw tests/visual/html-rendering.spec.ts --update-snapshots
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Expected: All cases generate snapshots. Verify a few match the old snapshots visually.
|
|
404
|
+
|
|
405
|
+
- [ ] **Step 3: Run without --update-snapshots to verify stability**
|
|
406
|
+
|
|
407
|
+
```bash
|
|
408
|
+
bun pw tests/visual/html-rendering.spec.ts
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Expected: All pass.
|
|
412
|
+
|
|
413
|
+
- [ ] **Step 4: Commit**
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
git add tests/visual/html-rendering.spec.ts tests/visual/html-rendering.spec.ts-snapshots/
|
|
417
|
+
git commit -m "Add data-driven HTML rendering visual test"
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
### Task 6: Refactor svg-parity.spec.ts to use shared test data
|
|
423
|
+
|
|
424
|
+
**Files:**
|
|
425
|
+
- Modify: `tests/visual/svg-parity.spec.ts`
|
|
426
|
+
|
|
427
|
+
Remove the 540-line inline `SVG_PARITY_CASES` array and replace with imports from `test-cases.ts`. The SVG parity test uses the same case names but renders through `renderToSvg()` instead of the HTML renderer.
|
|
428
|
+
|
|
429
|
+
- [ ] **Step 1: Add SVG parity case list to `tests/test-cases.ts`**
|
|
430
|
+
|
|
431
|
+
Add after `HTML_VISUAL_CASES`:
|
|
432
|
+
|
|
433
|
+
```typescript
|
|
434
|
+
/**
|
|
435
|
+
* Subset of cases used by the SVG parity visual regression tests.
|
|
436
|
+
* Each entry renders through renderToSvg() on svg-test.html.
|
|
437
|
+
*/
|
|
438
|
+
export const SVG_PARITY_CASES: string[] = [
|
|
439
|
+
"smoke",
|
|
440
|
+
"creation",
|
|
441
|
+
"creation-rtl",
|
|
442
|
+
"defect-406",
|
|
443
|
+
"fragment",
|
|
444
|
+
"fragment-issue",
|
|
445
|
+
"if-fragment",
|
|
446
|
+
"fragments-return",
|
|
447
|
+
"interaction",
|
|
448
|
+
"async-1",
|
|
449
|
+
"async-2",
|
|
450
|
+
"async-3",
|
|
451
|
+
"return",
|
|
452
|
+
"self-sync",
|
|
453
|
+
"nested-fragment",
|
|
454
|
+
"nested-outbound",
|
|
455
|
+
"named-params",
|
|
456
|
+
"vertical-1",
|
|
457
|
+
"vertical-2",
|
|
458
|
+
"vertical-3",
|
|
459
|
+
"vertical-4",
|
|
460
|
+
"vertical-5",
|
|
461
|
+
"vertical-6",
|
|
462
|
+
"vertical-7",
|
|
463
|
+
"vertical-8",
|
|
464
|
+
"vertical-9",
|
|
465
|
+
"vertical-10",
|
|
466
|
+
"vertical-11",
|
|
467
|
+
"demo1-smoke",
|
|
468
|
+
"demo3-nested-fragments",
|
|
469
|
+
"demo4-fragment-span",
|
|
470
|
+
"demo5-self-named",
|
|
471
|
+
"demo6-async-styled",
|
|
472
|
+
];
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
- [ ] **Step 2: Rewrite `tests/visual/svg-parity.spec.ts`**
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
import { test, expect } from "../fixtures";
|
|
479
|
+
import { TEST_CASES, SVG_PARITY_CASES } from "../test-cases";
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* SVG Parity Tests
|
|
483
|
+
*
|
|
484
|
+
* Renders every visual test fixture through renderToSvg() and captures
|
|
485
|
+
* screenshot baselines. These verify structural/layout parity with the
|
|
486
|
+
* React/HTML renderer — same elements, positions, and reading order.
|
|
487
|
+
*/
|
|
488
|
+
test.describe("SVG Parity Tests", () => {
|
|
489
|
+
for (const name of SVG_PARITY_CASES) {
|
|
490
|
+
test(`svg-${name}`, async ({ page }) => {
|
|
491
|
+
const code = TEST_CASES[name];
|
|
492
|
+
if (!code) throw new Error(`Missing test case: ${name}`);
|
|
493
|
+
|
|
494
|
+
await page.goto("/cy/svg-test.html");
|
|
495
|
+
await page.evaluate((c) => (window as any).__renderSvg(c), code);
|
|
496
|
+
await expect(page.locator("#svg-output > svg")).toBeVisible({ timeout: 5000 });
|
|
497
|
+
await expect(page).toHaveScreenshot(`svg-${name}.png`, {
|
|
498
|
+
threshold: 0.02,
|
|
499
|
+
fullPage: true,
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
});
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
- [ ] **Step 3: Run to verify snapshots still match**
|
|
507
|
+
|
|
508
|
+
```bash
|
|
509
|
+
bun pw tests/visual/svg-parity.spec.ts
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
Expected: All pass with existing snapshots (screenshot names unchanged).
|
|
513
|
+
|
|
514
|
+
- [ ] **Step 4: Commit**
|
|
515
|
+
|
|
516
|
+
```bash
|
|
517
|
+
git add tests/visual/svg-parity.spec.ts tests/test-cases.ts
|
|
518
|
+
git commit -m "Refactor svg-parity.spec.ts to use shared test-cases module"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
### Task 7: Delete replaced spec files and HTML fixtures
|
|
524
|
+
|
|
525
|
+
**Files:**
|
|
526
|
+
- Delete: 16 spec files (replaced by `html-rendering.spec.ts`)
|
|
527
|
+
- Delete: ~27 HTML fixture files (replaced by `fixture.html`)
|
|
528
|
+
|
|
529
|
+
- [ ] **Step 1: Verify the new data-driven tests cover all old tests**
|
|
530
|
+
|
|
531
|
+
Run both old and new tests, compare test counts:
|
|
532
|
+
|
|
533
|
+
```bash
|
|
534
|
+
# Count old individual tests
|
|
535
|
+
bun pw tests/smoke.spec.ts tests/creation.spec.ts tests/creation-rtl.spec.ts tests/fragment.spec.ts tests/fragments-with-return.spec.ts tests/if-fragment.spec.ts tests/interaction.spec.ts tests/nested-interactions.spec.ts tests/named-parameters.spec.ts tests/return.spec.ts tests/return-in-nested-if.spec.ts tests/self-sync-message-at-root.spec.ts tests/vertical.spec.ts tests/async-message.spec.ts tests/demo.spec.ts tests/style-panel.spec.ts --list 2>/dev/null | wc -l
|
|
536
|
+
|
|
537
|
+
# Count new data-driven tests
|
|
538
|
+
bun pw tests/visual/html-rendering.spec.ts --list 2>/dev/null | wc -l
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
The new test count should be >= old test count.
|
|
542
|
+
|
|
543
|
+
- [ ] **Step 2: Delete old spec files**
|
|
544
|
+
|
|
545
|
+
```bash
|
|
546
|
+
git rm tests/smoke.spec.ts
|
|
547
|
+
git rm tests/creation.spec.ts
|
|
548
|
+
git rm tests/creation-rtl.spec.ts
|
|
549
|
+
git rm tests/fragment.spec.ts
|
|
550
|
+
git rm tests/fragments-with-return.spec.ts
|
|
551
|
+
git rm tests/if-fragment.spec.ts
|
|
552
|
+
git rm tests/interaction.spec.ts
|
|
553
|
+
git rm tests/nested-interactions.spec.ts
|
|
554
|
+
git rm tests/named-parameters.spec.ts
|
|
555
|
+
git rm tests/return.spec.ts
|
|
556
|
+
git rm tests/return-in-nested-if.spec.ts
|
|
557
|
+
git rm tests/self-sync-message-at-root.spec.ts
|
|
558
|
+
git rm tests/vertical.spec.ts
|
|
559
|
+
git rm tests/async-message.spec.ts
|
|
560
|
+
git rm tests/demo.spec.ts
|
|
561
|
+
git rm tests/style-panel.spec.ts
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
- [ ] **Step 3: Delete old snapshot directories for removed specs**
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
git rm -r tests/smoke.spec.ts-snapshots
|
|
568
|
+
git rm -r tests/creation.spec.ts-snapshots
|
|
569
|
+
git rm -r tests/creation-rtl.spec.ts-snapshots
|
|
570
|
+
git rm -r tests/fragment.spec.ts-snapshots
|
|
571
|
+
git rm -r tests/fragments-with-return.spec.ts-snapshots
|
|
572
|
+
git rm -r tests/if-fragment.spec.ts-snapshots
|
|
573
|
+
git rm -r tests/interaction.spec.ts-snapshots
|
|
574
|
+
git rm -r tests/nested-interactions.spec.ts-snapshots
|
|
575
|
+
git rm -r tests/named-parameters.spec.ts-snapshots
|
|
576
|
+
git rm -r tests/return.spec.ts-snapshots
|
|
577
|
+
git rm -r tests/return-in-nested-if.spec.ts-snapshots
|
|
578
|
+
git rm -r tests/self-sync-message-at-root.spec.ts-snapshots
|
|
579
|
+
git rm -r tests/vertical.spec.ts-snapshots
|
|
580
|
+
git rm -r tests/async-message.spec.ts-snapshots
|
|
581
|
+
git rm -r tests/demo.spec.ts-snapshots
|
|
582
|
+
git rm -r tests/style-panel.spec.ts-snapshots
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
- [ ] **Step 4: Delete replaced HTML fixtures**
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
git rm cy/smoke.html
|
|
589
|
+
git rm cy/smoke-creation.html
|
|
590
|
+
git rm cy/smoke-fragment.html
|
|
591
|
+
git rm cy/smoke-fragment-issue.html
|
|
592
|
+
git rm cy/smoke-interaction.html
|
|
593
|
+
git rm cy/creation-rtl.html
|
|
594
|
+
git rm cy/defect-406-alt-under-creation.html
|
|
595
|
+
git rm cy/fragment.html
|
|
596
|
+
git rm cy/fragments-with-return.html
|
|
597
|
+
git rm cy/if-fragment.html
|
|
598
|
+
git rm cy/return.html
|
|
599
|
+
git rm cy/return-in-nested-if.html
|
|
600
|
+
git rm cy/self-sync-message-at-root.html
|
|
601
|
+
git rm cy/named-parameters.html
|
|
602
|
+
git rm cy/nested-interaction-with-fragment.html
|
|
603
|
+
git rm cy/nested-interaction-with-outbound.html
|
|
604
|
+
git rm cy/vertical-1.html cy/vertical-2.html cy/vertical-3.html cy/vertical-4.html
|
|
605
|
+
git rm cy/vertical-5.html cy/vertical-6.html cy/vertical-7.html cy/vertical-8.html
|
|
606
|
+
git rm cy/vertical-9.html cy/vertical-10.html cy/vertical-11.html
|
|
607
|
+
git rm cy/async-message-1.html cy/async-message-2.html cy/async-message-3.html
|
|
608
|
+
git rm cy/demo1.html cy/demo3.html cy/demo4.html
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
- [ ] **Step 5: Run full test suite to verify nothing is broken**
|
|
612
|
+
|
|
613
|
+
```bash
|
|
614
|
+
bun pw
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
Expected: All tests pass. No tests reference deleted files.
|
|
618
|
+
|
|
619
|
+
- [ ] **Step 6: Commit**
|
|
620
|
+
|
|
621
|
+
```bash
|
|
622
|
+
git add -A
|
|
623
|
+
git commit -m "Remove replaced spec files and HTML fixtures"
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
### Task 8: Final verification and cleanup
|
|
629
|
+
|
|
630
|
+
**Files:**
|
|
631
|
+
- Verify: All tests pass
|
|
632
|
+
- Verify: No dead references
|
|
633
|
+
|
|
634
|
+
- [ ] **Step 1: Run the full test suite**
|
|
635
|
+
|
|
636
|
+
```bash
|
|
637
|
+
bun pw --reporter=list
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
Expected: All tests pass.
|
|
641
|
+
|
|
642
|
+
- [ ] **Step 2: Verify test count**
|
|
643
|
+
|
|
644
|
+
```bash
|
|
645
|
+
bun pw --list | wc -l
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
Expected: Should be roughly the same as before (the data-driven tests cover all the old individual tests plus SVG parity tests).
|
|
649
|
+
|
|
650
|
+
- [ ] **Step 3: Check for dead HTML references**
|
|
651
|
+
|
|
652
|
+
```bash
|
|
653
|
+
grep -r "cy/smoke\.html\|cy/vertical-\|cy/creation-rtl\|cy/fragment\.html\|cy/demo[134]\.html" tests/
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
Expected: No matches (no spec files reference deleted HTML fixtures).
|
|
657
|
+
|
|
658
|
+
- [ ] **Step 4: Verify directory structure matches target**
|
|
659
|
+
|
|
660
|
+
```bash
|
|
661
|
+
find tests -name "*.spec.ts" | sort
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
Expected output:
|
|
665
|
+
```
|
|
666
|
+
tests/interaction/editable-label.spec.ts
|
|
667
|
+
tests/interaction/editable-span-escape.spec.ts
|
|
668
|
+
tests/measurement/width-provider-comparison.spec.ts
|
|
669
|
+
tests/regression/defect-406.spec.ts
|
|
670
|
+
tests/visual/html-rendering.spec.ts
|
|
671
|
+
tests/visual/svg-parity.spec.ts
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
- [ ] **Step 5: Commit (if any cleanup needed)**
|
|
675
|
+
|
|
676
|
+
```bash
|
|
677
|
+
git add -A
|
|
678
|
+
git commit -m "Final cleanup after E2E test reorganization"
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
---
|
|
682
|
+
|
|
683
|
+
## Summary of Changes
|
|
684
|
+
|
|
685
|
+
| Metric | Before | After |
|
|
686
|
+
|--------|--------|-------|
|
|
687
|
+
| Spec files | 21 | 6 |
|
|
688
|
+
| HTML fixtures | 37 | ~14 (unique pages only) |
|
|
689
|
+
| Lines in `vertical.spec.ts` | 147 (11 copy-paste blocks) | 0 (absorbed into html-rendering.spec.ts) |
|
|
690
|
+
| Lines in `svg-parity.spec.ts` | 553 (inline DSL) | ~25 (imports from test-cases) |
|
|
691
|
+
| DSL source of truth | 3 places | 1 (`compare-cases.js`) |
|
|
692
|
+
| Test organization | Flat | 4 subdirectories by type |
|
|
693
|
+
|
|
694
|
+
## Risk Mitigation
|
|
695
|
+
|
|
696
|
+
- **Snapshot names change** — The new `html-rendering.spec.ts` uses `${name}.png` naming. Old snapshots used various names like `should-load-the-home-page.png`, `creation.png`, etc. We generate fresh snapshots in Task 5 and verify they match visually.
|
|
697
|
+
- **fixture.html rendering differs from dedicated HTML** — The `main-cy.ts` script renders `<pre class="zenuml">` content. The parameterized template sets `textContent` before `main-cy.ts` runs (script is `type="module"`, deferred). Test in Task 1 confirms this.
|
|
698
|
+
- **CI snapshot mismatch** — Linux snapshots will need regenerating. Run `bun pw:update` in CI or update manually after merge.
|