@sun-asterisk/sungen 2.1.1 → 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/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/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 +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 +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/{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} +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 +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/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/patterns/navigation-patterns.ts +2 -2
- 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 +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/{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} +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 +256 -0
- package/src/orchestrator/templates/playwright.config.ts +3 -1
- package/src/orchestrator/templates/readme.md +78 -101
|
@@ -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. Use this when creating test cases for a screen with Gherkin scenarios.'
|
|
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 |
|
|
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
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright.config.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAKH;;GAEG;;AACH,
|
|
1
|
+
{"version":3,"file":"playwright.config.d.ts","sourceRoot":"","sources":["../../../src/orchestrator/templates/playwright.config.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAKH;;GAEG;;AACH,wBAoEG"}
|
|
@@ -20,7 +20,9 @@ exports.default = (0, test_1.defineConfig)({
|
|
|
20
20
|
/* Retry on CI only */
|
|
21
21
|
retries: process.env.CI ? 2 : 0,
|
|
22
22
|
/* Opt out of parallel tests on CI. */
|
|
23
|
-
workers: process.env.CI ? 1 :
|
|
23
|
+
workers: process.env.CI ? 1 : 2,
|
|
24
|
+
/* Global timeout per test */
|
|
25
|
+
timeout: 10000,
|
|
24
26
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
25
27
|
reporter: 'html',
|
|
26
28
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
@@ -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,
|
|
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,QAAQ,EAAE,MAAM;IAChB,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"}
|
|
@@ -20,7 +20,9 @@ export default defineConfig({
|
|
|
20
20
|
/* Retry on CI only */
|
|
21
21
|
retries: process.env.CI ? 2 : 0,
|
|
22
22
|
/* Opt out of parallel tests on CI. */
|
|
23
|
-
workers: process.env.CI ? 1 :
|
|
23
|
+
workers: process.env.CI ? 1 : 2,
|
|
24
|
+
/* Global timeout per test */
|
|
25
|
+
timeout: 10_000,
|
|
24
26
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
25
27
|
reporter: 'html',
|
|
26
28
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
@@ -17,11 +17,17 @@ sungen generate → compiles Gherkin + selectors + data → Playwright .spec.ts
|
|
|
17
17
|
│ ├── selectors/ # Element locator YAML mappings
|
|
18
18
|
│ └── test-data/ # Test data YAML values
|
|
19
19
|
├── specs/
|
|
20
|
-
│
|
|
21
|
-
|
|
20
|
+
│ └── generated/ # Auto-generated Playwright tests
|
|
21
|
+
├── .claude/
|
|
22
|
+
│ ├── commands/sungen/ # Claude Code slash commands
|
|
23
|
+
│ └── skills/ # Claude Code auto-loaded skills
|
|
22
24
|
├── .github/
|
|
23
|
-
│
|
|
24
|
-
└──
|
|
25
|
+
│ ├── copilot-instructions.md # AI rules for GitHub Copilot
|
|
26
|
+
│ └── prompts/ # Copilot slash commands
|
|
27
|
+
├── .vscode/
|
|
28
|
+
│ └── settings.json # Copilot auto-attach settings
|
|
29
|
+
├── CLAUDE.md # AI rules for Claude Code
|
|
30
|
+
└── playwright.config.ts # Playwright config (timeout: 10s, workers: 2)
|
|
25
31
|
```
|
|
26
32
|
|
|
27
33
|
## Workflow
|
|
@@ -32,45 +38,50 @@ Step 1 Step 2 Step 3
|
|
|
32
38
|
│ /add- │────────▶│ /make-tc │────────▶│ /make- │
|
|
33
39
|
│ screen │ │ │ │ test │
|
|
34
40
|
└──────────┘ └──────────┘ └──────────┘
|
|
35
|
-
Scaffold
|
|
36
|
-
directories
|
|
37
|
-
|
|
41
|
+
Scaffold Pick sections Generate
|
|
42
|
+
directories → design TCs selectors
|
|
43
|
+
→ generate → compile
|
|
44
|
+
.feature + → run tests
|
|
45
|
+
test-data → auto-fix
|
|
38
46
|
```
|
|
39
47
|
|
|
40
48
|
Use AI commands (Claude Code or GitHub Copilot) to drive the workflow:
|
|
41
49
|
|
|
42
50
|
### Step 1: Add a screen
|
|
43
51
|
|
|
44
|
-
| Claude Code | GitHub Copilot |
|
|
52
|
+
| Claude Code | GitHub Copilot (VS Code) |
|
|
45
53
|
|---|---|
|
|
46
|
-
| `/sungen:add-screen
|
|
54
|
+
| `/sungen:add-screen` | `/sungen-add-screen` |
|
|
47
55
|
|
|
48
56
|
Scaffolds `qa/screens/<name>/` with empty feature, selectors, and test-data files, then asks if you want to create test cases.
|
|
49
57
|
|
|
50
58
|
### Step 2: Create test cases
|
|
51
59
|
|
|
52
|
-
| Claude Code | GitHub Copilot |
|
|
60
|
+
| Claude Code | GitHub Copilot (VS Code) |
|
|
53
61
|
|---|---|
|
|
54
|
-
| `/sungen:make-tc login` |
|
|
62
|
+
| `/sungen:make-tc login` | `/sungen-make-tc login` |
|
|
55
63
|
|
|
56
|
-
AI acts as a **Senior QA Engineer**:
|
|
64
|
+
AI acts as a **Senior QA Engineer**:
|
|
65
|
+
1. Explores the live page via Playwright MCP (asks user to log in if auth needed)
|
|
66
|
+
2. Identifies screen sections → asks user which to focus on
|
|
67
|
+
3. Generates **20+ scenarios per viewpoint** (UI/UX, Validation, Logic, Security) for each section
|
|
68
|
+
4. Confirms test plan before generating `.feature` + `test-data.yaml`
|
|
57
69
|
|
|
58
70
|
### Step 3: Compile & run tests
|
|
59
71
|
|
|
60
|
-
| Claude Code | GitHub Copilot |
|
|
72
|
+
| Claude Code | GitHub Copilot (VS Code) |
|
|
61
73
|
|---|---|
|
|
62
|
-
| `/sungen:make-test login` |
|
|
74
|
+
| `/sungen:make-test login` | `/sungen-make-test login` |
|
|
63
75
|
|
|
64
|
-
AI acts as a **Senior Developer**:
|
|
76
|
+
AI acts as a **Senior Developer**:
|
|
77
|
+
1. Navigates to live page, takes snapshot, verifies DOM properties
|
|
78
|
+
2. Generates `selectors.yaml` from exact accessible names
|
|
79
|
+
3. Compiles Gherkin → Playwright `.spec.ts`
|
|
80
|
+
4. Runs tests, auto-fixes selectors on failure (up to 5 attempts)
|
|
65
81
|
|
|
66
|
-
### Auth setup
|
|
82
|
+
### Auth setup
|
|
67
83
|
|
|
68
|
-
If any page requires authentication,
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
sungen makeauth admin --url <baseURL>
|
|
72
|
-
# Opens browser → login manually → saves specs/.auth/admin.json
|
|
73
|
-
```
|
|
84
|
+
If any page requires authentication, the AI will ask you to **log in manually via the MCP browser** during Step 2 or Step 3. No separate auth command needed.
|
|
74
85
|
|
|
75
86
|
### Manual CLI commands
|
|
76
87
|
|
|
@@ -85,7 +96,24 @@ npx playwright test --ui # Interactive mode
|
|
|
85
96
|
|
|
86
97
|
---
|
|
87
98
|
|
|
88
|
-
##
|
|
99
|
+
## VS Code Copilot Setup
|
|
100
|
+
|
|
101
|
+
Add to `.vscode/settings.json` to auto-load Gherkin syntax when editing `.feature` files:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"github.copilot.chat.codeGeneration.instructions": [
|
|
106
|
+
{
|
|
107
|
+
"file": ".github/prompts/sungen-gherkin-syntax.prompt.md",
|
|
108
|
+
"applyTo": "**/*.feature"
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Gherkin Quick Reference
|
|
89
117
|
|
|
90
118
|
### Syntax
|
|
91
119
|
|
|
@@ -97,101 +125,50 @@ User <action> [<Target>] <type> with {{<Value>}}
|
|
|
97
125
|
- `{{Value}}` → test data reference → lookup in `test-data/*.yaml`
|
|
98
126
|
- `<type>` → element type: button, link, field, heading, text, etc.
|
|
99
127
|
|
|
100
|
-
###
|
|
101
|
-
|
|
102
|
-
#### Actions
|
|
103
|
-
|
|
104
|
-
| Pattern | Example |
|
|
105
|
-
|---|---|
|
|
106
|
-
| Simple click | `User click [Submit] button` |
|
|
107
|
-
| Click with data | `User click [Teammate] button with {{name}}` |
|
|
108
|
-
| Fill field | `User fill [Email] field with {{email}}` |
|
|
109
|
-
| Check/Uncheck | `User check [Remember me] checkbox` |
|
|
110
|
-
| Select dropdown | `User select [Country] dropdown with {{country}}` |
|
|
111
|
-
| Upload file | `User upload [Avatar] file with {{path}}` |
|
|
112
|
-
| Double click | `User double click [Cell] element` |
|
|
113
|
-
| Hover | `User hover [Info] icon` |
|
|
114
|
-
| Clear | `User clear [Search] field` |
|
|
115
|
-
|
|
116
|
-
#### Keyboard
|
|
117
|
-
|
|
118
|
-
| Pattern | Example |
|
|
119
|
-
|---|---|
|
|
120
|
-
| Global key | `User press Escape key` |
|
|
121
|
-
| Key on element | `User press Enter on [Search] field` |
|
|
122
|
-
|
|
123
|
-
#### Navigation
|
|
124
|
-
|
|
125
|
-
| Pattern | Example |
|
|
126
|
-
|---|---|
|
|
127
|
-
| Open page | `User is on [login] page` |
|
|
128
|
-
| See page (URL) | `User see [dashboard] page` |
|
|
129
|
-
|
|
130
|
-
#### Wait
|
|
131
|
-
|
|
132
|
-
| Pattern | Example |
|
|
133
|
-
|---|---|
|
|
134
|
-
| Wait timeout | `User wait for 3 seconds` |
|
|
135
|
-
| Wait element | `User wait for [Modal] dialog` |
|
|
136
|
-
| Wait hidden | `User wait for [Loading] spinner is hidden` |
|
|
137
|
-
| Wait with data | `User wait for [Dialog] dialog with {{title}}` |
|
|
138
|
-
|
|
139
|
-
#### Assertions
|
|
140
|
-
|
|
141
|
-
| Pattern | Example |
|
|
142
|
-
|---|---|
|
|
143
|
-
| See element | `User see [Welcome] heading` |
|
|
144
|
-
| See with value | `User see [Title] heading with {{title}}` |
|
|
145
|
-
| State check | `User see [Submit] button is disabled` |
|
|
146
|
-
| State + data | `User see [Panel] dialog with {{title}} is hidden` |
|
|
147
|
-
| Text contains | `User see [Message] text contains {{partial}}` |
|
|
148
|
-
|
|
149
|
-
States: `hidden`, `visible`, `disabled`, `enabled`, `checked`, `unchecked`, `focused`, `empty`
|
|
150
|
-
|
|
151
|
-
#### Table
|
|
128
|
+
### Key Patterns
|
|
152
129
|
|
|
153
130
|
| Pattern | Example |
|
|
154
131
|
|---|---|
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
160
|
-
|
|
|
161
|
-
|
|
|
162
|
-
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
| Pattern | Example |
|
|
167
|
-
|---|---|
|
|
168
|
-
| Scroll | `User scroll to [Footer] section` |
|
|
169
|
-
| Frame enter | `User switch to [Payment] frame` |
|
|
170
|
-
| Frame exit | `User switch to [main] frame` |
|
|
132
|
+
| Navigate | `User is on [login] page` |
|
|
133
|
+
| Click | `User click [Submit] button` |
|
|
134
|
+
| Fill | `User fill [Email] field with {{email}}` |
|
|
135
|
+
| Assert visible | `User see [Welcome] heading is visible` |
|
|
136
|
+
| Assert text | `User see [Title] heading with {{title}}` |
|
|
137
|
+
| Assert state | `User see [Submit] button is disabled` |
|
|
138
|
+
| Wait for | `User wait for [Modal] dialog is visible` |
|
|
139
|
+
| Table row | `User see [Users] table has row with {{name}}` |
|
|
140
|
+
| Table column | `User see [Users] table has [Email] column` |
|
|
141
|
+
|
|
142
|
+
States: `hidden` `visible` `disabled` `enabled` `checked` `unchecked` `focused` `empty` `loading` `selected`
|
|
171
143
|
|
|
172
144
|
### Tags
|
|
173
145
|
|
|
174
146
|
| Tag | Purpose |
|
|
175
147
|
|---|---|
|
|
176
148
|
| `@auth:role` | Use Playwright storage state for auth |
|
|
149
|
+
| `@no-auth` | Disable inherited auth for this scenario |
|
|
177
150
|
| `@steps:name` | Define reusable step group |
|
|
178
151
|
| `@extend:name` | Inherit steps from another scenario |
|
|
179
152
|
| `@manual` | Skip scenario in generation |
|
|
180
153
|
|
|
181
|
-
### Selector
|
|
154
|
+
### YAML Selector Keys
|
|
155
|
+
|
|
156
|
+
Keys are **lowercase with spaces**, Unicode preserved:
|
|
157
|
+
- `[Search Content]` → `search content:`
|
|
158
|
+
- `[Thời gian]` → `thời gian:`
|
|
159
|
+
- Same label, different types → `add campaign--button:` / `add campaign--text:`
|
|
160
|
+
|
|
161
|
+
### Selector Types
|
|
182
162
|
|
|
183
163
|
```yaml
|
|
184
|
-
|
|
185
|
-
type: '
|
|
186
|
-
value: '
|
|
187
|
-
name: '
|
|
188
|
-
nth: 0
|
|
189
|
-
exact: true # exact name match (avoid "Submit" matching "Submit Form")
|
|
190
|
-
scope: 'desktop navigation' # scope to parent landmark
|
|
191
|
-
match: 'exact' # exact text match for getByText
|
|
164
|
+
search:
|
|
165
|
+
type: 'placeholder' # testid, role, placeholder, label, text, locator, page
|
|
166
|
+
value: 'Search users' # placeholder text, role name, CSS selector, etc.
|
|
167
|
+
name: 'Search' # accessible name (for role type)
|
|
168
|
+
nth: 0 # element index (for multiple matches)
|
|
192
169
|
```
|
|
193
170
|
|
|
194
|
-
|
|
171
|
+
Priority: `data-testid` > `role+name` > `placeholder` > `label` > `text` > `CSS locator`
|
|
195
172
|
|
|
196
173
|
---
|
|
197
174
|
|
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
package/src/generators/test-generator/adapters/playwright/templates/steps/actions/fill-action.hbs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
await {{> locator}}.fill('{{fillValue}}');
|
|
1
|
+
await {{> locator}}.fill('{{escapeQuotes fillValue}}');
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
await page.waitForLoadState('networkidle');
|
|
2
1
|
const {{columnIndexVar}} = (await page.getByRole('columnheader').allTextContents()).findIndex(h => h.includes('{{columnName}}'));
|
|
3
2
|
await expect(page.getByRole('row').nth({{rowNth}}).getByRole('cell').nth({{columnIndexVar}})).toHaveText('{{dataValue}}');
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
await page.waitForLoadState('networkidle');
|
|
2
1
|
{{#if name}}
|
|
3
2
|
await expect(page.getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }).filter({ hasText: /^{{escapeRegex dataValue}}$/ }){{#if (gte nth 0)}}.nth({{nth}}){{/if}}).toBeDisabled();
|
|
4
3
|
{{else}}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
await page.waitForLoadState('networkidle');
|
|
2
1
|
await expect(page.getByText('{{escapeQuotes selectorRef}}').filter({ hasText: {{#if (eq selectorValue "")}}/.*{{escapeRegex dataValue}}$/{{else}}'{{escapeQuotes dataValue}}'{{/if}} }){{#if (gte nth 0)}}.nth({{nth}}){{/if}}).toBeDisabled();
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
await page.waitForLoadState('networkidle');
|
|
2
1
|
{{#if name}}
|
|
3
2
|
await expect(page.getByRole('{{role}}', { name: '{{escapeQuotes name}}'{{#if exact}}, exact: true{{/if}} }).filter({ hasText: /^{{escapeRegex dataValue}}$/ }){{#if (gte nth 0)}}.nth({{nth}}){{/if}}).toBeHidden();
|
|
4
3
|
{{else}}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
await page.waitForLoadState('networkidle');
|
|
2
1
|
await expect(page.getByText('{{escapeQuotes selectorRef}}').filter({ hasText: {{#if (eq selectorValue "")}}/.*{{escapeRegex dataValue}}$/{{else}}'{{escapeQuotes dataValue}}'{{/if}} }){{#if (gte nth 0)}}.nth({{nth}}){{/if}}).toBeHidden();
|