@sun-asterisk/sungen 2.5.2 → 2.6.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.
Files changed (170) hide show
  1. package/dist/cli/commands/add-flow.d.ts +3 -0
  2. package/dist/cli/commands/add-flow.d.ts.map +1 -0
  3. package/dist/cli/commands/add-flow.js +27 -0
  4. package/dist/cli/commands/add-flow.js.map +1 -0
  5. package/dist/cli/commands/delivery.d.ts.map +1 -1
  6. package/dist/cli/commands/delivery.js +95 -60
  7. package/dist/cli/commands/delivery.js.map +1 -1
  8. package/dist/cli/commands/generate.d.ts.map +1 -1
  9. package/dist/cli/commands/generate.js +38 -6
  10. package/dist/cli/commands/generate.js.map +1 -1
  11. package/dist/cli/index.js +3 -1
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +1 -0
  14. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  15. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +1 -0
  16. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  17. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  18. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +2 -2
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -1
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -1
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -1
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +2 -2
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +1 -0
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +2 -1
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +1 -2
  26. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -1
  27. package/dist/generators/test-generator/code-generator.d.ts +1 -0
  28. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  29. package/dist/generators/test-generator/code-generator.js +30 -12
  30. package/dist/generators/test-generator/code-generator.js.map +1 -1
  31. package/dist/generators/test-generator/step-mapper.d.ts +4 -0
  32. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  33. package/dist/generators/test-generator/step-mapper.js +7 -0
  34. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  35. package/dist/generators/test-generator/template-engine.d.ts +1 -0
  36. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  37. package/dist/generators/test-generator/template-engine.js +1 -1
  38. package/dist/generators/test-generator/template-engine.js.map +1 -1
  39. package/dist/generators/test-generator/utils/data-resolver.d.ts +3 -20
  40. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  41. package/dist/generators/test-generator/utils/data-resolver.js +23 -66
  42. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  43. package/dist/generators/test-generator/utils/selector-resolver.d.ts +2 -6
  44. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  45. package/dist/generators/test-generator/utils/selector-resolver.js +18 -80
  46. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  47. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  48. package/dist/orchestrator/ai-rules-updater.js +4 -0
  49. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  50. package/dist/orchestrator/flow-manager.d.ts +22 -0
  51. package/dist/orchestrator/flow-manager.d.ts.map +1 -0
  52. package/dist/orchestrator/flow-manager.js +251 -0
  53. package/dist/orchestrator/flow-manager.js.map +1 -0
  54. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  55. package/dist/orchestrator/project-initializer.js +1 -0
  56. package/dist/orchestrator/project-initializer.js.map +1 -1
  57. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +88 -0
  58. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -8
  59. package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +8 -6
  60. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +15 -11
  61. package/dist/orchestrator/templates/ai-instructions/claude-config.md +41 -10
  62. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +12 -0
  63. package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +19 -18
  64. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +12 -0
  65. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +52 -0
  66. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +31 -3
  67. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +45 -0
  68. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +69 -0
  69. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +30 -0
  70. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +86 -0
  71. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +13 -10
  72. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +16 -15
  73. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +9 -7
  74. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +21 -17
  75. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +40 -9
  76. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +12 -0
  77. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +19 -18
  78. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +12 -0
  79. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +52 -0
  80. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +31 -3
  81. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +45 -0
  82. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +70 -0
  83. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +30 -0
  84. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
  85. package/dist/orchestrator/templates/playwright.config.js +3 -1
  86. package/dist/orchestrator/templates/playwright.config.js.map +1 -1
  87. package/dist/orchestrator/templates/playwright.config.ts +4 -1
  88. package/dist/orchestrator/templates/specs-base.d.ts.map +1 -1
  89. package/dist/orchestrator/templates/specs-base.js +11 -56
  90. package/dist/orchestrator/templates/specs-base.js.map +1 -1
  91. package/dist/orchestrator/templates/specs-base.ts +11 -61
  92. package/dist/orchestrator/templates/specs-test-data.d.ts +3 -1
  93. package/dist/orchestrator/templates/specs-test-data.d.ts.map +1 -1
  94. package/dist/orchestrator/templates/specs-test-data.js +10 -2
  95. package/dist/orchestrator/templates/specs-test-data.js.map +1 -1
  96. package/dist/orchestrator/templates/specs-test-data.ts +9 -2
  97. package/package.json +1 -1
  98. package/src/cli/commands/add-flow.ts +25 -0
  99. package/src/cli/commands/delivery.ts +109 -58
  100. package/src/cli/commands/generate.ts +43 -6
  101. package/src/cli/index.ts +3 -1
  102. package/src/generators/test-generator/adapters/adapter-interface.ts +1 -1
  103. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +1 -1
  104. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +2 -2
  105. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -1
  106. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -1
  107. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -1
  108. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +2 -2
  109. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +1 -0
  110. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +2 -1
  111. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +1 -2
  112. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -1
  113. package/src/generators/test-generator/code-generator.ts +32 -14
  114. package/src/generators/test-generator/step-mapper.ts +8 -0
  115. package/src/generators/test-generator/template-engine.ts +2 -2
  116. package/src/generators/test-generator/utils/data-resolver.ts +25 -77
  117. package/src/generators/test-generator/utils/selector-resolver.ts +23 -109
  118. package/src/orchestrator/ai-rules-updater.ts +5 -0
  119. package/src/orchestrator/flow-manager.ts +243 -0
  120. package/src/orchestrator/project-initializer.ts +1 -0
  121. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +88 -0
  122. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -8
  123. package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +8 -6
  124. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +15 -11
  125. package/src/orchestrator/templates/ai-instructions/claude-config.md +41 -10
  126. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +12 -0
  127. package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +19 -18
  128. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +12 -0
  129. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +52 -0
  130. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +31 -3
  131. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +45 -0
  132. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +69 -0
  133. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +30 -0
  134. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +86 -0
  135. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +13 -10
  136. package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +16 -15
  137. package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +9 -7
  138. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +21 -17
  139. package/src/orchestrator/templates/ai-instructions/copilot-config.md +40 -9
  140. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +12 -0
  141. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +19 -18
  142. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +12 -0
  143. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +52 -0
  144. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +31 -3
  145. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +45 -0
  146. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +70 -0
  147. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +30 -0
  148. package/src/orchestrator/templates/playwright.config.ts +4 -1
  149. package/src/orchestrator/templates/specs-base.ts +11 -61
  150. package/src/orchestrator/templates/specs-test-data.ts +9 -2
  151. package/dist/utils/feature-finder.d.ts +0 -9
  152. package/dist/utils/feature-finder.d.ts.map +0 -1
  153. package/dist/utils/feature-finder.js +0 -67
  154. package/dist/utils/feature-finder.js.map +0 -1
  155. package/dist/utils/screen-paths.d.ts +0 -10
  156. package/dist/utils/screen-paths.d.ts.map +0 -1
  157. package/dist/utils/screen-paths.js +0 -73
  158. package/dist/utils/screen-paths.js.map +0 -1
  159. package/dist/utils/selector-loader.d.ts +0 -6
  160. package/dist/utils/selector-loader.d.ts.map +0 -1
  161. package/dist/utils/selector-loader.js +0 -20
  162. package/dist/utils/selector-loader.js.map +0 -1
  163. package/dist/utils/test-data-loader.d.ts +0 -6
  164. package/dist/utils/test-data-loader.d.ts.map +0 -1
  165. package/dist/utils/test-data-loader.js +0 -20
  166. package/dist/utils/test-data-loader.js.map +0 -1
  167. package/src/utils/feature-finder.ts +0 -33
  168. package/src/utils/screen-paths.ts +0 -37
  169. package/src/utils/selector-loader.ts +0 -23
  170. package/src/utils/test-data-loader.ts +0 -23
