@sun-asterisk/sungen 2.1.0 → 2.2.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.
- package/README.md +78 -51
- package/dist/cli/index.js +1 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts +6 -1
- package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
- package/dist/generators/test-generator/adapters/playwright/templates/scenario.hbs +0 -4
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/drag-action.hbs +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +11 -0
- 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/actions/toggle-action.hbs +1 -0
- 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 +1 -0
- 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 +1 -0
- package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +1 -0
- 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/adapters/playwright/templates/test-file.hbs +25 -0
- package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
- package/dist/generators/test-generator/code-generator.js +41 -3
- package/dist/generators/test-generator/code-generator.js.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/assertion-patterns.js +58 -6
- package/dist/generators/test-generator/patterns/assertion-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/form-patterns.js +3 -3
- package/dist/generators/test-generator/patterns/form-patterns.js.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.d.ts.map +1 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.js +86 -1
- package/dist/generators/test-generator/patterns/interaction-patterns.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/template-engine.d.ts +6 -0
- package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
- package/dist/generators/test-generator/template-engine.js +1 -0
- package/dist/generators/test-generator/template-engine.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 +4 -0
- package/dist/orchestrator/project-initializer.d.ts.map +1 -1
- package/dist/orchestrator/project-initializer.js +49 -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 +11 -0
- package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +8 -4
- 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/{copilot-skill-error-mapping.md → github-skill-sungen-error-mapping.md} +14 -3
- package/{src/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +11 -7
- 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 +256 -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/package.json +1 -1
- package/src/cli/index.ts +1 -1
- package/src/generators/test-generator/adapters/adapter-interface.ts +7 -1
- package/src/generators/test-generator/adapters/playwright/templates/scenario.hbs +0 -4
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/drag-action.hbs +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/actions/expand-action.hbs +11 -0
- 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/actions/toggle-action.hbs +1 -0
- 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 +1 -0
- 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 +1 -0
- package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/sorted-assertion.hbs +1 -0
- 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/adapters/playwright/templates/test-file.hbs +25 -0
- package/src/generators/test-generator/code-generator.ts +50 -8
- package/src/generators/test-generator/patterns/assertion-patterns.ts +62 -6
- package/src/generators/test-generator/patterns/form-patterns.ts +3 -3
- package/src/generators/test-generator/patterns/interaction-patterns.ts +93 -1
- package/src/generators/test-generator/patterns/navigation-patterns.ts +2 -2
- package/src/generators/test-generator/template-engine.ts +4 -0
- package/src/generators/test-generator/utils/selector-resolver.ts +27 -204
- package/src/orchestrator/project-initializer.ts +60 -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 +11 -0
- package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +8 -4
- 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/{copilot-skill-error-mapping.md → github-skill-sungen-error-mapping.md} +14 -3
- package/{dist/orchestrator/templates/ai-instructions/copilot-skill-gherkin-syntax.md → src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md} +11 -7
- 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 +256 -0
- package/src/orchestrator/templates/playwright.config.ts +3 -1
- package/src/orchestrator/templates/readme.md +78 -101
|
@@ -1,59 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: make-test
|
|
3
|
-
description: '
|
|
3
|
+
description: 'Generate selectors, compile, and run Playwright tests — auto-fixes selectors on failure'
|
|
4
4
|
argument-hint: [screen-name]
|
|
5
|
-
allowed-tools: Read, Grep, Bash, Glob, Edit
|
|
5
|
+
allowed-tools: Read, Grep, Bash, Glob, Edit, AskUserQuestion
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Role
|
|
9
9
|
|
|
10
|
-
You are a **Senior Developer** specialized in Playwright test debugging. You diagnose test failures, fix selectors/test-data
|
|
10
|
+
You are a **Senior Developer** specialized in Playwright test debugging. You generate selectors from live pages, diagnose test failures, and fix selectors/test-data using the `sungen-selector-fix`, `sungen-selector-keys`, and `sungen-error-mapping` skills.
|
|
11
11
|
|
|
12
12
|
## Parameters
|
|
13
13
|
|
|
14
|
-
Parse from `$ARGUMENTS
|
|
15
|
-
- **screen** — screen name (e.g., `login`, `dashboard`)
|
|
16
|
-
|
|
17
|
-
If missing, ask the user.
|
|
14
|
+
Parse **screen** from `$ARGUMENTS`. If missing, ask the user.
|
|
18
15
|
|
|
19
16
|
## Steps
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
sungen generate --screen <screen>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
If fails, fix source files per `sungen-error-mapping` skill and retry.
|
|
32
|
-
|
|
33
|
-
### 3. Run tests
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npx playwright test specs/screens/<screen>/<screen>.spec.ts
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
If pass → Step 5. If fail → Step 4.
|
|
40
|
-
|
|
41
|
-
### 4. Fix and retry (max 5 attempts)
|
|
42
|
-
|
|
43
|
-
Per attempt:
|
|
44
|
-
1. Read Playwright error output
|
|
45
|
-
2. Map error to fix using `sungen-error-mapping` skill
|
|
46
|
-
3. Fix `selectors.yaml` or `test-data.yaml`
|
|
47
|
-
4. Recompile: `sungen generate --screen <screen>`
|
|
48
|
-
5. Retest
|
|
49
|
-
|
|
50
|
-
### 5. Fallback — AI fix .spec.ts
|
|
51
|
-
|
|
52
|
-
After 5 failed attempts, ask user:
|
|
53
|
-
> Tests still failing. Would you like me to directly fix the `.spec.ts` file?
|
|
54
|
-
|
|
55
|
-
If yes: read `.spec.ts`, fix locators/assertions, mark with `// AI-fixed: <reason>`
|
|
56
|
-
|
|
57
|
-
### 6. Confirm
|
|
58
|
-
|
|
59
|
-
Show: pass/fail, attempt count, files changed.
|
|
18
|
+
1. Verify `qa/screens/<screen>/` has `.feature` + `test-data.yaml`. If not → `/sungen:make-tc` first.
|
|
19
|
+
2. Generate `selectors.yaml` from live page using `sungen-selector-fix` and `sungen-selector-keys` skills.
|
|
20
|
+
3. Compile: `sungen generate --screen <screen>`
|
|
21
|
+
4. Run: `npx playwright test specs/screens/<screen>/<screen>.spec.ts`
|
|
22
|
+
5. If fail → fix selectors/test-data per `sungen-selector-fix` + `sungen-error-mapping` skills, retry (max 5).
|
|
23
|
+
6. After 5 fails → ask user about direct `.spec.ts` fix.
|
|
24
|
+
7. Show: pass/fail, attempt count, files changed.
|
|
@@ -12,7 +12,7 @@ Given a login page, here are the 3 files you generate:
|
|
|
12
12
|
|
|
13
13
|
**qa/screens/login/features/login.feature**
|
|
14
14
|
```gherkin
|
|
15
|
-
@auth
|
|
15
|
+
@no-auth
|
|
16
16
|
Feature: Login Screen
|
|
17
17
|
|
|
18
18
|
Scenario: Successful login
|
|
@@ -73,12 +73,14 @@ When exploring a page to generate test files:
|
|
|
73
73
|
Only use: `browser_navigate`, `browser_snapshot`, `browser_click`, `browser_fill_form`, `browser_evaluate`.
|
|
74
74
|
|
|
75
75
|
To browse authenticated pages via MCP:
|
|
76
|
-
1.
|
|
77
|
-
2. If
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
1. `browser_navigate` to `baseURL`
|
|
77
|
+
2. If redirected to login, ask the user to log in manually:
|
|
78
|
+
> "This page requires login. Please log in using the browser. Confirm when you're done."
|
|
79
|
+
3. Once confirmed, `browser_navigate` to the target page and take `browser_snapshot`
|
|
80
|
+
|
|
81
|
+
**Never use `sungen makeauth`.** Always let the user log in manually via the MCP browser.
|
|
82
|
+
**NEVER use `browser_evaluate` to inject cookies or localStorage.** It causes size limit issues and server 500 errors.
|
|
83
|
+
**Minimize navigations** — take one snapshot per page, do not navigate repeatedly.
|
|
82
84
|
|
|
83
85
|
## Commands
|
|
84
86
|
|
|
@@ -86,5 +88,4 @@ To browse authenticated pages via MCP:
|
|
|
86
88
|
sungen add --screen <name> --path <url-path> # Create screen
|
|
87
89
|
sungen generate --screen <name> # Compile to .spec.ts
|
|
88
90
|
sungen generate --all # Compile all
|
|
89
|
-
sungen makeauth <role> # Capture auth state
|
|
90
91
|
```
|
|
@@ -17,6 +17,17 @@ 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
|
+
|
|
20
31
|
## Sungen Errors → Fix
|
|
21
32
|
|
|
22
33
|
| Error | Fix |
|
|
@@ -4,13 +4,13 @@ description: 'Sungen Gherkin patterns, selector types, and YAML key rules. Auto-
|
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## Step Patterns (
|
|
7
|
+
## Step Patterns (65 patterns)
|
|
8
8
|
|
|
9
9
|
### Setup
|
|
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
|
|
|
@@ -22,6 +22,7 @@ User clear [T] field # clear input
|
|
|
22
22
|
User check [T] checkbox # check
|
|
23
23
|
User uncheck [T] checkbox # uncheck
|
|
24
24
|
User select [T] dropdown with {{v}} # select option
|
|
25
|
+
User toggle [T] switch # toggle switch/checkbox
|
|
25
26
|
User upload [T] file with {{f}} # file upload
|
|
26
27
|
```
|
|
27
28
|
|
|
@@ -32,6 +33,9 @@ User click [T] button # click
|
|
|
32
33
|
User click [T] button with {{v}} # click with text match
|
|
33
34
|
User double click [T] element # double click
|
|
34
35
|
User hover [T] icon # hover
|
|
36
|
+
User drag [T] to [T2] # drag and drop
|
|
37
|
+
User expand [T] row # expand (aria-expanded)
|
|
38
|
+
User collapse [T] row # collapse (aria-expanded)
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
### Keyboard
|
|
@@ -86,7 +90,7 @@ User click [Act] in [Table] table row with {{f}} # action in row
|
|
|
86
90
|
|
|
87
91
|
### States
|
|
88
92
|
|
|
89
|
-
`hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty`
|
|
93
|
+
`hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected` `sorted ascending` `sorted descending`
|
|
90
94
|
|
|
91
95
|
### Element Types
|
|
92
96
|
|
|
@@ -94,7 +98,7 @@ User click [Act] in [Table] table row with {{f}} # action in row
|
|
|
94
98
|
|
|
95
99
|
## YAML Keys
|
|
96
100
|
|
|
97
|
-
`[Reference]` → **lowercase,
|
|
101
|
+
`[Reference]` → **lowercase, keep Unicode**: `[Search Content]` → `search content:`, `[Thời gian]` → `thời gian:`
|
|
98
102
|
|
|
99
103
|
## Selectors (priority order)
|
|
100
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
|