@qa-gentic/stlc-agents 1.0.5 → 1.0.7
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 +175 -34
- package/bin/postinstall.js +125 -44
- package/bin/qa-stlc.js +15 -8
- package/package.json +2 -2
- package/skills/{qa-stlc/AGENT-BEHAVIOR.md → AGENT-BEHAVIOR.md} +7 -6
- package/{.github/copilot-instructions/deduplication-protocol.md → skills/deduplication-protocol/SKILL.md} +16 -21
- package/skills/generate-gherkin/SKILL.md +287 -0
- package/skills/generate-gherkin/references/step-by-step.md +267 -0
- package/skills/{qa-stlc/generate-playwright-code.md → generate-playwright-code/SKILL.md} +13 -23
- package/{.github/copilot-instructions/generate-test-cases.md → skills/generate-test-cases/SKILL.md} +16 -2
- package/skills/qa-jira-manager/SKILL.md +287 -0
- package/{.github/copilot-instructions/write-helix-files.md → skills/write-helix-files/SKILL.md} +11 -17
- package/src/{boilerplate-bundle.js → cli/boilerplate-bundle.js} +8 -8
- package/src/cli/cmd-init.js +145 -0
- package/src/{cmd-mcp-config.js → cli/cmd-mcp-config.js} +72 -9
- package/src/cli/cmd-skills.js +209 -0
- package/src/{cmd-verify.js → cli/cmd-verify.js} +35 -3
- package/src/cli/prompt-integration.js +87 -0
- package/src/stlc_agents/agent_helix_writer/tools/boilerplate.py +8 -8
- package/src/stlc_agents/agent_jira_manager/__init__.py +0 -0
- package/src/stlc_agents/agent_jira_manager/server.py +500 -0
- package/src/stlc_agents/agent_jira_manager/tools/__init__.py +0 -0
- package/src/stlc_agents/agent_jira_manager/tools/jira_workitem.py +467 -0
- package/src/stlc_agents/shared_jira/__init__.py +0 -0
- package/src/stlc_agents/shared_jira/auth.py +270 -0
- package/.github/copilot-instructions/AGENT-BEHAVIOR.md +0 -448
- package/.github/copilot-instructions/generate-gherkin.md +0 -550
- package/.github/copilot-instructions/generate-playwright-code.md +0 -464
- package/skills/qa-stlc/deduplication-protocol.md +0 -303
- package/skills/qa-stlc/generate-gherkin.md +0 -550
- package/skills/qa-stlc/generate-test-cases.md +0 -176
- package/skills/qa-stlc/write-helix-files.md +0 -374
- package/src/cmd-init.js +0 -92
- package/src/cmd-skills.js +0 -124
- /package/src/{cmd-scaffold.js → cli/cmd-scaffold.js} +0 -0
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: generate-playwright-code
|
|
3
|
-
description: >
|
|
4
|
-
Use this skill whenever the user asks to generate, create, or update Playwright TypeScript
|
|
5
|
-
automation code for a Feature, PBI, or Bug. Triggers when the user mentions "Playwright",
|
|
6
|
-
"page object", "locators", "step definitions", "automation", "self-healing", "locator
|
|
7
|
-
repository", "TimingHealer", "VisualIntentChecker", or asks to automate a Gherkin feature
|
|
8
|
-
file. Always reads existing attached Playwright files from the ADO work item before generating
|
|
9
|
-
anything, to avoid duplicate locators, page methods, and step definitions. Works with any ADO
|
|
10
|
-
work item type: PBI, Bug, or Feature ID.
|
|
11
|
-
compatibility:
|
|
12
|
-
tools:
|
|
13
|
-
- qa-playwright-generator:scaffold_locator_repository
|
|
14
|
-
- qa-playwright-generator:generate_playwright_code
|
|
15
|
-
- qa-playwright-generator:attach_code_to_work_item
|
|
16
|
-
- qa-playwright-generator:validate_gherkin_steps
|
|
17
|
-
- qa-test-case-manager:get_linked_test_cases
|
|
18
|
-
- qa-gherkin-generator:fetch_feature_hierarchy
|
|
19
|
-
- playwright:browser_navigate
|
|
20
|
-
- playwright:browser_snapshot
|
|
21
|
-
- playwright:browser_fill_form
|
|
22
|
-
- playwright:browser_click
|
|
23
|
-
- playwright:browser_file_upload
|
|
24
|
-
---
|
|
25
|
-
|
|
26
|
-
# Generate Playwright Code Skill
|
|
27
|
-
|
|
28
|
-
> **Read `AGENT-BEHAVIOR.md` before this skill.** The behavior rules there override any
|
|
29
|
-
> inference. This skill provides the step-by-step workflow only.
|
|
30
|
-
|
|
31
|
-
Generate production-quality, three-layer self-healing Playwright TypeScript automation from a
|
|
32
|
-
validated Gherkin feature file, using live Playwright MCP snapshots for verified locators.
|
|
33
|
-
Works with any ADO work item type: PBI, Bug, or Feature ID.
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Three Healing Layers
|
|
38
|
-
|
|
39
|
-
Every generated page object implements three layers of self-healing:
|
|
40
|
-
|
|
41
|
-
| Layer | Class | What it heals |
|
|
42
|
-
|---|---|---|
|
|
43
|
-
| 1 — Locator | `LocatorHealer` | primary selector → role → label → text → AI Vision → CDPSession AX tree |
|
|
44
|
-
| 2 — Timing | `TimingHealer` | network-trace drift → auto-adjusted timeouts → HealingDashboard |
|
|
45
|
-
| 3 — Visual | `VisualIntentChecker` | element screenshot diff at assertions → HealingDashboard |
|
|
46
|
-
|
|
47
|
-
Healed selectors are persisted in `LocatorRepository` — zero overhead on repeat runs.
|
|
48
|
-
HealingDashboard runs at `http://localhost:7890` during test execution for approve/reject.
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## ⛔ Mandatory Pre-Flight: Deduplication Protocol
|
|
53
|
-
|
|
54
|
-
Before generating or attaching any file, run the deduplication protocol:
|
|
55
|
-
`skills/deduplication-protocol.md`
|
|
56
|
-
|
|
57
|
-
The protocol is **work-item-scoped**: PHASE 1 runs once per `work_item_id` and results are
|
|
58
|
-
cached. If `generate-gherkin` already ran for this `work_item_id`, skip PHASE 1 and read from
|
|
59
|
-
`CACHE[work_item_id]` directly. A different `work_item_id` always triggers a fresh PHASE 1.
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Step-by-Step Workflow
|
|
64
|
-
|
|
65
|
-
### Step 0 — Route: fresh project vs. existing boilerplate
|
|
66
|
-
|
|
67
|
-
Before any other step, determine whether the Helix-QA project already has the automation
|
|
68
|
-
infrastructure in place.
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
Call: qa-helix-writer:list_helix_tree(helix_root)
|
|
72
|
-
│
|
|
73
|
-
├─ framework_state: "absent" or "partial" → FRESH PROJECT
|
|
74
|
-
│ Call scaffold_locator_repository(...) FIRST
|
|
75
|
-
│ Then call generate_playwright_code(...)
|
|
76
|
-
│
|
|
77
|
-
└─ framework_state: "present" → EXISTING BOILERPLATE
|
|
78
|
-
Call generate_playwright_code(...) ONLY
|
|
79
|
-
Do NOT call scaffold_locator_repository — infra already exists
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
**Why this matters:** `scaffold_locator_repository` generates the six shared infrastructure
|
|
83
|
-
files (`LocatorRepository`, `LocatorHealer`, `TimingHealer`, `VisualIntentChecker`,
|
|
84
|
-
`DevToolsHealer`, `cucumber.config.ts`). Calling it on an existing project overwrites those
|
|
85
|
-
files and destroys any customisations. Never call it when `framework_state: "present"`.
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
### Step 1 — Load existing Playwright artifacts from cache
|
|
90
|
-
|
|
91
|
-
Read from `CACHE[work_item_id]` (populated by the deduplication protocol pre-flight):
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
CACHE[work_item_id].existing_attachments.locators_ts → existing locator keys
|
|
95
|
-
CACHE[work_item_id].existing_attachments.page_objects → existing method names
|
|
96
|
-
CACHE[work_item_id].existing_attachments.steps_files → existing step strings
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
If a file exists but content could not be read, treat it as fully covering its domain and
|
|
100
|
-
produce no new file of that type unless you can prove a gap.
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
### Step 2 — GAP CHECK: identify screens you cannot reach and ASK before proceeding
|
|
105
|
-
|
|
106
|
-
Before navigating the live app, scan the Gherkin feature file for every `Given` step that
|
|
107
|
-
requires a specific app state — a state only reachable by performing a real action (uploading
|
|
108
|
-
a file, submitting a form, triggering an error, completing a multi-step flow).
|
|
109
|
-
|
|
110
|
-
For each such step, ask: **can I reach this screen right now with the information I have?**
|
|
111
|
-
|
|
112
|
-
#### Blockers that require a user question before proceeding
|
|
113
|
-
|
|
114
|
-
| Blocker | Example | What to ask |
|
|
115
|
-
|---|---|---|
|
|
116
|
-
| File upload required to reach a screen | "Given I am on the failure summary screen" — only after uploading a CSV with bad rows | "Please provide the CSV file or tell me which emails to use as known duplicates" |
|
|
117
|
-
| Specific record / ID required | "Given work item #12345 has linked test cases" | "Which org / record should I test against?" |
|
|
118
|
-
| Error state requires specific bad data | "Given the upload is rejected for unsupported format" | "Should I use .txt or .pdf to test the rejection?" |
|
|
119
|
-
| Multi-step prerequisite from a sibling PBI | "Given the mass add has completed" | "Should I replay the upload step, or is there a seed/shortcut?" |
|
|
120
|
-
| Screen only exists after a backend event | "Given the processing is complete" | "Is there a test endpoint I can hit to seed this state?" |
|
|
121
|
-
|
|
122
|
-
**If any blocker is found, output a question block and wait for answers.**
|
|
123
|
-
|
|
124
|
-
#### Question format
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
Before I navigate the live app to capture locators for "<feature title>", I need:
|
|
128
|
-
|
|
129
|
-
**[Blocker type]: [screen or element name]**
|
|
130
|
-
[One sentence describing what the Gherkin step requires]
|
|
131
|
-
→ [Specific question — what file, what email, what record, what sequence?]
|
|
132
|
-
|
|
133
|
-
I will not proceed until these are answered, to avoid inventing selectors
|
|
134
|
-
(stability: 0) for screens I cannot reach.
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
**Only proceed to Step 3 once every blocker is resolved, OR the user explicitly grants
|
|
138
|
-
sign-off to proceed with known `stability: 0` limitations documented.**
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
### Step 3 — Live locator verification through the FULL flow
|
|
143
|
-
|
|
144
|
-
Navigate through **every screen in the Gherkin feature** — including state-dependent screens —
|
|
145
|
-
using the real test data provided in Step 2. Never snapshot only the landing page and infer.
|
|
146
|
-
|
|
147
|
-
```
|
|
148
|
-
playwright:browser_navigate(APP_BASE_URL)
|
|
149
|
-
playwright:browser_snapshot() ← login screen
|
|
150
|
-
|
|
151
|
-
playwright:browser_fill_form(fields: [
|
|
152
|
-
{ name: "Email", type: "textbox", ref: "<ref>", value: "<email>" },
|
|
153
|
-
{ name: "Password", type: "textbox", ref: "<ref>", value: "<password>" }
|
|
154
|
-
])
|
|
155
|
-
playwright:browser_click(ref: "<login-button-ref>")
|
|
156
|
-
playwright:browser_snapshot() ← dashboard — verify logged in
|
|
157
|
-
|
|
158
|
-
← Navigate through EVERY prerequisite step to reach state-dependent screens
|
|
159
|
-
playwright:browser_click(...) ← e.g. "Add Users" button
|
|
160
|
-
playwright:browser_click(...) ← e.g. "Add Multiple" tab
|
|
161
|
-
playwright:browser_snapshot() ← capture screen locators
|
|
162
|
-
|
|
163
|
-
← Upload real test file (from user's Step 2 answer)
|
|
164
|
-
playwright:browser_file_upload(
|
|
165
|
-
files: ["<real file path>"],
|
|
166
|
-
element: "file upload input",
|
|
167
|
-
ref: "<ref from snapshot>"
|
|
168
|
-
)
|
|
169
|
-
playwright:browser_snapshot() ← verify file attached, Next enabled
|
|
170
|
-
|
|
171
|
-
playwright:browser_click(...) ← "Next" / Submit
|
|
172
|
-
playwright:browser_snapshot() ← capture processing screen (if any)
|
|
173
|
-
playwright:browser_snapshot() ← capture state-dependent result screen
|
|
174
|
-
← capture ALL interactive elements here
|
|
175
|
-
|
|
176
|
-
playwright:browser_click(...) ← any further actions (Export, Accept, etc.)
|
|
177
|
-
playwright:browser_snapshot() ← capture post-action state
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
**Rule:** Every locator in the generated `locators.ts` must appear in one of these snapshots.
|
|
181
|
-
If a screen cannot be reached because test data is missing, go back to Step 2 and ask — do
|
|
182
|
-
not assign `stability: 0` and continue silently.
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
### Step 4 — Build the context_map
|
|
187
|
-
|
|
188
|
-
From each snapshot, map AX tree nodes to locator entries using this stability rank:
|
|
189
|
-
|
|
190
|
-
| Selector source | Stability |
|
|
191
|
-
|---|---|
|
|
192
|
-
| `data-testid` attribute | 100 |
|
|
193
|
-
| `aria-role` + accessible name | 90 |
|
|
194
|
-
| `id` attribute | 80 |
|
|
195
|
-
| `aria-label` | 70 |
|
|
196
|
-
| `placeholder` text | 60 |
|
|
197
|
-
| Gherkin-inferred (no live verification) | 0 — `⚠ NOT VERIFIED` comment required |
|
|
198
|
-
|
|
199
|
-
Only include keys NOT already present in the existing `locators.ts` (from Step 1).
|
|
200
|
-
|
|
201
|
-
**Example context_map (built from Playwright MCP AX snapshots):**
|
|
202
|
-
```json
|
|
203
|
-
{
|
|
204
|
-
"emailInput": { "selector": "[data-testid='auth0_login-input-email']", "intent": "Auth0 login email field", "stability": 100 },
|
|
205
|
-
"loginButton": { "selector": "[data-testid='auth0_login-button-login']", "intent": "Submit login credentials", "stability": 100 },
|
|
206
|
-
"addUsersButton": { "selector": "[data-testid='person_header-button-add_users']", "intent": "Add Users button, opens slide-out", "stability": 100 },
|
|
207
|
-
"addMultipleTab": { "selector": "[data-testid='person_slider-tab-add_multiple']", "intent": "Add Multiple tab in Add Users panel", "stability": 100 },
|
|
208
|
-
"fileInput": { "selector": "input[type='file']", "intent": "Hidden file input for CSV upload", "stability": 70 },
|
|
209
|
-
"nextButton": { "selector": "button:has-text('Next')", "intent": "Proceed after file upload", "stability": 90 },
|
|
210
|
-
"exportListButton": { "selector": "button:has-text('Export List')", "intent": "Export failed users CSV", "stability": 90, "visualIntent": true },
|
|
211
|
-
"failureSummaryTable":{ "selector": "table", "intent": "Failed user rows table", "stability": 80, "visualIntent": true }
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
### Step 5 — Generate the code
|
|
218
|
-
|
|
219
|
-
```
|
|
220
|
-
qa-playwright-generator:generate_playwright_code(
|
|
221
|
-
gherkin_content : <validated .feature file content>,
|
|
222
|
-
page_class_name : "<ScreenName>Page",
|
|
223
|
-
app_name : "<AppName>",
|
|
224
|
-
context_map : <context_map from Step 4>,
|
|
225
|
-
healing_strategy : "role-label-text-ai",
|
|
226
|
-
enable_timing_healing : true,
|
|
227
|
-
enable_visual_regression : true
|
|
228
|
-
)
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
The tool produces four files:
|
|
232
|
-
- `locators.ts` — selector registry with intent, stability score, visualIntent flag
|
|
233
|
-
- `{ScreenName}Page.ts` — three-layer self-healing page object
|
|
234
|
-
- `{feature}.steps.ts` — Cucumber step definitions
|
|
235
|
-
- `cucumber-profile.js` snippet — profile config to add to `config/cucumber.js`
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
### Step 6 — Apply the deduplication delta filter
|
|
240
|
-
|
|
241
|
-
Diff generated output against `CACHE[work_item_id].existing_attachments`:
|
|
242
|
-
|
|
243
|
-
**locators.ts:** Remove keys already in existing file. Empty delta → skip. Non-empty → attach as `locators.delta.ts`:
|
|
244
|
-
```typescript
|
|
245
|
-
// DELTA — merge these keys into the existing locators.ts
|
|
246
|
-
// Generated: <date> | Work item: #<id>
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
**{ScreenName}Page.ts:** Remove methods already in existing page object. Empty delta → skip. Non-empty → attach as `{ScreenName}Page.delta.ts` with merge header.
|
|
250
|
-
|
|
251
|
-
**{feature}.steps.ts:** Remove any `Given(` / `When(` / `Then(` whose step string already exists. Empty delta → skip. Non-empty → attach only net-new steps.
|
|
252
|
-
**CRITICAL: Never re-register an existing step string** — causes `Ambiguous step definition` at runtime.
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
### Step 7 — Delivery gate (mandatory before attaching to ADO)
|
|
257
|
-
|
|
258
|
-
Before calling `attach_code_to_work_item`, present the following to the user and wait:
|
|
259
|
-
|
|
260
|
-
```
|
|
261
|
-
I've generated the following Playwright TypeScript files for work item #{id}:
|
|
262
|
-
|
|
263
|
-
📄 locators.delta.ts — {N} new locator keys
|
|
264
|
-
📄 {ScreenName}Page.delta.ts — {N} new page methods
|
|
265
|
-
📄 {feature}.steps.delta.ts — {N} new step definitions
|
|
266
|
-
|
|
267
|
-
**Do you want me to attach these to ADO work item #{id}? (yes / no)**
|
|
268
|
-
|
|
269
|
-
Note:
|
|
270
|
-
- Saying yes here only attaches the Playwright files.
|
|
271
|
-
- It does NOT create manual test cases or attach Gherkin files.
|
|
272
|
-
- If you also want those, say so separately.
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
**Do not call `attach_code_to_work_item` until the user replies "yes".**
|
|
276
|
-
|
|
277
|
-
If user says "yes", call with delta files only:
|
|
278
|
-
|
|
279
|
-
```
|
|
280
|
-
qa-playwright-generator:attach_code_to_work_item(
|
|
281
|
-
organization_url : "<org_url>",
|
|
282
|
-
project_name : "<project>",
|
|
283
|
-
work_item_id : <id>,
|
|
284
|
-
files : [
|
|
285
|
-
{ file_name: "locators.delta.ts", content: "..." },
|
|
286
|
-
{ file_name: "{ScreenName}Page.delta.ts", content: "..." },
|
|
287
|
-
{ file_name: "{feature}.steps.delta.ts", content: "..." }
|
|
288
|
-
]
|
|
289
|
-
)
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
If user says "no": present the files inline. Offer local download only if user says
|
|
293
|
-
"save" or "download". Do not create a local file automatically.
|
|
294
|
-
|
|
295
|
-
**After attach — STOP. Do not trigger Helix write or any other action automatically.**
|
|
296
|
-
Helix-QA disk writes are a separate decision requiring a separate user request.
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## Generated File Structures
|
|
301
|
-
|
|
302
|
-
### locators.ts
|
|
303
|
-
|
|
304
|
-
```typescript
|
|
305
|
-
/**
|
|
306
|
-
* Locators: <ScreenName>Page
|
|
307
|
-
* SOURCE: Playwright MCP AX tree snapshot — <app-url>/<route>
|
|
308
|
-
* Stability: data-testid(100) > role+name(90) > id(80) > aria-label(70) > placeholder(60)
|
|
309
|
-
* ⚠ stability:0 entries were NOT reached in the live session — get user sign-off before using.
|
|
310
|
-
*/
|
|
311
|
-
export const <ScreenName>Locators = {
|
|
312
|
-
// stability: 100 — data-testid, survives refactors
|
|
313
|
-
addUsersButton: {
|
|
314
|
-
selector : "[data-testid='person_header-button-add_users']",
|
|
315
|
-
intent : "Add Users button that opens the slide-out panel",
|
|
316
|
-
stability : 100,
|
|
317
|
-
},
|
|
318
|
-
// stability: 90 — aria-role+name, visualIntent: screenshot at assertions
|
|
319
|
-
exportListButton: {
|
|
320
|
-
selector : "button:has-text('Export List')",
|
|
321
|
-
intent : "Export List button on the failure summary screen",
|
|
322
|
-
stability : 90,
|
|
323
|
-
visualIntent : true,
|
|
324
|
-
},
|
|
325
|
-
// ⚠ stability: 0 — NOT VERIFIED: could not reach this screen (reason: <why>)
|
|
326
|
-
// Get user sign-off before using in automation.
|
|
327
|
-
someUnreachedElement: {
|
|
328
|
-
selector : "[data-testid='TODO']",
|
|
329
|
-
intent : "...",
|
|
330
|
-
stability : 0,
|
|
331
|
-
},
|
|
332
|
-
} as const;
|
|
333
|
-
|
|
334
|
-
export type LocatorKey = keyof typeof <ScreenName>Locators;
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
### {ScreenName}Page.ts
|
|
338
|
-
|
|
339
|
-
```typescript
|
|
340
|
-
import { Page, expect, Download } from '@playwright/test';
|
|
341
|
-
import { fixture } from '@hooks/pageFixture';
|
|
342
|
-
import { <ScreenName>Locators } from './locators';
|
|
343
|
-
import { LocatorHealer } from '@utils/locators/LocatorHealer';
|
|
344
|
-
import { LocatorRepository } from '@utils/locators/LocatorRepository';
|
|
345
|
-
import { VisualIntentChecker } from '@utils/locators/VisualIntentChecker';
|
|
346
|
-
import { TimingHealer } from '@utils/locators/TimingHealer';
|
|
347
|
-
|
|
348
|
-
/**
|
|
349
|
-
* <ScreenName>Page — Three-Layer Self-Healing Page Object
|
|
350
|
-
* Layer 1 (LocatorHealer): primary → role → label → text → AI Vision → AX tree
|
|
351
|
-
* Layer 2 (TimingHealer): network-trace drift → auto-adjusted timeouts
|
|
352
|
-
* Layer 3 (VisualIntentChecker): element screenshot diff at key assertions
|
|
353
|
-
* HealingDashboard: http://localhost:7890
|
|
354
|
-
* RULE: Never use page.click / page.fill / page.locator directly.
|
|
355
|
-
*/
|
|
356
|
-
export default class <ScreenName>Page {
|
|
357
|
-
private readonly loc = <ScreenName>Locators;
|
|
358
|
-
private readonly page: Page;
|
|
359
|
-
private readonly healer: LocatorHealer;
|
|
360
|
-
private readonly repo: LocatorRepository;
|
|
361
|
-
private readonly visual: VisualIntentChecker;
|
|
362
|
-
private readonly timing: TimingHealer;
|
|
363
|
-
|
|
364
|
-
constructor(page?: Page) {
|
|
365
|
-
this.page = page ?? fixture().page;
|
|
366
|
-
this.repo = fixture().locatorRepository ?? new LocatorRepository();
|
|
367
|
-
this.healer = new LocatorHealer(this.page, fixture().logger, this.repo);
|
|
368
|
-
this.visual = new VisualIntentChecker(this.page, fixture().logger, this.repo);
|
|
369
|
-
this.timing = new TimingHealer(this.page, fixture().logger, this.repo);
|
|
370
|
-
Object.entries(this.loc).forEach(([k, v]) => this.repo.register(k, v.selector, v.intent));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
async login(email: string, password: string): Promise<void> {
|
|
374
|
-
await this.page.goto(process.env.APP_BASE_URL!, { waitUntil: 'networkidle' });
|
|
375
|
-
await this.healer.fillWithHealing('emailInput', this.loc.emailInput.selector, email, this.loc.emailInput.intent);
|
|
376
|
-
await this.healer.fillWithHealing('passwordInput', this.loc.passwordInput.selector, password, this.loc.passwordInput.intent);
|
|
377
|
-
await this.healer.clickWithHealing('loginButton', this.loc.loginButton.selector, this.loc.loginButton.intent);
|
|
378
|
-
await this.timing.waitForNetworkIdle('login');
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// All interactions go through LocatorHealer — never raw page.click / page.fill
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### {feature}.steps.ts
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
import { Given, When, Then, Before } from '@cucumber/cucumber';
|
|
389
|
-
import { expect } from '@playwright/test';
|
|
390
|
-
import { fixture } from '@hooks/pageFixture';
|
|
391
|
-
import <ScreenName>Page from '@pages/<screenName>/<ScreenName>Page';
|
|
392
|
-
|
|
393
|
-
let page_: <ScreenName>Page;
|
|
394
|
-
|
|
395
|
-
Before(async () => { page_ = new <ScreenName>Page(fixture().page); });
|
|
396
|
-
|
|
397
|
-
Given('I am logged in to {word} as {string}', async (_app: string, email: string) => {
|
|
398
|
-
await page_.login(email, process.env.APP_PASSWORD!);
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
// Only net-new steps — never re-register steps already in existing files
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
---
|
|
405
|
-
|
|
406
|
-
## Run Commands
|
|
407
|
-
|
|
408
|
-
```bash
|
|
409
|
-
ENABLE_SELF_HEALING=true \
|
|
410
|
-
HEALING_DASHBOARD_PORT=7890 \
|
|
411
|
-
APP_BASE_URL=https://account.myamplify.io \
|
|
412
|
-
APP_EMAIL=<email> \
|
|
413
|
-
APP_PASSWORD=<password> \
|
|
414
|
-
cucumber-js --config=config/cucumber.js -p <feature_profile>
|
|
415
|
-
|
|
416
|
-
# Smoke only:
|
|
417
|
-
cucumber-js --config=config/cucumber.js -p <feature_profile> --tags "@smoke"
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
---
|
|
421
|
-
|
|
422
|
-
## Quality Gates — Do Not Attach Without These
|
|
423
|
-
|
|
424
|
-
- [ ] Deduplication protocol run — existing locator keys, methods, step strings extracted
|
|
425
|
-
- [ ] **Gap check (Step 2) completed** — every state-dependent screen identified
|
|
426
|
-
- [ ] **All blockers answered by user before any navigation began**
|
|
427
|
-
- [ ] **Live snapshots taken of every screen in the full flow** using real test data
|
|
428
|
-
- [ ] **Zero `stability: 0` locators** for screens reachable with provided test data
|
|
429
|
-
- [ ] Every `stability: 0` locator has `⚠ NOT VERIFIED` comment with explicit user sign-off
|
|
430
|
-
- [ ] No step string re-registers an already-registered Given/When/Then
|
|
431
|
-
- [ ] Page object methods use `LocatorHealer` — never raw `page.click` / `page.fill`
|
|
432
|
-
- [ ] Credentials sourced from `process.env`, not hardcoded
|
|
433
|
-
- [ ] Delta files have merge-instruction comment at top
|
|
434
|
-
|
|
435
|
-
---
|
|
436
|
-
|
|
437
|
-
## Locator Stability Reference
|
|
438
|
-
|
|
439
|
-
| Pattern | Stability | When to use |
|
|
440
|
-
|---|---|---|
|
|
441
|
-
| `[data-testid='...']` | 100 | Always prefer — survives refactors |
|
|
442
|
-
| `role=button[name='...']` | 90 | When data-testid absent |
|
|
443
|
-
| `#id` | 80 | When id is stable and meaningful |
|
|
444
|
-
| `[aria-label='...']` | 70 | Accessibility attributes |
|
|
445
|
-
| `[placeholder='...']` | 60 | Input fields only |
|
|
446
|
-
| Text / position selectors | 0 | Last resort — flag for upgrade |
|
|
447
|
-
|
|
448
|
-
---
|
|
449
|
-
|
|
450
|
-
## Explicit Delivery Rules — No Inference
|
|
451
|
-
|
|
452
|
-
| Decision | Rule |
|
|
453
|
-
|---|---|
|
|
454
|
-
| Generate Playwright code | Always: show file summary and delta counts first |
|
|
455
|
-
| Attach to ADO | Requires explicit "yes" at Step 7 gate |
|
|
456
|
-
| User says "no" at Step 7 | Present files inline; offer local download only if user asks |
|
|
457
|
-
| Local file creation | Only if user says "save" or "download" |
|
|
458
|
-
| Helix-QA disk write | Must be a separate user request — not triggered by ADO attachment |
|
|
459
|
-
| Test case creation | Must be a separate user request — not triggered by this skill |
|
|
460
|
-
| Gherkin attachment | Must be a separate user request — not triggered by this skill |
|
|
461
|
-
| Prior Gherkin "yes" | Has NO bearing on Playwright attachment decision |
|
|
462
|
-
| Prior test case "no" | Has NO bearing on Playwright attachment decision |
|
|
463
|
-
|
|
464
|
-
**Each artifact delivery is independent. A yes/no for one does not answer any other.**
|