@sun-asterisk/sungen 2.1.1 → 2.2.1
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/README.md +78 -51
- package/dist/cli/index.js +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
- package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
- package/dist/generators/test-generator/code-generator.d.ts +4 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +19 -0
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/patterns/navigation-patterns.js +2 -2
- package/dist/generators/test-generator/patterns/navigation-patterns.js.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.d.ts +15 -8
- package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
- package/dist/generators/test-generator/utils/selector-resolver.js +26 -197
- package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
- package/dist/orchestrator/project-initializer.d.ts +8 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +68 -4
- package/dist/orchestrator/project-initializer.js.map +1 -1
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
- package/dist/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
- package/dist/orchestrator/templates/ai-instructions/claude-config.md +9 -8
- package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +29 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -2
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
- package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
- package/dist/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
- package/dist/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +56 -0
- package/{src/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +5 -5
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
- package/dist/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
- package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +257 -0
- package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
- package/dist/orchestrator/templates/playwright.config.js +3 -1
- package/dist/orchestrator/templates/playwright.config.js.map +1 -1
- package/dist/orchestrator/templates/playwright.config.ts +3 -1
- package/dist/orchestrator/templates/readme.md +78 -101
- package/dist/orchestrator/templates/specs-base.d.ts +4 -0
- package/dist/orchestrator/templates/specs-base.d.ts.map +1 -0
- package/dist/orchestrator/templates/specs-base.js +70 -0
- package/dist/orchestrator/templates/specs-base.js.map +1 -0
- package/dist/orchestrator/templates/specs-base.ts +73 -0
- package/package.json +1 -1
- package/src/cli/index.ts +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-editor-action.hbs +1 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/checked-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/contain-text-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/count-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-filter-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-role-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/disabled-with-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/empty-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/enabled-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/focused-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/have-text-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-dialog-heading-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-filter-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-role-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/hidden-with-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/is-hidden-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/label-value-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/list-item-count-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/loading-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/not-checked-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/page-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/selected-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-filter.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-cell-by-index.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-column-exists.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-empty.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-count.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-exists.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/table-row-not-exists.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-dialog-heading-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-locator-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-role-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-value-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/visible-with-variable-assertion.hbs +0 -1
- package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +1 -1
- package/src/generators/test-generator/code-generator.ts +21 -0
- package/src/generators/test-generator/patterns/navigation-patterns.ts +2 -2
- package/src/generators/test-generator/utils/selector-resolver.ts +27 -204
- package/src/orchestrator/project-initializer.ts +84 -5
- package/src/orchestrator/templates/ai-instructions/claude-cmd-add-screen.md +4 -3
- package/src/orchestrator/templates/ai-instructions/claude-cmd-make-tc.md +11 -46
- package/src/orchestrator/templates/ai-instructions/claude-cmd-make-test.md +11 -46
- package/src/orchestrator/templates/ai-instructions/claude-config.md +9 -8
- package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +29 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +2 -2
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +206 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +19 -21
- package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +256 -0
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-screen.md +14 -17
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-tc.md +16 -47
- package/src/orchestrator/templates/ai-instructions/copilot-cmd-make-test.md +16 -47
- package/src/orchestrator/templates/ai-instructions/copilot-config.md +8 -7
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +56 -0
- package/{dist/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +5 -5
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +206 -0
- package/src/orchestrator/templates/ai-instructions/{copilot-skill-selector-keys.md → github-skill-sungen-selector-keys.md} +22 -24
- package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +257 -0
- package/src/orchestrator/templates/playwright.config.ts +3 -1
- package/src/orchestrator/templates/readme.md +78 -101
- package/src/orchestrator/templates/specs-base.ts +73 -0
- package/dist/orchestrator/templates/ai-instructions/copilot-skill-error-mapping.md +0 -27
- package/src/orchestrator/templates/ai-instructions/copilot-skill-error-mapping.md +0 -27
|
@@ -17,6 +17,35 @@ user-invocable: false
|
|
|
17
17
|
| not a select | set `variant: 'custom'` |
|
|
18
18
|
| Frame not found | fix `frame` value |
|
|
19
19
|
|
|
20
|
+
## Auth Errors → Fix
|
|
21
|
+
|
|
22
|
+
| Symptom | Fix |
|
|
23
|
+
|---|---|
|
|
24
|
+
| Tests redirect to login page | `specs/.auth/<role>.json` missing or expired. Tell user: `sungen makeauth <role> --url <baseURL>` |
|
|
25
|
+
| `storageState` file not found | Run `sungen makeauth <role> --url <baseURL>` to create auth state |
|
|
26
|
+
| Most tests timeout on first step | Auth expired — re-run `sungen makeauth <role> --url <baseURL>` |
|
|
27
|
+
| Page shows home/login instead of target | SPA routing + expired auth. Re-run `sungen makeauth`, add `wait for` step after navigation |
|
|
28
|
+
|
|
29
|
+
**Never run `sungen makeauth` yourself.** Always tell the user to run it manually.
|
|
30
|
+
|
|
31
|
+
## Performance Errors → Fix (specs/base.ts)
|
|
32
|
+
|
|
33
|
+
All generated `.spec.ts` files import from `specs/base.ts`. This shared file handles context caching, navigation skip, and overlay cleanup.
|
|
34
|
+
|
|
35
|
+
| Symptom | Fix in `specs/base.ts` |
|
|
36
|
+
|---|---|
|
|
37
|
+
| Server returns 429 (rate limited) | Context caching broken — check `contextCache` Map reuses sessions per `storageState` |
|
|
38
|
+
| Tests slow even with `--workers=1` | Navigation skip not working — check `goto` patch compares `currentPath === url` |
|
|
39
|
+
| Previous test's modal blocks next test | Overlay cleanup insufficient — improve Escape/click dismiss logic |
|
|
40
|
+
| All tests fail on first navigation | `page.url()` is `about:blank` — check try/catch in goto patch |
|
|
41
|
+
| Multiple session invalidation errors | Too many contexts created — ensure `contextCache.get(cacheKey)` returns existing context |
|
|
42
|
+
|
|
43
|
+
**Rules:**
|
|
44
|
+
- `base.ts` changes affect ALL tests — edit carefully
|
|
45
|
+
- Small project-specific tweaks are OK (e.g., custom overlay dismiss, timeout tuning, extra wait logic)
|
|
46
|
+
- Do NOT move individual selector/data fixes into `base.ts` — those belong in `selectors.yaml` / `test-data.yaml`
|
|
47
|
+
- If unsure whether a fix belongs in `base.ts` or selectors, ask the user
|
|
48
|
+
|
|
20
49
|
## Sungen Errors → Fix
|
|
21
50
|
|
|
22
51
|
| Error | Fix |
|
|
@@ -10,7 +10,7 @@ user-invocable: false
|
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
User is on [T] page # navigate to page
|
|
13
|
-
User
|
|
13
|
+
User is on [T] page with {{v}} # navigate with data (e.g., detail page with ID)
|
|
14
14
|
User is logged in | is not logged in # auth state
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -98,7 +98,7 @@ User click [Act] in [Table] table row with {{f}} # action in row
|
|
|
98
98
|
|
|
99
99
|
## YAML Keys
|
|
100
100
|
|
|
101
|
-
`[Reference]` → **lowercase,
|
|
101
|
+
`[Reference]` → **lowercase, keep Unicode**: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
|
|
102
102
|
|
|
103
103
|
## Selectors (priority order)
|
|
104
104
|
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-selector-fix
|
|
3
|
+
description: 'Selector generation and fixing strategy for make-test — explores live page, generates selectors.yaml, auto-fixes on test failure. Auto-loaded by make-test command.'
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Selector Generation & Fix Strategy
|
|
8
|
+
|
|
9
|
+
### When to Generate Selectors
|
|
10
|
+
|
|
11
|
+
Selectors are generated during `/sungen:make-test`, NOT during `/sungen:make-tc`. This ensures selectors are always validated against the live page.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### Step 1: Authenticate
|
|
16
|
+
|
|
17
|
+
1. Read `baseURL` from `playwright.config.ts`
|
|
18
|
+
2. `browser_navigate` to `baseURL`
|
|
19
|
+
3. If redirected to login, ask the user to log in manually:
|
|
20
|
+
> "This page requires login. Please log in using the browser. Confirm when you're done."
|
|
21
|
+
4. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
|
|
22
|
+
|
|
23
|
+
**Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
|
|
24
|
+
**Never use `browser_evaluate` to inject cookies or localStorage.** Use `browser_evaluate` only to read DOM info (e.g. detect `data-testid` attributes, check element properties).
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Step 2: Build an Element Catalog from the Snapshot
|
|
29
|
+
|
|
30
|
+
**Never guess or infer selector names from Gherkin labels. Always copy exact values from the snapshot.**
|
|
31
|
+
|
|
32
|
+
After taking the snapshot, mentally catalog ALL accessible elements:
|
|
33
|
+
|
|
34
|
+
- **Buttons**: list each `button "..."` with its exact accessible name
|
|
35
|
+
- **Links**: list each `link "..."` with its exact accessible name
|
|
36
|
+
- **Headings**: list each `heading "..."` with level and exact name
|
|
37
|
+
- **Inputs**: list each `textbox`, `searchbox`, `combobox` — note if it has an accessible name or not
|
|
38
|
+
- **Regions/landmarks**: `region "..."`, `navigation "..."`, `dialog "..."`
|
|
39
|
+
- **Images**: `img "..."` with accessible name (alt text)
|
|
40
|
+
|
|
41
|
+
Then check for `data-testid` attributes (more stable than accessible names):
|
|
42
|
+
```js
|
|
43
|
+
// browser_evaluate — read-only, safe:
|
|
44
|
+
Array.from(document.querySelectorAll('[data-testid]'))
|
|
45
|
+
.map(e => ({ testid: e.dataset.testid, tag: e.tagName, text: e.textContent.trim().slice(0, 60) }))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Step 3: Map Gherkin Labels → Selectors
|
|
51
|
+
|
|
52
|
+
For each `[Reference]` in the `.feature` file, find the best match in the element catalog.
|
|
53
|
+
|
|
54
|
+
#### Selector priority (use first applicable)
|
|
55
|
+
|
|
56
|
+
| Priority | type | When to use |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| 1 | `testid` | `data-testid` attribute exists |
|
|
59
|
+
| 2 | `role` + exact name | Interactive elements (button, link, heading) |
|
|
60
|
+
| 3 | `placeholder` | Input with visible placeholder text |
|
|
61
|
+
| 4 | `label` | Form field with `<label>` association |
|
|
62
|
+
| 5 | `locator` (CSS / aria attr) | No accessible name (e.g. bare searchbox, icon button) |
|
|
63
|
+
| 6 | `text` | Static text only — avoid for dynamic/data-driven content |
|
|
64
|
+
|
|
65
|
+
#### The exact name rule
|
|
66
|
+
|
|
67
|
+
Copy the accessible name **character-for-character** from the snapshot. Do not transform, translate, or infer from the Gherkin label.
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
# BAD — name inferred from Gherkin label, not from snapshot
|
|
71
|
+
notification bell:
|
|
72
|
+
type: 'role'
|
|
73
|
+
value: 'button'
|
|
74
|
+
name: 'Notification Bell'
|
|
75
|
+
|
|
76
|
+
# GOOD — exact name from snapshot: button "Notifications"
|
|
77
|
+
notification bell:
|
|
78
|
+
type: 'role'
|
|
79
|
+
value: 'button'
|
|
80
|
+
name: 'Notifications'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### When there is no accessible name
|
|
84
|
+
|
|
85
|
+
Use a `locator` with a CSS attribute selector or ARIA role:
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
search field:
|
|
89
|
+
type: 'locator'
|
|
90
|
+
value: '[role="searchbox"]'
|
|
91
|
+
|
|
92
|
+
icon button:
|
|
93
|
+
type: 'locator'
|
|
94
|
+
value: '[aria-label="Close"]'
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
### Step 4: Handle Dynamic Content
|
|
100
|
+
|
|
101
|
+
For elements whose text changes between test runs (list items, card data, user-generated content, timestamps):
|
|
102
|
+
|
|
103
|
+
**Never use `type: text` with a specific value** — it breaks when data changes.
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
# BAD — specific text breaks when data changes
|
|
107
|
+
card title:
|
|
108
|
+
type: 'text'
|
|
109
|
+
value: 'Some specific title'
|
|
110
|
+
|
|
111
|
+
# GOOD — structural: first heading inside a card container
|
|
112
|
+
card title:
|
|
113
|
+
type: 'role'
|
|
114
|
+
value: 'heading'
|
|
115
|
+
nth: 1 # skip page-level headings, get first card heading
|
|
116
|
+
|
|
117
|
+
# BEST — if the app has data-testid
|
|
118
|
+
card title:
|
|
119
|
+
type: 'testid'
|
|
120
|
+
value: 'card-title'
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
To determine the correct `nth` offset, count how many matching elements appear before the target in the snapshot (e.g. how many headings come before the first card heading).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Step 5: Handle SPA / Client-side Routing
|
|
128
|
+
|
|
129
|
+
Many modern apps (Next.js, Nuxt, SvelteKit, etc.) return the same HTML shell for all URLs and route client-side. `domcontentloaded` fires on the shell before the target page renders.
|
|
130
|
+
|
|
131
|
+
**Symptom**: Tests see a different page than expected (e.g. home page instead of `/dashboard`).
|
|
132
|
+
|
|
133
|
+
**Fix in the feature file**: Add an explicit assertion after navigation to confirm the correct page has loaded before proceeding:
|
|
134
|
+
|
|
135
|
+
```gherkin
|
|
136
|
+
Scenario: VP-UI-001 Some test
|
|
137
|
+
Given User is on [Dashboard] page
|
|
138
|
+
Then User see [Dashboard Title] heading is visible ← confirms page loaded
|
|
139
|
+
When User click [Some Button] button
|
|
140
|
+
...
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The "page loaded" check should use a **stable, always-visible element** on that specific page — typically the main page heading.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### Step 6: Handle Multiple Matches (strict mode)
|
|
148
|
+
|
|
149
|
+
When an element appears more than once (e.g. desktop + mobile nav, repeated list items), add `nth`:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
nav link:
|
|
153
|
+
type: 'role'
|
|
154
|
+
value: 'link'
|
|
155
|
+
name: 'Dashboard'
|
|
156
|
+
nth: 0 # first occurrence (desktop nav)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Use `nth: 0` for the first match of dynamic/repeated elements.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Auto-Infer (skip YAML entry)
|
|
164
|
+
|
|
165
|
+
Many elements don't need a YAML entry — sungen auto-infers from the Gherkin label:
|
|
166
|
+
|
|
167
|
+
| Gherkin | Auto-inferred locator |
|
|
168
|
+
|---|---|
|
|
169
|
+
| `[Submit] button` | `getByRole('button', { name: 'Submit' })` |
|
|
170
|
+
| `[Home] link` | `getByRole('link', { name: 'Home' })` |
|
|
171
|
+
| `[Welcome] heading` | `getByRole('heading', { name: 'Welcome' })` |
|
|
172
|
+
| `[Email] field` | `getByPlaceholder('Email')` |
|
|
173
|
+
| `[Success] text` | `getByText('Success')` |
|
|
174
|
+
|
|
175
|
+
**Only add a YAML entry when auto-infer won't work:**
|
|
176
|
+
- The accessible name differs from the Gherkin label
|
|
177
|
+
- Needs `nth` to disambiguate
|
|
178
|
+
- Needs `testid` or CSS locator
|
|
179
|
+
- Is dynamic content (needs structural selector)
|
|
180
|
+
- Is a bare input with no label or placeholder
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### Fix Loop on Test Failure
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
attempt = 0
|
|
188
|
+
while attempt < 5:
|
|
189
|
+
compile → run test
|
|
190
|
+
if pass → done
|
|
191
|
+
read error-context.md in test-results/ → check exact snapshot state at failure time
|
|
192
|
+
fix selectors.yaml or test-data.yaml
|
|
193
|
+
recompile → attempt++
|
|
194
|
+
if still failing → ask user about direct .spec.ts fix
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Always read the error context snapshot first** — it shows the exact page state when the test failed, which is more reliable than re-navigating with MCP.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
### Key Rules (from sungen-selector-keys)
|
|
202
|
+
|
|
203
|
+
- `[Reference]` → lowercase, keep Unicode: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
|
|
204
|
+
- Keys use **spaces** (not dots) as word separators
|
|
205
|
+
- Same label, different element types → add `--type` suffix
|
|
206
|
+
- Same label, nth occurrence → add `--N` suffix
|
|
@@ -6,28 +6,26 @@ user-invocable: false
|
|
|
6
6
|
|
|
7
7
|
## Key Generation: `[Reference]` → YAML key
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Copy the text from `[Reference]` as-is, then lowercase. Unicode characters (Vietnamese, Japanese, etc.) are preserved.
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
[Submit] → submit
|
|
13
|
-
[Search Content] → search
|
|
14
|
-
[User's Profile] →
|
|
15
|
-
[Thời gian] →
|
|
16
|
-
[Địa điểm] →
|
|
17
|
-
[ログイン] →
|
|
18
|
-
[パスワード] →
|
|
19
|
-
[Page 2] → page
|
|
20
|
-
[Kudos Detail Modal] → kudos
|
|
13
|
+
[Search Content] → search content
|
|
14
|
+
[User's Profile] → user's profile
|
|
15
|
+
[Thời gian] → thời gian
|
|
16
|
+
[Địa điểm] → địa điểm
|
|
17
|
+
[ログイン] → ログイン
|
|
18
|
+
[パスワード] → パスワード
|
|
19
|
+
[Page 2] → page 2
|
|
20
|
+
[Kudos Detail Modal] → kudos detail modal
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
**Rules:**
|
|
24
|
-
1.
|
|
25
|
-
2.
|
|
26
|
-
3.
|
|
27
|
-
4.
|
|
28
|
-
5.
|
|
29
|
-
6. Trim, then spaces → dots
|
|
30
|
-
7. **NEVER use spaces, underscores, or uppercase in YAML keys**
|
|
24
|
+
1. Lowercase the text
|
|
25
|
+
2. Trim leading/trailing whitespace
|
|
26
|
+
3. Collapse multiple spaces into one
|
|
27
|
+
4. **Keep all Unicode characters as-is** (Vietnamese diacritics, Japanese, etc.)
|
|
28
|
+
5. **Keys use spaces** (not dots) as word separators
|
|
31
29
|
|
|
32
30
|
## Type-Suffixed Keys
|
|
33
31
|
|
|
@@ -35,12 +33,12 @@ When the same label is used for different element types, add `--type` suffix:
|
|
|
35
33
|
|
|
36
34
|
```yaml
|
|
37
35
|
# [Add Campaign] button AND [Add Campaign] text
|
|
38
|
-
add
|
|
36
|
+
add campaign--button:
|
|
39
37
|
type: 'role'
|
|
40
38
|
value: 'button'
|
|
41
39
|
name: 'Add Campaign'
|
|
42
40
|
|
|
43
|
-
add
|
|
41
|
+
add campaign--text:
|
|
44
42
|
type: 'text'
|
|
45
43
|
value: 'Add Campaign'
|
|
46
44
|
```
|
|
@@ -61,11 +59,11 @@ Type aliases (normalized automatically):
|
|
|
61
59
|
When targeting a specific occurrence by index, add `--N` suffix:
|
|
62
60
|
|
|
63
61
|
```yaml
|
|
64
|
-
# [
|
|
65
|
-
|
|
62
|
+
# [Gửi lời cảm ơn] button 3
|
|
63
|
+
gửi lời cảm ơn--3:
|
|
66
64
|
type: 'role'
|
|
67
65
|
value: 'button'
|
|
68
|
-
name: '
|
|
66
|
+
name: 'Gửi lời cảm ơn'
|
|
69
67
|
```
|
|
70
68
|
|
|
71
69
|
## Lookup Priority
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sungen-tc-generation
|
|
3
|
+
description: 'Exhaustive test case generation strategy — section-focused, 20+ scenarios per viewpoint per section, Gherkin + test-data only, no selectors. Auto-loaded by make-tc command.'
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Test Case Generation Strategy
|
|
8
|
+
|
|
9
|
+
### Goal
|
|
10
|
+
|
|
11
|
+
Generate **focused, high-quality test cases per screen section** with **at least 20 scenarios per viewpoint category**. Output only `.feature` and `test-data.yaml` — selectors are deferred to `/sungen:make-test`.
|
|
12
|
+
|
|
13
|
+
### Update Mode (existing test cases)
|
|
14
|
+
|
|
15
|
+
When the `.feature` file already has scenarios, read it first and summarize what exists:
|
|
16
|
+
|
|
17
|
+
> This screen already has **57 scenarios**:
|
|
18
|
+
> - Section: Filters & Search — 22 scenarios (UI: 7, VAL: 8, LOGIC: 5, SEC: 2)
|
|
19
|
+
> - Section: User Table — 23 scenarios (UI: 13, LOGIC: 11, SEC: 3)
|
|
20
|
+
> - Section: Pagination — 12 scenarios (UI: 4, LOGIC: 6, SEC: 2)
|
|
21
|
+
>
|
|
22
|
+
> What would you like to do?
|
|
23
|
+
> 1. **Add new sections** — keep existing, add tests for uncovered sections
|
|
24
|
+
> 2. **Add viewpoints to existing sections** — e.g., more edge cases, more security tests
|
|
25
|
+
> 3. **Replace all** — start fresh
|
|
26
|
+
|
|
27
|
+
For options 1 and 2:
|
|
28
|
+
- Read the existing scenarios to understand current coverage and the highest `VP-<CAT>-<NNN>` number
|
|
29
|
+
- Continue numbering from the next available number (e.g., if last is `VP-UI-024`, start at `VP-UI-025`)
|
|
30
|
+
- **Append** new scenarios to the end of the relevant section — never modify or delete existing scenarios
|
|
31
|
+
- Merge new test-data variables into `test-data.yaml` without overwriting existing ones
|
|
32
|
+
|
|
33
|
+
For option 3:
|
|
34
|
+
- Overwrite both `.feature` and `test-data.yaml` completely
|
|
35
|
+
|
|
36
|
+
### Page Exploration & Auth
|
|
37
|
+
|
|
38
|
+
Use Playwright MCP to explore the live page. If the page requires authentication:
|
|
39
|
+
1. `browser_navigate` to `baseURL` (from `playwright.config.ts`)
|
|
40
|
+
2. If redirected to login, ask the user to log in manually:
|
|
41
|
+
> "This page requires login. Please log in using the browser. Confirm when you're done."
|
|
42
|
+
3. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
|
|
43
|
+
|
|
44
|
+
**Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
|
|
45
|
+
|
|
46
|
+
### Single Screen Focus
|
|
47
|
+
|
|
48
|
+
**One screen = one URL path.** Only generate test cases for elements visible on the target page.
|
|
49
|
+
|
|
50
|
+
- Navigate to the target screen path — do NOT explore sibling paths (e.g., testing `/admin/users` should not scan `/admin/review`)
|
|
51
|
+
- Take ONE snapshot of the target page — do not click links to navigate away
|
|
52
|
+
- If a link goes to a different path, test only that the link is visible and clickable — the destination page is a SEPARATE screen
|
|
53
|
+
- If a modal/dialog opens on the same page, that IS part of this screen
|
|
54
|
+
- Each screen gets its own `qa/screens/<name>/` directory — never mix screens
|
|
55
|
+
|
|
56
|
+
#### Detail screens with dynamic IDs
|
|
57
|
+
|
|
58
|
+
For screens like `/admin/users/:id` or `/products/:slug`:
|
|
59
|
+
1. Navigate to the **list page** first via MCP browser to find a real record ID
|
|
60
|
+
2. Use that ID in the page selector value
|
|
61
|
+
3. Use `User is on [X] page` — sungen resolves the path from the selector
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# selectors.yaml — full path with real ID (generated during make-test)
|
|
65
|
+
user detail:
|
|
66
|
+
type: 'page'
|
|
67
|
+
value: '/admin/users/de42d800-0f5a-490e-9dcf-344fedbd34a5'
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```gherkin
|
|
71
|
+
Scenario: VP-UI-001 User detail displays name
|
|
72
|
+
Given User is on [User Detail] page
|
|
73
|
+
And User wait for [User Name] heading is visible
|
|
74
|
+
Then User see [User Name] heading with {{user_name}}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Note: the selector uses a hardcoded ID from the live page. If the record is deleted, update the ID in `selectors.yaml`.
|
|
78
|
+
|
|
79
|
+
### Section-Focused Approach
|
|
80
|
+
|
|
81
|
+
After exploring the page, identify distinct **sections** based on common UI patterns. Present them as a numbered list and ask the user which to focus on.
|
|
82
|
+
|
|
83
|
+
#### Common Section Patterns
|
|
84
|
+
|
|
85
|
+
Identify which patterns exist on the screen:
|
|
86
|
+
|
|
87
|
+
| Pattern | Elements to look for |
|
|
88
|
+
|---|---|
|
|
89
|
+
| **Header / Navigation** | Logo, nav links, breadcrumbs, user menu, notifications, language selector |
|
|
90
|
+
| **Form** | Input fields, dropdowns, checkboxes, radio buttons, date pickers, file uploads, submit/cancel buttons |
|
|
91
|
+
| **Data Table** | Column headers, sortable columns, row data, row actions, bulk actions, column filters |
|
|
92
|
+
| **Search & Filters** | Search input, filter dropdowns, clear/reset, active filter tags |
|
|
93
|
+
| **Card Grid / List** | Cards with title/image/description, load more, infinite scroll |
|
|
94
|
+
| **Pagination** | Previous/next buttons, page numbers, page size selector, total count |
|
|
95
|
+
| **Tabs / Accordion** | Tab headers, tab panels, expand/collapse |
|
|
96
|
+
| **Modal / Dialog** | Open trigger, close button, form inside modal, confirmation dialog |
|
|
97
|
+
| **Sidebar** | Stats, quick actions, related links, mini widgets |
|
|
98
|
+
| **File Upload** | Drop zone, file picker, progress bar, file list, delete |
|
|
99
|
+
| **Rich Text Editor** | Toolbar, content area, formatting buttons, preview |
|
|
100
|
+
| **Carousel / Slider** | Prev/next arrows, dots/indicators, auto-play, swipe |
|
|
101
|
+
|
|
102
|
+
Example output:
|
|
103
|
+
|
|
104
|
+
> This screen has the following sections:
|
|
105
|
+
> 1. Header (logo, navigation tabs, user menu)
|
|
106
|
+
> 2. Create Form (name, email, role dropdown, department, submit)
|
|
107
|
+
> 3. User Table (columns: name, email, status, actions; sortable, filterable)
|
|
108
|
+
> 4. Pagination (previous/next, page indicator)
|
|
109
|
+
>
|
|
110
|
+
> Which sections do you want to create test cases for? (e.g., "2, 3" or "all")
|
|
111
|
+
|
|
112
|
+
For each selected section, generate **20+ scenarios per applicable viewpoint**. Skip viewpoint categories that don't apply.
|
|
113
|
+
|
|
114
|
+
Present a test plan summary and wait for user confirmation before generating files.
|
|
115
|
+
|
|
116
|
+
### Viewpoint Categories
|
|
117
|
+
|
|
118
|
+
| VP Category | Description |
|
|
119
|
+
|---|---|
|
|
120
|
+
| **UI/UX** | Default appearance, element visibility, default states |
|
|
121
|
+
| **Validation** | Input validation, error messages, edge cases. **Must explore live page via MCP to capture actual error messages before writing tests. Use `User see {{error_var}}` pattern — never assert just "is visible".** |
|
|
122
|
+
| **Logic** | Business logic, interactions, state changes |
|
|
123
|
+
| **Security** | Auth guards, injection, permission checks |
|
|
124
|
+
|
|
125
|
+
### Coverage Checklist per Section Pattern
|
|
126
|
+
|
|
127
|
+
Apply the relevant checklist based on the section pattern:
|
|
128
|
+
|
|
129
|
+
#### Form sections
|
|
130
|
+
- **UI/UX**: All fields visible, labels correct, default values, placeholder text, required indicators
|
|
131
|
+
- **Validation**: Empty submit, each required field empty, invalid format (email, phone, URL), min/max length, special chars, unicode, XSS, SQL injection, whitespace-only, boundary values — **assert exact error messages via `User see {{error_var}}`**, store texts in test-data.yaml
|
|
132
|
+
- **Logic**: Successful submit, submit with all optional fields, edit existing record, cancel resets form, field dependencies (show/hide), auto-complete, date range validation
|
|
133
|
+
- **Security**: CSRF protection, unauthorized submit, role-based field visibility, input sanitization
|
|
134
|
+
|
|
135
|
+
#### Data Table sections
|
|
136
|
+
- **UI/UX**: All columns visible, column headers, row data displays correctly, empty state, loading state, action buttons visible
|
|
137
|
+
- **Validation**: N/A (read-only) or inline edit validation
|
|
138
|
+
- **Logic**: Sort ascending/descending per sortable column, filter by each column, search within table, row action menu (edit/delete/view), bulk select, bulk action, row click navigation, column resize
|
|
139
|
+
- **Security**: Cannot access other users' data, action permissions per role, data not exposed in DOM
|
|
140
|
+
|
|
141
|
+
#### Search & Filter sections
|
|
142
|
+
- **UI/UX**: Search field visible, filter buttons visible, clear button state
|
|
143
|
+
- **Validation**: Empty search, special chars, SQL injection, XSS, very long text, unicode/emoji, whitespace, partial match, case insensitive
|
|
144
|
+
- **Logic**: Apply single filter, combine multiple filters, clear single filter, clear all filters, search + filter combined, filter persists across pagination, no results state
|
|
145
|
+
- **Security**: Injection via search, injection via filter params
|
|
146
|
+
|
|
147
|
+
#### Pagination sections
|
|
148
|
+
- **UI/UX**: Page indicator visible, previous disabled on page 1, next enabled
|
|
149
|
+
- **Logic**: Next page, previous page, navigate to last page, boundary (first/last), page indicator updates, data refreshes on navigation
|
|
150
|
+
- **Security**: Filters persist across pages, search persists, cannot access page beyond max
|
|
151
|
+
|
|
152
|
+
#### Modal / Dialog sections
|
|
153
|
+
- **UI/UX**: Modal opens, close button visible, overlay visible, form fields inside modal
|
|
154
|
+
- **Validation**: Submit empty form in modal, field validation inside modal
|
|
155
|
+
- **Logic**: Open modal, close with X, close with Escape, close with overlay click, submit success closes modal, submit error keeps modal open
|
|
156
|
+
- **Security**: Cannot open unauthorized modals, CSRF on modal submit
|
|
157
|
+
|
|
158
|
+
#### Card Grid / List sections
|
|
159
|
+
- **UI/UX**: Cards display all expected fields (title, image, description, metadata), empty state, loading state
|
|
160
|
+
- **Logic**: Click card navigates to detail, load more / infinite scroll, card action buttons (like, share, delete), responsive layout
|
|
161
|
+
- **Security**: User-generated content sanitized, cannot access other users' cards
|
|
162
|
+
|
|
163
|
+
#### Carousel / Slider sections
|
|
164
|
+
- **UI/UX**: Arrows visible, indicators visible, current slide highlighted
|
|
165
|
+
- **Logic**: Next slide, previous slide, wrap at end, auto-play, indicator click navigates, swipe gesture
|
|
166
|
+
- **Security**: N/A
|
|
167
|
+
|
|
168
|
+
#### Tabs / Accordion sections
|
|
169
|
+
- **UI/UX**: All tabs visible, active tab highlighted, default tab selected
|
|
170
|
+
- **Logic**: Switch tabs, content updates per tab, deep link to tab, accordion expand/collapse, only one accordion open at a time
|
|
171
|
+
- **Security**: Tab content respects permissions
|
|
172
|
+
|
|
173
|
+
### General Coverage Dimensions (aim for 20+ total per viewpoint)
|
|
174
|
+
|
|
175
|
+
**Happy paths (3-5):** Standard flow, all optional fields, minimum required
|
|
176
|
+
**Edge cases (5-8):** Empty, max length, special chars, unicode/CJK/emoji, whitespace, leading/trailing spaces, overflow
|
|
177
|
+
**Boundary values (3-5):** At min/max limit, one above/below, zero/null
|
|
178
|
+
**Negative cases (3-5):** Invalid format, missing required, wrong type, injection attempts
|
|
179
|
+
**State transitions (2-4):** Before/after action, undo, cancel mid-flow
|
|
180
|
+
**Combinatorial (2-4):** Multiple invalid fields, valid+invalid combos, different roles
|
|
181
|
+
|
|
182
|
+
### SPA Wait-For Steps
|
|
183
|
+
|
|
184
|
+
If the page is an SPA (Next.js, Nuxt, React Router, etc.), add a `wait for` step after navigation:
|
|
185
|
+
|
|
186
|
+
```gherkin
|
|
187
|
+
Given User is on [Screen] page
|
|
188
|
+
And User wait for [Page Title] heading is visible
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
For scenarios needing dynamic data, add a second wait:
|
|
192
|
+
|
|
193
|
+
```gherkin
|
|
194
|
+
And User wait for [Data Element] button is visible
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Output Files
|
|
198
|
+
|
|
199
|
+
**1. Feature file** — `qa/screens/<screen>/features/<screen>.feature`
|
|
200
|
+
|
|
201
|
+
Group by section, then by viewpoint within each section:
|
|
202
|
+
|
|
203
|
+
```gherkin
|
|
204
|
+
@auth:role
|
|
205
|
+
Feature: <Screen> Screen
|
|
206
|
+
|
|
207
|
+
# ============================================================
|
|
208
|
+
# Section: Create User Form
|
|
209
|
+
# ============================================================
|
|
210
|
+
|
|
211
|
+
# --- UI/UX (20+) ---
|
|
212
|
+
|
|
213
|
+
Scenario: VP-UI-001 Name field is visible
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
# --- Validation (20+) ---
|
|
217
|
+
|
|
218
|
+
Scenario: VP-VAL-001 Submit with empty name
|
|
219
|
+
...
|
|
220
|
+
|
|
221
|
+
# ============================================================
|
|
222
|
+
# Section: User Table
|
|
223
|
+
# ============================================================
|
|
224
|
+
|
|
225
|
+
# --- UI/UX (20+) ---
|
|
226
|
+
|
|
227
|
+
Scenario: VP-UI-025 Table displays all columns
|
|
228
|
+
...
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Naming convention:** `VP-<CATEGORY>-<NNN>` prefix in Scenario name.
|
|
232
|
+
|
|
233
|
+
**2. Test data file** — `qa/screens/<screen>/test-data/<screen>.yaml`
|
|
234
|
+
|
|
235
|
+
Group variables by section:
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
# ============================================================
|
|
239
|
+
# Create User Form
|
|
240
|
+
# ============================================================
|
|
241
|
+
valid_name: 'John Doe'
|
|
242
|
+
valid_email: 'john@example.com'
|
|
243
|
+
empty_input: ''
|
|
244
|
+
special_chars: '!@#$%^&*()'
|
|
245
|
+
|
|
246
|
+
# ============================================================
|
|
247
|
+
# User Table
|
|
248
|
+
# ============================================================
|
|
249
|
+
sort_column: 'Name'
|
|
250
|
+
search_term: 'John'
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Do NOT Generate
|
|
254
|
+
|
|
255
|
+
- `selectors.yaml` — this is created during `/sungen:make-test`
|
|
256
|
+
- Playwright code — sungen compiles Gherkin to Playwright
|
|
@@ -1,41 +1,38 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
name: sungen-add-screen
|
|
3
|
+
description: 'Add a new Sungen screen — scaffolds directories and delegates to /sungen-make-tc for test case creation'
|
|
4
|
+
argument-hint: '[screen-name] [url-path]'
|
|
5
|
+
agent: 'agent'
|
|
4
6
|
tools: ['terminal']
|
|
5
7
|
---
|
|
6
8
|
|
|
9
|
+
**Input**: Screen name and URL path (e.g., `/sungen-add-screen login /login`).
|
|
10
|
+
|
|
7
11
|
You are adding a new Sungen screen for test generation.
|
|
8
12
|
|
|
9
13
|
## Parameters
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
- **
|
|
13
|
-
- **path** — URL path (e.g., `/login`, `/dashboard`, `/settings`)
|
|
14
|
-
|
|
15
|
-
If **screen** is missing, ask: "What is the screen name? (e.g., `login`, `dashboard`)"
|
|
16
|
-
If **path** is missing, ask: "What is the URL path? (e.g., `/login`, `/dashboard`)"
|
|
15
|
+
- **screen** — ${input:screen:screen name (e.g., login, dashboard)}
|
|
16
|
+
- **path** — ${input:path:URL path (e.g., /login, /dashboard)}
|
|
17
17
|
|
|
18
18
|
## Steps
|
|
19
19
|
|
|
20
20
|
### 1. Scaffold the screen
|
|
21
21
|
|
|
22
|
-
Run
|
|
22
|
+
Run with #tool:terminal:
|
|
23
23
|
```bash
|
|
24
|
-
sungen add --screen
|
|
24
|
+
sungen add --screen ${input:screen} --path ${input:path}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
### 2. Create test cases
|
|
28
28
|
|
|
29
29
|
Ask the user: "Would you like to create test cases now?"
|
|
30
30
|
|
|
31
|
-
If yes,
|
|
32
|
-
- Exploring the live page or analyzing static designs
|
|
33
|
-
- Gathering test viewpoints (UI/UX, Validation, Logic, Security)
|
|
34
|
-
- Generating the 3 files (feature, selectors, test-data)
|
|
31
|
+
If yes, tell the user to run `/sungen-make-tc ${input:screen}`.
|
|
35
32
|
|
|
36
33
|
### 3. Confirm
|
|
37
34
|
|
|
38
35
|
Tell the user what was created and next steps:
|
|
39
|
-
- If the page requires authentication
|
|
40
|
-
-
|
|
41
|
-
- Run `
|
|
36
|
+
- If the page requires authentication, the user will be asked to log in via the MCP browser during `/sungen-make-tc`
|
|
37
|
+
- Run `/sungen-make-tc` to create test cases
|
|
38
|
+
- Run `/sungen-make-test` to generate selectors, compile, and run tests
|