@@ -6,7 +6,7 @@ user-invocable: false
6
6
 
7
7
  ## Purpose
8
8
 
9
- Export test cases from Sungen screens to a standardized CSV file (format BM-2-901-13) for QA delivery.
9
+ Export test cases from Sungen screens and flows to a standardized CSV file (format BM-2-901-13) for QA delivery.
10
10
 
11
11
  **This skill delegates all heavy work to the `sungen delivery` CLI.** The CLI is the single source of truth for parsing logic — do NOT re-parse files in AI. Your role is only to:
12
12
 
@@ -19,18 +19,19 @@ Export test cases from Sungen screens to a standardized CSV file (format BM-2-90
19
19
  ## Architecture
20
20
 
21
21
  ```
22
- User → /sungen:delivery [screen...]
22
+ User → /sungen:delivery [name...]
23
23
 
24
24
 
25
25
  sungen delivery CLI (deterministic — no AI tokens)
26
- ├─ Scope detection (no-arg = all screens)
27
- ├─ Pre-flight source checks per screen
26
+ ├─ Scope detection (no-arg = all screens + flows)
27
+ ├─ Auto-detect: qa/flows/<name>/ flow, qa/screens/<name>/ → screen
28
+ ├─ Pre-flight source checks per target
28
29
  ├─ Parse .feature (metadata)
29
30
  ├─ Parse .spec.ts (resolved Playwright code — source of truth)
30
31
  ├─ Parse test-data.yaml (resolve {{vars}})
31
32
  ├─ Parse test-results/results.json (match test titles)
32
33
  ├─ Merge sources + generate CSV rows
33
- └─ Write qa/deliverables/<screen>-testcases.csv
34
+ └─ Write qa/deliverables/<name>-testcases.csv
34
35
  ```
35
36
 
36
37
  Source modules: `src/exporters/*.ts`
@@ -39,18 +40,18 @@ Source modules: `src/exporters/*.ts`
39
40
 
40
41
  ## Required sources (CLI pre-flight checks these)
41
42
 
42
- | # | Source | Path | Created by |
43
- |---|--------|------|------------|
44
- | 1 | Feature file | `qa/screens/<screen>/features/<screen>.feature` | `/sungen:add-screen` + `/sungen:create-test` |
45
- | 2 | Test data | `qa/screens/<screen>/test-data/<screen>.yaml` | `/sungen:create-test` |
46
- | 3 | Selectors | `qa/screens/<screen>/selectors/<screen>.yaml` | `/sungen:run-test` |
47
- | 4 | Compiled spec | `specs/generated/<screen>/<screen>.spec.ts` | `sungen generate` (during `/sungen:run-test`) |
48
- | 5 | Test results | `specs/generated/<screen>/<screen>-test-result.json` (per-screen) or `test-results/results.json` (global fallback) | `/sungen:run-test` |
43
+ | # | Source | Screen path | Flow path | Created by |
44
+ |---|--------|-------------|-----------|------------|
45
+ | 1 | Feature file | `qa/screens/<name>/features/<name>.feature` | `qa/flows/<name>/features/<name>.feature` | `add-screen`/`add-flow` + `create-test` |
46
+ | 2 | Test data | `qa/screens/<name>/test-data/<name>.yaml` | `qa/flows/<name>/test-data/<name>.yaml` | `create-test` |
47
+ | 3 | Selectors | `qa/screens/<name>/selectors/<name>.yaml` | `qa/flows/<name>/selectors/<name>.yaml` | `run-test` |
48
+ | 4 | Compiled spec | `specs/generated/<name>/<name>.spec.ts` | `specs/generated/flows/<name>/<name>.spec.ts` | `sungen generate` |
49
+ | 5 | Test results | `specs/generated/<name>/<name>-test-result.json` or `test-results/results.json` | `specs/generated/flows/<name>/<name>-test-result.json` or global fallback | `run-test` |
49
50
 
50
51
  **Sources 1-4 are blocking** — CLI aborts if any is missing.
51
52
  **Source 5 is optional** — CSV is still generated but Test Result/Date/Executor/Env columns are empty (all tests show as Pending).
52
53
 
53
- The CLI reads the **per-screen result file first** (co-located with `.spec.ts`), then falls back to the global `test-results/results.json`. Per-screen is preferred because the global file gets OVERWRITTEN each time Playwright runs, losing results from earlier screens.
54
+ The CLI reads the **per-target result file first** (co-located with `.spec.ts`), then falls back to the global `test-results/results.json`. Per-target is preferred because the global file gets OVERWRITTEN each time Playwright runs, losing results from earlier targets.
54
55
 
55
56
  ---
56
57
 
@@ -87,17 +88,17 @@ The CLI reads the **per-screen result file first** (co-located with `.spec.ts`),
87
88
  ## CLI command reference
88
89
 
89
90
  ```bash
90
- # Export all screens
91
+ # Export all screens and flows
91
92
  sungen delivery
92
93
 
93
- # Export specific screens
94
- sungen delivery kudos awards
94
+ # Export specific targets (auto-detects screen vs flow)
95
+ sungen delivery kudos awards nomination-flow
95
96
 
96
97
  # Skip pre-flight (CI only)
97
98
  sungen delivery --skip-preflight
98
99
 
99
- # Skip screens with blocking misses
100
+ # Skip targets with blocking misses
100
101
  sungen delivery --continue-on-missing
101
102
  ```
102
103
 
103
- Output: `qa/deliverables/<screen>-testcases.csv` (UTF-8 with BOM)
104
+ Output: `qa/deliverables/<name>-testcases.csv` (UTF-8 with BOM)
@@ -101,6 +101,18 @@ If `toHaveText` fails on an input → the Gherkin step has wrong target type. Fi
101
101
 
102
102
  ---
103
103
 
104
+ ## Flow-Specific Errors
105
+
106
+ | Error | Diagnosis | Fix |
107
+ |---|---|---|
108
+ | Navigation timeout between screens | Cross-screen transition takes too long or URL mismatch | Add explicit `wait for page` step between screen transitions in `.feature`. Verify target URL path |
109
+ | Selector `"screen:element"` not found | Namespace key missing or wrong format | Ensure colon-namespaced key in `selectors.yaml` is **quoted**: `"login:submit":`. Check screen prefix matches `[Screen:Element]` ref in Gherkin |
110
+ | Test data `screen.key` undefined | Phase namespace mismatch | Verify `test-data.yaml` uses dot-namespaced keys: `login.email`, `submission.nominee`. Keys must match `{{screen.key}}` refs in `.feature` |
111
+ | State lost between screens | Auth/session expired during multi-screen flow | Ensure all screens in the flow share the same `@auth:role` tag. Check if the app invalidates sessions on navigation |
112
+ | Duplicate selector key across screens | Two screens use same element name without namespace | Always use `[Screen:Element]` format in flow `.feature`. Selectors must use `"screen:element":` quoted keys |
113
+
114
+ ---
115
+
104
116
  ## Performance & Infrastructure Errors → Fix in `specs/base.ts`
105
117
 
106
118
  All generated `.spec.ts` import from `specs/base.ts` — shared context caching, navigation, overlay cleanup. AI **can and should** tune `base.ts` to match the project.
@@ -160,6 +160,57 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
160
160
  | `@afterEach` | Hook: runs after each test → `test.afterEach()` (custom cleanup) |
161
161
  | `@afterAll` | Hook: runs once after all tests → `test.afterAll()` |
162
162
 
163
+ ### `@flow` tag (E2E cross-screen testing)
164
+
165
+ `@flow` marks a feature as a **flow** — an E2E journey spanning multiple screens. Flows live in `qa/flows/<name>/` with their own selectors, test-data, and requirements.
166
+
167
+ **Key differences from screen tests:**
168
+
169
+ | Aspect | Screen (`qa/screens/`) | Flow (`qa/flows/`) |
170
+ |---|---|---|
171
+ | Scope | Single page | Multiple pages |
172
+ | Selectors | `[Element]` → own YAML | `[Screen:Element]` → own YAML (namespaced) |
173
+ | Test data | `{{variable}}` | `{{phase.variable}}` (namespaced by phase) |
174
+ | Tag | `@auto` / `@smoke` etc. | `@flow` (required at feature level) |
175
+
176
+ **Selector namespace format:** `[Screen:Element]` where colon separates screen prefix from element name. The YAML key is `"screen:element"` (quoted, lowercase).
177
+
178
+ ```gherkin
179
+ # Feature file
180
+ When User fill [Login:Email] field with {{login.email}}
181
+ And User click [Login:Submit] button
182
+ Then User see [Dashboard] page
183
+ When User click [Dashboard:Awards] link
184
+ ```
185
+
186
+ ```yaml
187
+ # selectors.yaml — keys are namespaced, quoted due to colon
188
+ "login:email":
189
+ type: 'testid'
190
+ value: 'email-input'
191
+
192
+ "login:submit":
193
+ type: 'role'
194
+ value: 'button'
195
+ name: 'Login'
196
+
197
+ dashboard:
198
+ type: 'page'
199
+ value: '/dashboard'
200
+
201
+ "dashboard:awards":
202
+ type: 'role'
203
+ value: 'link'
204
+ name: 'Awards'
205
+ ```
206
+
207
+ **Flow structure:**
208
+ - `Background:` — set starting page only (e.g., `Given User is on [Login] page`)
209
+ - Each `Scenario:` — one phase/step of the flow (login, navigate, submit, etc.)
210
+ - Page navigation between scenarios uses `[Screen] page` references
211
+
212
+ **CLI:** `sungen add-flow --flow <name>`, `sungen generate --flow <name>`, `sungen generate --all` (includes flows)
213
+
163
214
  ### @extend behavior
164
215
 
165
216
  - Tool executes **only Given→When** of `@steps` scenario (skips Then)
@@ -185,6 +236,7 @@ Options: `nth` `exact` `scope` `match` `variant` `frame` `contenteditable` `colu
185
236
  | Missing target type | `fill [email] with {{v}}` | `fill [email] field with {{v}}` |
186
237
  | Background with scope | `Background: ... And User is on [X] dialog` | Use `@steps` + `@extend` for scope-dependent flows |
187
238
  | `is on` after When | `When ... And User is on [X] dialog` | `And User see [X] dialog` or separate Given |
239
+ | Literal URL navigate | `User navigate to "/dashboard"` | `User is on [Dashboard] page` (add page selector in `selectors.yaml`) |
188
240
 
189
241
  ## Background vs @steps/@extend
190
242
 
@@ -24,6 +24,28 @@ Run tests in priority waves — catch fundamental issues early, fix critical pat
24
24
 
25
25
  If existing selectors already cover the feature file, **skip Phase 0** and go straight to compile + Phase 1.
26
26
 
27
+ ### Flow Mode: Screen Selector Reference
28
+
29
+ When running Phase 0 for a **flow** (`qa/flows/<name>/`), check existing screen selectors first before snapshotting live pages. Screen selectors are already verified and proven — reuse them to save time and reduce errors.
30
+
31
+ **Steps (before the standard Phase 0 steps):**
32
+
33
+ 1. **Parse screen references**: read the `.feature` file for `[Screen:Element]` references. Group by screen name (e.g., `Login`, `Awards`, `Dashboard`).
34
+ 2. **For each referenced screen**, check `qa/screens/<screen>/selectors/<screen>.yaml`:
35
+ - **If exists** → copy matching entries to the flow's `selectors.yaml`, remapping keys to namespace format:
36
+ - Screen key `submit` with screen `login` → flow key `"login:submit"`
37
+ - Screen key `email-field` with screen `login` → flow key `"login:email-field"`
38
+ - Preserve the full selector definition (type, value, name, etc.)
39
+ - Mark these entries as **verified** (no `@needs-live-verify` comment needed)
40
+ - **If not found** → add this screen to the "needs live snapshot" list
41
+ 3. **Elements not found in any screen selector** → also added to the "needs live snapshot" list
42
+ 4. **If "needs live snapshot" list is empty** → Phase 0 screen-reference covered everything, skip to compile
43
+ 5. **If "needs live snapshot" list is non-empty** → continue with the standard Phase 0 steps below, but only generate selectors for the missing elements (don't re-snapshot elements already copied from screens)
44
+
45
+ **Merge rule**: screen-referenced entries take priority over provisional (Figma-sourced) entries. If an element was previously generated from Figma with `@needs-live-verify`, the screen-verified entry replaces it.
46
+
47
+ **Important**: flow selectors remain private — they live in the flow's own YAML file. This is just initialization from screen data, not a runtime dependency.
48
+
27
49
  ### Steps
28
50
 
29
51
  1. **Confirm with the user**: *"Generate selectors from the live page via Playwright MCP now?"* — offer **Yes, scan live page** / **Skip (use existing selectors.yaml)** / **Cancel**.
@@ -39,9 +61,10 @@ If existing selectors already cover the feature file, **skip Phase 0** and go st
39
61
  - Selector priority: follow the table in **Diagnosis & Fix § Step 3** (`testid` > `role`+name > `placeholder` > `label` > `locator` > `text`).
40
62
  - Copy names **character-for-character** from the snapshot. Never infer from the Gherkin label.
41
63
  - If an element is auto-inferable per `sungen-selector-keys` § Auto-Infer, **omit it** from YAML — keep the file minimal.
42
- 7. **Merge, don't overwrite**: preserve the page selector and any user-authored entries in `selectors.yaml`. Only add missing keys.
43
- 8. **Show summary + confirm**: list the keys that will be added, ask the user to approve, then write the file.
44
- 9. **Compile**: `sungen generate --screen <screen>` then proceed to Phase 1.
64
+ 7. **Substring ambiguity check**: for each `role` + `name` selector, check if any other element in the snapshot has a name that **contains** this name as a substring (e.g., `"Đăng ký"` vs `"Đăng ký bằng Google"`). If yes → add `exact: true` to prevent strict mode violation at runtime.
65
+ 8. **Merge, don't overwrite**: preserve the page selector and any user-authored entries in `selectors.yaml`. Only add missing keys.
66
+ 9. **Show summary + confirm**: list the keys that will be added, ask the user to approve, then write the file.
67
+ 10. **Compile**: **Screen**: `sungen generate --screen <screen>`. **Flow**: `sungen generate --flow <flow>`. Then proceed to Phase 1.
45
68
 
46
69
  ### Common Phase 0 pitfalls
47
70
 
@@ -265,6 +288,7 @@ Array.from(document.querySelectorAll('[data-testid]'))
265
288
  Common fixes:
266
289
  - Name mismatch → copy exact name from snapshot
267
290
  - Multiple matches → add `nth` or `exact: true`
291
+ - Substring ambiguity (e.g., `"Submit"` matches `"Submit"` and `"Submit & Continue"`) → add `exact: true`
268
292
  - No accessible name → use `testid` or `locator` (CSS)
269
293
  - Element in iframe → add `frame` field
270
294
  - Dynamic content → use `testid` or structural `role` + `nth`
@@ -273,7 +297,11 @@ Common fixes:
273
297
 
274
298
  Always recompile before re-running:
275
299
  ```bash
300
+ # Screen
276
301
  sungen generate --screen <screen>
302
+
303
+ # Flow
304
+ sungen generate --flow <flow>
277
305
  ```
278
306
 
279
307
  Then re-run only the current phase's failing tests, not all tests.
@@ -27,6 +27,51 @@ Copy the text from `[Reference]` as-is, then lowercase. Unicode characters (Viet
27
27
  4. **Keep all Unicode characters as-is** (Vietnamese diacritics, Japanese, etc.)
28
28
  5. **Keys use spaces** (not dots) as word separators
29
29
 
30
+ ## Flow Namespaced Keys
31
+
32
+ In `@flow` features, selectors are namespaced by screen using colon: `[Screen:Element]` → YAML key `"screen:element"` (quoted).
33
+
34
+ ```
35
+ [Login:Email] → "login:email"
36
+ [Login:Submit] → "login:submit"
37
+ [Dashboard:Awards] → "dashboard:awards"
38
+ [Awards:Submit] → "awards:submit"
39
+ ```
40
+
41
+ **Rules:**
42
+ 1. Same lowercase + Unicode rules as standard keys
43
+ 2. Colon separates screen prefix from element name
44
+ 3. **YAML keys must be quoted** because of the colon: `"login:email":`
45
+ 4. Page references don't need prefix: `[Login]` → `login:` (page type)
46
+ 5. Prevents duplicate names across screens (e.g., `"login:submit"` vs `"awards:submit"`)
47
+
48
+ ```yaml
49
+ # Flow selectors — each screen section namespaced
50
+ login:
51
+ type: 'page'
52
+ value: '/login'
53
+
54
+ "login:email":
55
+ type: 'testid'
56
+ value: 'email-input'
57
+
58
+ "login:submit":
59
+ type: 'role'
60
+ value: 'button'
61
+ name: 'Login'
62
+
63
+ awards:
64
+ type: 'page'
65
+ value: '/awards'
66
+
67
+ "awards:submit":
68
+ type: 'role'
69
+ value: 'button'
70
+ name: 'Submit Award'
71
+ ```
72
+
73
+ **Type and nth suffixes still apply:** `"login:submit--button"`, `"awards:item--3"`
74
+
30
75
  ## Type-Suffixed Keys
31
76
 
32
77
  When the same label is used for different element types, add `--type` suffix:
@@ -251,3 +251,73 @@ valid_password: StagingPass456
251
251
  ```
252
252
 
253
253
  **Do NOT generate**: `selectors.yaml` (created during run-test), Playwright code (sungen compiles).
254
+
255
+ ---
256
+
257
+ ## Flow Test Generation
258
+
259
+ When generating tests for a **flow** (`qa/flows/<name>/`), adapt the strategy:
260
+
261
+ ### Structure
262
+
263
+ - **Background** — starting page only: `Given User is on [Login] page`
264
+ - **Scenarios** — each phase of the E2E journey as a separate scenario
265
+ - **Selector refs** — use `[Screen:Element]` namespace format (see `sungen-gherkin-syntax`)
266
+ - **Test data** — namespace by phase: `login.email`, `submission.nominee`
267
+ - **Feature tag** — `@flow` required at feature level
268
+
269
+ ### Flow vs Screen Differences
270
+
271
+ | Aspect | Screen | Flow |
272
+ |---|---|---|
273
+ | Section focus | UI patterns per section | Journey phases across screens |
274
+ | Viewpoints | VP-UI, VP-VAL, VP-LOGIC, VP-SEC per section | VP-LOGIC (flow transitions), VP-SEC (auth persistence), VP-VAL (cross-screen data) |
275
+ | Tier 1 focus | Happy path + required validation per section | Happy path through entire flow + auth + key error recovery |
276
+ | Background | Navigate to screen | Navigate to starting page |
277
+
278
+ ### Flow-specific scenarios to generate
279
+
280
+ | Category | Examples |
281
+ |---|---|
282
+ | **Happy path** | Complete flow end-to-end with valid data |
283
+ | **Auth persistence** | Auth state maintained across screen transitions |
284
+ | **Error recovery** | Invalid input mid-flow → fix → continue |
285
+ | **Incomplete flow** | User abandons at each phase → state cleanup |
286
+ | **Cross-screen data** | Data entered on screen A visible on screen B |
287
+
288
+ ### Output Format (Flow)
289
+
290
+ ```gherkin
291
+ @flow @auth:user
292
+ Feature: Award Submission Flow
293
+
294
+ Background:
295
+ Given User is on [Login] page
296
+
297
+ @critical
298
+ Scenario: User login successfully
299
+ When User fill [Login:Email] field with {{login.email}}
300
+ And User fill [Login:Password] field with {{login.password}}
301
+ And User click [Login:Submit] button
302
+ Then User see [Dashboard] page
303
+
304
+ @critical
305
+ Scenario: User navigates to awards and submits
306
+ Given User is on [Awards] page
307
+ When User fill [Awards:Nominee] field with {{submission.nominee}}
308
+ And User fill [Awards:Reason] field with {{submission.reason}}
309
+ And User click [Awards:Submit] button
310
+ Then User see [Awards:Success Message] text with {{submission.success_message}}
311
+ ```
312
+
313
+ ```yaml
314
+ # test-data — namespaced by phase
315
+ login:
316
+ email: "user@example.com"
317
+ password: "Password123"
318
+
319
+ submission:
320
+ nominee: "John Doe"
321
+ reason: "Outstanding contribution to the team"
322
+ success_message: "Award submitted successfully"
323
+ ```
@@ -89,6 +89,36 @@ Do NOT mark `@manual` when data is visible in snapshot or documented in spec —
89
89
 
90
90
  ---
91
91
 
92
+ ## Flow Review Additions
93
+
94
+ When reviewing a `@flow` feature (`qa/flows/<name>/`), apply standard scoring PLUS these flow-specific checks:
95
+
96
+ ### Syntax — additional checks
97
+ - `[Screen:Element]` format used consistently (not mixing bare `[Element]` refs)
98
+ - YAML keys quoted with colon: `"login:submit":` not `login:submit:`
99
+ - `@flow` tag present at feature level
100
+
101
+ ### Coverage — additional dimensions
102
+ | Dimension | Pts (from existing 40) | What to check |
103
+ |---|---|---|
104
+ | Screen transitions | (part of State transitions) | Each screen-to-screen navigation tested |
105
+ | Auth persistence | (part of Happy paths) | Auth state maintained across transitions |
106
+ | Error recovery mid-flow | (part of Negative cases) | Invalid input at each phase → fix → continue |
107
+ | Cross-screen data | (part of Edge cases) | Data entered on screen A asserted on screen B |
108
+
109
+ ### Viewpoint — flow-specific classification
110
+ - **VP-LOGIC** — screen transitions, navigation flow, auth persistence
111
+ - **VP-VAL** — cross-screen data consistency, form data carried across pages
112
+ - **VP-SEC** — auth state across redirects, permission changes mid-flow
113
+ - VP-UI is typically minimal in flows (focus on functionality over layout)
114
+
115
+ ### Checklist — flow-specific items
116
+ 11. **Missing screen transitions** — flow visits 4 screens but only 2 transitions tested? Add missing
117
+ 12. **Orphan scenarios** — scenario doesn't connect to previous/next phase? Flag broken flow
118
+ 13. **Selector namespace consistency** — mixing `[Submit]` and `[Login:Submit]` in same flow? Standardize
119
+
120
+ ---
121
+
92
122
  ## Unverified Selectors metric
93
123
 
94
124
  **When to check**: if `qa/screens/<screen>/selectors/<screen>.yaml` exists, count lines matching the pattern `@needs-live-verify`.
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.config.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAKH;;GAEG;;AACH,wBAyEG"}
1
+ {"version":3,"file":"playwright.config.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAKH;;GAEG;;AACH,wBA4EG"}
@@ -22,7 +22,7 @@ exports.default = (0, test_1.defineConfig)({
22
22
  /* Opt out of parallel tests on CI. */
23
23
  workers: process.env.CI ? 1 : 2,
24
24
  /* Global timeout per test */
25
- timeout: 10000,
25
+ timeout: 15000,
26
26
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
27
27
  /* JSON reporter is required by `sungen delivery` to populate test result columns in the exported CSV. */
28
28
  /* Output file path is controlled by PLAYWRIGHT_JSON_OUTPUT_NAME env var for per-screen isolation. */
@@ -34,6 +34,8 @@ exports.default = (0, test_1.defineConfig)({
34
34
  use: {
35
35
  /* Base URL to use in actions like `await page.goto('')`. */
36
36
  baseURL: 'https://example.com',
37
+ /* Per-action timeout (click, fill, etc.) */
38
+ actionTimeout: 10000,
37
39
  /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
38
40
  trace: 'on-first-retry',
39
41
  },
@@ -1 +1 @@
1
- {"version":3,"file":"playwright.config.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":";;AAAA,2CAAyD;AAEzD;;;GAGG;AACH,+BAA+B;AAC/B,2BAA2B;AAC3B,4DAA4D;AAE5D;;GAEG;AACH,kBAAe,IAAA,mBAAY,EAAC;IAC1B,OAAO,EAAE,mBAAmB;IAC5B,oCAAoC;IACpC,aAAa,EAAE,IAAI;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;IAC5B,sBAAsB;IACtB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,6BAA6B;IAC7B,OAAO,EAAE,KAAM;IACf,qEAAqE;IACrE,yGAAyG;IACzG,qGAAqG;IACrG,QAAQ,EAAE;QACR,CAAC,MAAM,CAAC;QACR,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,2BAA2B,EAAE,CAAC;KACjG;IACD,wGAAwG;IACxG,GAAG,EAAE;QACH,4DAA4D;QAC5D,OAAO,EAAE,qBAAqB;QAE9B,+FAA+F;QAC/F,KAAK,EAAE,gBAAgB;KACxB;IAED,2CAA2C;IAC3C,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,EAAE,GAAG,cAAO,CAAC,gBAAgB,CAAC,EAAE;SACtC;QAED;;;;;;;;;;;;;;;;;;;;;4CAqBoC;QACpC,IAAI;QACJ,4BAA4B;QAC5B,4DAA4D;QAC5D,KAAK;QACL,IAAI;QACJ,2BAA2B;QAC3B,8DAA8D;QAC9D,KAAK;KACN;IAED,yDAAyD;IACzD,eAAe;IACf,8BAA8B;IAC9B,kCAAkC;IAClC,0CAA0C;IAC1C,KAAK;CACN,CAAC,CAAC"}
1
+ {"version":3,"file":"playwright.config.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":";;AAAA,2CAAyD;AAEzD;;;GAGG;AACH,+BAA+B;AAC/B,2BAA2B;AAC3B,4DAA4D;AAE5D;;GAEG;AACH,kBAAe,IAAA,mBAAY,EAAC;IAC1B,OAAO,EAAE,mBAAmB;IAC5B,oCAAoC;IACpC,aAAa,EAAE,IAAI;IACnB,iFAAiF;IACjF,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;IAC5B,sBAAsB;IACtB,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,6BAA6B;IAC7B,OAAO,EAAE,KAAM;IACf,qEAAqE;IACrE,yGAAyG;IACzG,qGAAqG;IACrG,QAAQ,EAAE;QACR,CAAC,MAAM,CAAC;QACR,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,2BAA2B,EAAE,CAAC;KACjG;IACD,wGAAwG;IACxG,GAAG,EAAE;QACH,4DAA4D;QAC5D,OAAO,EAAE,qBAAqB;QAE9B,4CAA4C;QAC5C,aAAa,EAAE,KAAM;QAErB,+FAA+F;QAC/F,KAAK,EAAE,gBAAgB;KACxB;IAED,2CAA2C;IAC3C,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,EAAE,GAAG,cAAO,CAAC,gBAAgB,CAAC,EAAE;SACtC;QAED;;;;;;;;;;;;;;;;;;;;;4CAqBoC;QACpC,IAAI;QACJ,4BAA4B;QAC5B,4DAA4D;QAC5D,KAAK;QACL,IAAI;QACJ,2BAA2B;QAC3B,8DAA8D;QAC9D,KAAK;KACN;IAED,yDAAyD;IACzD,eAAe;IACf,8BAA8B;IAC9B,kCAAkC;IAClC,0CAA0C;IAC1C,KAAK;CACN,CAAC,CAAC"}
@@ -22,7 +22,7 @@ export default defineConfig({
22
22
  /* Opt out of parallel tests on CI. */
23
23
  workers: process.env.CI ? 1 : 2,
24
24
  /* Global timeout per test */
25
- timeout: 10_000,
25
+ timeout: 15_000,
26
26
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
27
27
  /* JSON reporter is required by `sungen delivery` to populate test result columns in the exported CSV. */
28
28
  /* Output file path is controlled by PLAYWRIGHT_JSON_OUTPUT_NAME env var for per-screen isolation. */
@@ -35,6 +35,9 @@ export default defineConfig({
35
35
  /* Base URL to use in actions like `await page.goto('')`. */
36
36
  baseURL: 'https://example.com',
37
37
 
38
+ /* Per-action timeout (click, fill, etc.) */
39
+ actionTimeout: 10_000,
40
+
38
41
  /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
39
42
  trace: 'on-first-retry',
40
43
  },
@@ -1 +1 @@
1
- {"version":3,"file":"specs-base.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAGxD,KAAK,aAAa,GAAG;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAOF,QAAA,MAAM,IAAI;iBACK,aAAa;yBACL,OAAO;kBACd,IAAI;qBACD,IAAI;wGA6GrB,CAAC;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"specs-base.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAExD,KAAK,aAAa,GAAG;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,QAAA,MAAM,IAAI;iBACK,aAAa;yBACL,OAAO;kBACd,IAAI;qBACD,IAAI;wGAiErB,CAAC;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC"}
@@ -3,72 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.expect = exports.test = void 0;
4
4
  const test_1 = require("@playwright/test");
5
5
  Object.defineProperty(exports, "expect", { enumerable: true, get: function () { return test_1.expect; } });
6
- // Share one context per storageState — avoids creating multiple sessions
7
- // that trigger server rate limiting or session invalidation
8
- const contextCache = new Map();
9
- const GOTO_PATCHED = Symbol('goto-patched');
10
6
  const test = test_1.test.extend({
11
7
  autoCleanup: [{}, { option: true }],
12
8
  screenshotOnFailure: [false, { option: true }],
13
9
  page: async ({ browser, storageState }, use) => {
14
- if (storageState) {
15
- const cacheKey = typeof storageState === 'string' ? storageState : JSON.stringify(storageState);
16
- let cached = contextCache.get(cacheKey);
17
- if (!cached) {
18
- const context = await browser.newContext({ storageState });
19
- const page = await context.newPage();
20
- cached = { context, page };
21
- contextCache.set(cacheKey, cached);
22
- }
23
- const page = cached.page;
24
- // Patch goto once: skip navigation if already on the target path
25
- if (!page[GOTO_PATCHED]) {
26
- const originalGoto = page.goto.bind(page);
27
- page.goto = async function (url, options) {
28
- try {
29
- const currentPath = new URL(page.url()).pathname;
30
- if (currentPath === url || currentPath === url + '/') {
31
- const hasOverlay = await page.evaluate(`(() => {
32
- const el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);
33
- if (!el) return false;
34
- let current = el;
35
- while (current && current !== document.body) {
36
- if (getComputedStyle(current).position === 'fixed') return true;
37
- current = current.parentElement;
38
- }
39
- return false;
40
- })()`).catch(() => true);
41
- if (hasOverlay) {
42
- return originalGoto(url, options);
43
- }
44
- return null;
45
- }
46
- }
47
- catch {
48
- // page.url() might be about:blank on first run
49
- }
50
- return originalGoto(url, options);
51
- };
52
- page[GOTO_PATCHED] = true;
53
- }
54
- await use(page);
55
- }
56
- else {
57
- // No storageState: fresh context (e.g., unauthenticated tests)
58
- const context = await browser.newContext();
59
- const page = await context.newPage();
60
- await use(page);
61
- await page.close();
62
- await context.close();
63
- }
10
+ const context = storageState
11
+ ? await browser.newContext({ storageState })
12
+ : await browser.newContext();
13
+ const page = await context.newPage();
14
+ await use(page);
15
+ await page.close();
16
+ await context.close();
64
17
  },
65
18
  // Auto-cleanup fixture: runs teardown after each test based on @cleanup:* tags
66
- _autoCleanup: [async ({ page, autoCleanup }, use) => {
19
+ _autoCleanup: [async ({ page, autoCleanup }, use, testInfo) => {
67
20
  await use();
21
+ // Only run cleanup when the test failed — avoids masking state for the next test
22
+ if (testInfo.status === testInfo.expectedStatus)
23
+ return;
68
24
  if (autoCleanup.overlay) {
69
25
  await page.keyboard.press('Escape').catch(() => { });
70
26
  await page.locator('body').click({ position: { x: 1, y: 1 }, force: true }).catch(() => { });
71
- // Dismiss persistent fixed overlays (modals, dialogs)
72
27
  const hasOverlay = await page.evaluate(`(() => {
73
28
  const el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);
74
29
  if (!el) return false;
@@ -1 +1 @@
1
- {"version":3,"file":"specs-base.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"specs-base.js","sourceRoot":"","sources":["../../../src/orchestrator/templates/specs-base.ts"],"names":[],"mappings":"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"}