@keber/qa-framework 1.5.2 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -6
- package/README.md +150 -76
- package/docs/architecture.md +49 -44
- package/docs/folder-structure-guide.md +27 -23
- package/docs/installation.md +53 -43
- package/docs/usage-with-agent.md +52 -64
- package/integrations/ado-powershell/pipelines/azure-pipeline-qa.yml +1 -1
- package/integrations/playwright/README.md +1 -1
- package/package.json +1 -1
- package/scripts/init.js +20 -12
- package/scripts/upgrade.js +100 -11
- package/skills/qa-ado-integration/SKILL.md +2 -2
- package/skills/qa-automation/SKILL.md +6 -6
- package/skills/qa-maintenance/SKILL.md +2 -2
- package/templates/automation-scaffold/playwright.config.ts +1 -1
- package/agent-instructions/00-module-analysis.md +0 -266
- package/agent-instructions/01-spec-generation.md +0 -281
- package/agent-instructions/02-test-plan-generation.md +0 -205
- package/agent-instructions/03-test-case-generation.md +0 -150
- package/agent-instructions/04-automation-generation.md +0 -343
- package/agent-instructions/04b-test-stabilization.md +0 -309
- package/agent-instructions/05-ado-integration.md +0 -247
- package/agent-instructions/06-maintenance.md +0 -135
- package/docs/comparison-matrix.md +0 -131
- package/docs/generalization-decisions.md +0 -203
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
# Agent Instructions: Test Plan Generation
|
|
2
|
-
|
|
3
|
-
> ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-test-plan/SKILL.md`.
|
|
4
|
-
> Kept as reference during the transition period. Do not update this file.
|
|
5
|
-
|
|
6
|
-
**File**: `agent-instructions/02-test-plan-generation.md`
|
|
7
|
-
**Purpose**: Instructions for generating a test plan document for a module, after its spec set is complete.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## When to use
|
|
12
|
-
|
|
13
|
-
- After all submodule specs (`05-test-scenarios.md`) are written and reviewed
|
|
14
|
-
- When preparing for a sprint or release
|
|
15
|
-
- When deciding which TCs to automate vs test manually
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Inputs Required
|
|
20
|
-
|
|
21
|
-
1. `qa/01-specifications/module-{name}/` — all submodule specs
|
|
22
|
-
2. Scope definition: which submodules are in this test plan
|
|
23
|
-
3. Priority guidance (from the team or implied by sprint scope)
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Test Plan Document Structure
|
|
28
|
-
|
|
29
|
-
Create: `qa/02-test-plans/automated/{module}-test-plan.md`
|
|
30
|
-
|
|
31
|
-
```markdown
|
|
32
|
-
# Test Plan: {Module Display Name}
|
|
33
|
-
|
|
34
|
-
| Field | Value |
|
|
35
|
-
|-------|-------|
|
|
36
|
-
| Version | 1.0 |
|
|
37
|
-
| Date | YYYY-MM-DD |
|
|
38
|
-
| Module | {module-code} |
|
|
39
|
-
| Test plan type | Automated / Manual / Combined |
|
|
40
|
-
| Author | {agent or human name} |
|
|
41
|
-
| Status | Draft / Approved / Active |
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## 1. Objective
|
|
46
|
-
|
|
47
|
-
{1-2 sentences: what this test plan covers and why}
|
|
48
|
-
|
|
49
|
-
---
|
|
50
|
-
|
|
51
|
-
## 2. Scope
|
|
52
|
-
|
|
53
|
-
### In scope
|
|
54
|
-
- {submodule 1}: {what is being tested}
|
|
55
|
-
- {submodule 2}: {what is being tested}
|
|
56
|
-
|
|
57
|
-
### Out of scope
|
|
58
|
-
- {what is explicitly excluded and why}
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## 3. Automation Feasibility Analysis
|
|
63
|
-
|
|
64
|
-
| Submodule | Total TCs | Fully automatable | Partially | Not automatable | Reason for exclusions |
|
|
65
|
-
|-----------|-----------|------------------|-----------|-----------------|----------------------|
|
|
66
|
-
| {name} | {N} | {N} ({%}) | {N} ({%}) | {N} ({%}) | {brief reason} |
|
|
67
|
-
|
|
68
|
-
**Definition**:
|
|
69
|
-
- **Fully automatable**: deterministic, observable, no external dependencies
|
|
70
|
-
- **Partially automatable**: some steps can be automated, others require manual verification
|
|
71
|
-
- **Not automatable**: requires human judgment, external system access, or is too risky to automate in QA
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## 4. Priority Distribution
|
|
76
|
-
|
|
77
|
-
| Priority | TCs selected | Automated | Manual |
|
|
78
|
-
|----------|-------------|-----------|--------|
|
|
79
|
-
| P0 (Critical — must run every build) | {N} | {N} | {N} |
|
|
80
|
-
| P1 (High — must run before release) | {N} | {N} | {N} |
|
|
81
|
-
| P2 (Medium — periodic regression) | {N} | {N} | {N} |
|
|
82
|
-
| P3 (Low — manual only) | {N} | 0 | {N} |
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## 5. TC Selection and Automation Plan
|
|
87
|
-
|
|
88
|
-
### P0 Suite — {suite name}
|
|
89
|
-
|
|
90
|
-
| TC ID | Title | Type | Automation status |
|
|
91
|
-
|-------|-------|------|------------------|
|
|
92
|
-
| TC-{M}-{S}-001 | {title} | Functional | Queued |
|
|
93
|
-
| TC-{M}-{S}-002 | {title} | Negative | Queued |
|
|
94
|
-
|
|
95
|
-
### P1 Suite — {suite name}
|
|
96
|
-
|
|
97
|
-
| TC ID | Title | Type | Automation status |
|
|
98
|
-
|-------|-------|------|------------------|
|
|
99
|
-
| TC-{M}-{S}-010 | {title} | Functional | Queued |
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 6. Azure DevOps Test Plan (if enabled)
|
|
104
|
-
|
|
105
|
-
| Item | Value |
|
|
106
|
-
|------|-------|
|
|
107
|
-
| ADO Plan ID | (populate after creation) |
|
|
108
|
-
| ADO Suite IDs | (populate after creation) |
|
|
109
|
-
| Reporter | @alex_neo/playwright-azure-reporter |
|
|
110
|
-
| Sync script | qa/08-azure-integration/scripts/inject-ado-ids.ps1 |
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## 7. Test Environment
|
|
115
|
-
|
|
116
|
-
| Item | Value |
|
|
117
|
-
|------|-------|
|
|
118
|
-
| QA URL | {{QA_BASE_URL}} |
|
|
119
|
-
| Browser | Chromium (Playwright) |
|
|
120
|
-
| Workers (local) | {N from config} |
|
|
121
|
-
| Workers (CI) | {N from config} |
|
|
122
|
-
| Parallel sessions supported | Yes / No |
|
|
123
|
-
|
|
124
|
-
---
|
|
125
|
-
|
|
126
|
-
## 8. Risks and Assumptions
|
|
127
|
-
|
|
128
|
-
| Risk | Likelihood | Impact | Mitigation |
|
|
129
|
-
|------|-----------|--------|------------|
|
|
130
|
-
| Unstable QA data | Medium | High | Use EXEC_IDX-generated data |
|
|
131
|
-
| External service (email, etc.) not available | High | Medium | Use 3-layer validation strategy |
|
|
132
|
-
| QA env down-time | Low | High | Retry with 2h buffer in CI |
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## 9. Excluded TCs
|
|
137
|
-
|
|
138
|
-
| TC ID | Reason for exclusion |
|
|
139
|
-
|-------|---------------------|
|
|
140
|
-
| TC-{M}-{S}-NNN | `BLOCKED-PERMISSIONS`: QA user cannot access |
|
|
141
|
-
| TC-{M}-{S}-NNN | `PENDING-CODE`: feature not yet deployed |
|
|
142
|
-
| TC-{M}-{S}-NNN | Not automatable: requires visual inspection / external access |
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
## 10. Execution Schedule
|
|
147
|
-
|
|
148
|
-
| Suite | Trigger | Frequency |
|
|
149
|
-
|-------|---------|-----------|
|
|
150
|
-
| P0 smoke | Every CI build | On push to main / PR |
|
|
151
|
-
| P1 regression | Scheduled | Nightly |
|
|
152
|
-
| P2 full regression | Manual trigger | Before each release |
|
|
153
|
-
|
|
154
|
-
---
|
|
155
|
-
|
|
156
|
-
## Changelog
|
|
157
|
-
|
|
158
|
-
| Version | Date | Description |
|
|
159
|
-
|---------|------|-------------|
|
|
160
|
-
| 1.0 | YYYY-MM-DD | Initial creation |
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Rules for Priority Assignment
|
|
166
|
-
|
|
167
|
-
Use this decision tree for each TC:
|
|
168
|
-
|
|
169
|
-
```
|
|
170
|
-
Is this the primary happy path of the feature?
|
|
171
|
-
├── YES → P0
|
|
172
|
-
|
|
173
|
-
Is a bug here a show-stopper or critical data corruption risk?
|
|
174
|
-
├── YES → P0
|
|
175
|
-
├── NO →
|
|
176
|
-
Is this a common negative scenario (empty required field, duplicate)?
|
|
177
|
-
├── YES → P1
|
|
178
|
-
Is this a cross-module dependency or state machine transition?
|
|
179
|
-
├── YES → P1
|
|
180
|
-
Is this a secondary feature (export, pagination, search)?
|
|
181
|
-
├── YES → P2
|
|
182
|
-
Is this an edge case, cosmetic, or low-frequency scenario?
|
|
183
|
-
├── YES → P3
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## Automation Feasibility Decision Criteria
|
|
189
|
-
|
|
190
|
-
**Mark as fully automatable** when:
|
|
191
|
-
- All interactions are observable via browser automation
|
|
192
|
-
- The result is deterministic (same input → same output)
|
|
193
|
-
- No external systems are involved (live email server, payment gateway)
|
|
194
|
-
- Data can be set up programmatically
|
|
195
|
-
|
|
196
|
-
**Mark as partially automatable** when:
|
|
197
|
-
- Some result requires human visual inspection
|
|
198
|
-
- An external system is involved but can be mocked (email intercept, API stub)
|
|
199
|
-
- Data setup requires a manual step first
|
|
200
|
-
|
|
201
|
-
**Mark as not automatable** when:
|
|
202
|
-
- Requires physical access or real hardware
|
|
203
|
-
- Result is inherently non-deterministic (performance, visual design)
|
|
204
|
-
- Test would create irreversible side effects in QA environment (live invoice, real payment)
|
|
205
|
-
- The feature is blocked by permissions that cannot be granted to QA users
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
# Agent Instructions: Test Case Generation
|
|
2
|
-
|
|
3
|
-
> ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-test-cases/SKILL.md`.
|
|
4
|
-
> Kept as reference during the transition period. Do not update this file.
|
|
5
|
-
|
|
6
|
-
**File**: `agent-instructions/03-test-case-generation.md`
|
|
7
|
-
**Purpose**: Instructions for writing detailed, standalone test case documents from approved spec scenarios.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## When to use
|
|
12
|
-
|
|
13
|
-
- When a TC from `05-test-scenarios.md` needs more detail than the table row provides
|
|
14
|
-
- When writing complex multi-step TCs that require dedicated documentation
|
|
15
|
-
- When preparing TCs for manual testers who need step-by-step instructions
|
|
16
|
-
|
|
17
|
-
---
|
|
18
|
-
|
|
19
|
-
## Test Case Template
|
|
20
|
-
|
|
21
|
-
```markdown
|
|
22
|
-
# TC-{MODULE}-{SUBMODULE}-{NNN}: {TC Title}
|
|
23
|
-
|
|
24
|
-
| Field | Value |
|
|
25
|
-
|-------|-------|
|
|
26
|
-
| TC ID | TC-{MODULE}-{SUBMODULE}-{NNN} |
|
|
27
|
-
| Module | {Module display name} |
|
|
28
|
-
| Submodule | {Submodule display name} |
|
|
29
|
-
| Priority | P0 / P1 / P2 / P3 |
|
|
30
|
-
| Type | Functional / Negative / Regression / Security / Integration |
|
|
31
|
-
| Origin | UI-OBSERVED / PENDING-CODE / BLOCKED-PERMISSIONS |
|
|
32
|
-
| Observation date | YYYY-MM-DD |
|
|
33
|
-
| Automatable | Yes / Partial / No |
|
|
34
|
-
| Playwright file | (fill when automation is written) |
|
|
35
|
-
| Status | Draft / Approved / Automated / Deprecated |
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Objective
|
|
40
|
-
|
|
41
|
-
{1-2 sentences: what this test case verifies and why it matters}
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
## Preconditions
|
|
46
|
-
|
|
47
|
-
1. User is logged in as **{role}**
|
|
48
|
-
2. The following data exists in the QA environment:
|
|
49
|
-
- {item 1}: {description}
|
|
50
|
-
- {item 2}: {description}
|
|
51
|
-
3. {any other system state requirement}
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## Test Data
|
|
56
|
-
|
|
57
|
-
| Field | Value |
|
|
58
|
-
|-------|-------|
|
|
59
|
-
| {field name} | {value or generation rule} |
|
|
60
|
-
| {field name} | Use `EXEC_IDX`-generated value for uniqueness |
|
|
61
|
-
| User | Credentials from `QA_USER_{ROLE}_EMAIL` env var |
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Steps
|
|
66
|
-
|
|
67
|
-
| Step | Action | Expected result |
|
|
68
|
-
|------|--------|----------------|
|
|
69
|
-
| 1 | Navigate to {URL} | {page loads, specific element visible} |
|
|
70
|
-
| 2 | Click {element description} | {modal opens / form appears / etc.} |
|
|
71
|
-
| 3 | Fill {field} with {value} | {field accepts input} |
|
|
72
|
-
| 4 | Click {submit/save/confirm button} | {success message / redirect / state change} |
|
|
73
|
-
| 5 | Verify {observable outcome} | {specific text, element, state} |
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## Expected Results
|
|
78
|
-
|
|
79
|
-
**Final state**: {what the system should look like after all steps are complete}
|
|
80
|
-
|
|
81
|
-
**Verification points**:
|
|
82
|
-
- [ ] {verification 1}: {element} should {state}
|
|
83
|
-
- [ ] {verification 2}: {element} should contain {text}
|
|
84
|
-
- [ ] {verification 3}: page/modal should transition to {expected state}
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## Known Issues / Related Defects
|
|
89
|
-
|
|
90
|
-
| Issue | DEF-ID / ADO WI | Status | Impact on this TC |
|
|
91
|
-
|-------|----------------|--------|------------------|
|
|
92
|
-
| {description} | DEF-NNN | Open | TC skipped until resolved |
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Evidence
|
|
97
|
-
|
|
98
|
-
{Link to screenshot or video from execution, if available}
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## Automation Notes
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
// Playwright selector for key element (discovered during implementation)
|
|
106
|
-
// page.locator('{selector}')
|
|
107
|
-
|
|
108
|
-
// Key assertion
|
|
109
|
-
// await expect(page.locator('{selector}')).toHaveText('{expected text}');
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
---
|
|
113
|
-
|
|
114
|
-
## Changelog
|
|
115
|
-
|
|
116
|
-
| Version | Date | Author | Description |
|
|
117
|
-
|---------|------|--------|-------------|
|
|
118
|
-
| 1.0 | YYYY-MM-DD | {author} | Initial creation |
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## Rules for TC Content Quality
|
|
124
|
-
|
|
125
|
-
### Write measurable expected results
|
|
126
|
-
|
|
127
|
-
❌ BAD: "The system should work correctly"
|
|
128
|
-
✅ GOOD: "A success toast message 'Record saved' appears and the datatable row count increases by 1"
|
|
129
|
-
|
|
130
|
-
❌ BAD: "The form validates the input"
|
|
131
|
-
✅ GOOD: "A red validation message 'This field is required' appears below the Name field"
|
|
132
|
-
|
|
133
|
-
### Write observable steps
|
|
134
|
-
|
|
135
|
-
❌ BAD: "Add a new record with valid data"
|
|
136
|
-
✅ GOOD: "Click the 'New' button. Fill 'Name' with 'Test-{EXEC_IDX}'. Click 'Save'."
|
|
137
|
-
|
|
138
|
-
### Link to defects explicitly
|
|
139
|
-
|
|
140
|
-
If a TC is skipped due to a bug:
|
|
141
|
-
✅ GOOD: "Step 4 — SKIPPED: DEF-001 (ADO #21944). The switch defaults to OFF when it should be ON. Reactivate after fix."
|
|
142
|
-
|
|
143
|
-
### Priority guidelines recap
|
|
144
|
-
|
|
145
|
-
| Priority | Use when |
|
|
146
|
-
|---|---|
|
|
147
|
-
| P0 | Core feature is unusable without this working |
|
|
148
|
-
| P1 | Major functionality gap if this fails |
|
|
149
|
-
| P2 | Minor functionality gap, workaround exists |
|
|
150
|
-
| P3 | Edge case, cosmetic, or rare scenario |
|
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
# Agent Instructions: Automation Generation
|
|
2
|
-
|
|
3
|
-
> ⚠️ **DEPRECATED**: This file is superseded by `.github/skills/qa-automation/SKILL.md`.
|
|
4
|
-
> Kept as reference during the transition period. Do not update this file.
|
|
5
|
-
|
|
6
|
-
**File**: `agent-instructions/04-automation-generation.md`
|
|
7
|
-
**Purpose**: Instructions for writing Playwright E2E automation tests that trace back to approved test cases in `01-specifications/`.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
> **Prerequisite**: Specifications must be reviewed and approved before writing automation. Do not automate TCs that are `PENDING-CODE` or `BLOCKED-PERMISSIONS`.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## Structure: How to Organize Spec Files
|
|
16
|
-
|
|
17
|
-
Each module gets a directory under `qa/07-automation/e2e/tests/`:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
qa/07-automation/e2e/tests/
|
|
21
|
-
└── {module-kebab}/
|
|
22
|
-
├── COVERAGE-MAPPING.md ← TC-ID → spec location map
|
|
23
|
-
├── {suite-name}.spec.ts ← P0 suite
|
|
24
|
-
├── {suite-name}-p1.spec.ts ← P1 suite
|
|
25
|
-
└── integration/
|
|
26
|
-
└── cross-module.spec.ts ← Cross-module dependencies
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Spec file naming: `{description}.spec.ts` in kebab-case.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Spec File Template
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
/**
|
|
37
|
-
* @module {MODULE_CODE}
|
|
38
|
-
* @submodule {SUBMODULE_CODE}
|
|
39
|
-
* @spec qa/01-specifications/module-{name}/submodule-{name}/05-test-scenarios.md
|
|
40
|
-
* @priority P0
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
import { test, expect } from '@playwright/test';
|
|
44
|
-
|
|
45
|
-
// EXEC_IDX: changes every 60 seconds, provides collision-resistant unique values
|
|
46
|
-
const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
|
|
47
|
-
|
|
48
|
-
test.describe('{Feature Suite Name}', () => {
|
|
49
|
-
|
|
50
|
-
test.beforeAll(async ({ browser }) => {
|
|
51
|
-
// Provision data needed by tests in this suite
|
|
52
|
-
// Rule: provision AT LEAST as many records as tests that consume them
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('[TC-{MODULE}-{SUB}-001] {TC title} @P0', async ({ page }) => {
|
|
56
|
-
// Arrange
|
|
57
|
-
// ...
|
|
58
|
-
|
|
59
|
-
// Act
|
|
60
|
-
// ...
|
|
61
|
-
|
|
62
|
-
// Assert
|
|
63
|
-
// ...
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('[TC-{MODULE}-{SUB}-002] {TC title} @P1', async ({ page }) => {
|
|
67
|
-
// ...
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test.skip('[TC-{MODULE}-{SUB}-003] {TC title} @P1 — DEF-{NNN}: {description}. Reactivate when {ADO WI or DEF ID} is resolved.', async ({ page }) => {
|
|
71
|
-
// Skip body: write the test as if the bug were fixed
|
|
72
|
-
// This documents the expected behavior, not the buggy state
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
});
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Required Patterns
|
|
81
|
-
|
|
82
|
-
### Pattern 1: EXEC_IDX — Unique Test Data
|
|
83
|
-
|
|
84
|
-
Use EXEC_IDX everywhere you create records to avoid collisions between consecutive test runs:
|
|
85
|
-
|
|
86
|
-
```typescript
|
|
87
|
-
const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
|
|
88
|
-
|
|
89
|
-
// For titles/names
|
|
90
|
-
const entityName = `Test-Record-${EXEC_IDX}`;
|
|
91
|
-
|
|
92
|
-
// For dates (future-dated to avoid prod data collisions)
|
|
93
|
-
const year = 2120 + (EXEC_IDX % 10);
|
|
94
|
-
const month = String((EXEC_IDX % 12) + 1).padStart(2, '0');
|
|
95
|
-
const day = String((EXEC_IDX % 28) + 1).padStart(2, '0');
|
|
96
|
-
const testDate = `${year}-${month}-${day}`;
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
Why year 2120+: avoids any overlap with real production data.
|
|
100
|
-
Why modular arithmetic: the date always represents a valid date, never day 32 or month 13.
|
|
101
|
-
|
|
102
|
-
### Pattern 2: Multi-Role Auth with storageState
|
|
103
|
-
|
|
104
|
-
Use `global-setup.ts` to log in once per role and save storageState:
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
// playwright.config.ts
|
|
108
|
-
use: {
|
|
109
|
-
storageState: '.auth/session.json', // single role
|
|
110
|
-
// or: storageState: (workerInfo) => `.auth/role-${workerInfo.workerIndex}.json`
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// global-setup.ts — runs once before all tests
|
|
114
|
-
async function globalSetup(config) {
|
|
115
|
-
const browser = await chromium.launch();
|
|
116
|
-
const page = await browser.newPage();
|
|
117
|
-
|
|
118
|
-
// Log in and save session
|
|
119
|
-
await page.goto(process.env.QA_BASE_URL + process.env.QA_LOGIN_PATH);
|
|
120
|
-
await page.fill(process.env.QA_LOGIN_EMAIL_SELECTOR, process.env.QA_USER_EMAIL);
|
|
121
|
-
// Use evaluate() for password — excluded from traces
|
|
122
|
-
await page.evaluate(
|
|
123
|
-
([sel, pwd]) => { (document.querySelector(sel) as HTMLInputElement).value = pwd; },
|
|
124
|
-
[process.env.QA_LOGIN_PASSWORD_SELECTOR, process.env.QA_USER_PASSWORD]
|
|
125
|
-
);
|
|
126
|
-
await page.click(process.env.QA_LOGIN_SUBMIT_SELECTOR);
|
|
127
|
-
await page.waitForURL(url => !url.includes(process.env.QA_LOGIN_PATH));
|
|
128
|
-
|
|
129
|
-
await page.context().storageState({ path: '.auth/session.json' });
|
|
130
|
-
await browser.close();
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
For multi-role: call login sequence sequentially for each role (apps often reject concurrent sessions).
|
|
135
|
-
|
|
136
|
-
### Pattern 3: Fast-Fail for Status Checks
|
|
137
|
-
|
|
138
|
-
When checking the text content of status indicators, use a short timeout to prevent hanging:
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
// BAD: inherits the full test timeout (30s or more)
|
|
142
|
-
const status = await page.locator('.status-badge').textContent();
|
|
143
|
-
|
|
144
|
-
// GOOD: fails fast if not available in 3 seconds
|
|
145
|
-
const status = await page.locator('.status-badge').textContent({ timeout: 3_000 });
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### Pattern 4: Email Validation — 3-Layer Strategy
|
|
149
|
-
|
|
150
|
-
When testing email notification behavior without a real inbox:
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
// Layer 1: HTTP route interception (most reliable)
|
|
154
|
-
const emailRequests: string[] = [];
|
|
155
|
-
await page.route('**/*mail*', (route) => {
|
|
156
|
-
emailRequests.push(route.request().url());
|
|
157
|
-
route.continue();
|
|
158
|
-
});
|
|
159
|
-
await page.route('**/*correo*', (route) => {
|
|
160
|
-
emailRequests.push(route.request().url());
|
|
161
|
-
route.continue();
|
|
162
|
-
});
|
|
163
|
-
// ... perform the action ...
|
|
164
|
-
expect(emailRequests.length).toBeGreaterThan(0);
|
|
165
|
-
|
|
166
|
-
// Layer 2: UI confirmation (toast, banner, badge)
|
|
167
|
-
await expect(page.locator('.email-sent-indicator')).toBeVisible();
|
|
168
|
-
|
|
169
|
-
// Layer 3: test.fixme() — if inbox access is needed and not available
|
|
170
|
-
test.fixme(process.env.QA_MAILBOX_ACCESS !== 'true', 'Requires mailbox access');
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### Pattern 5: Skip Pattern for Known Bugs
|
|
174
|
-
|
|
175
|
-
```typescript
|
|
176
|
-
test.skip(true,
|
|
177
|
-
'DEF-001: {Description of bug}. ' +
|
|
178
|
-
'Expected: {expected behavior}. ' +
|
|
179
|
-
'Actual: {buggy behavior}. ' +
|
|
180
|
-
'Reactivate when ADO #{WI_ID} / DEF-001 is resolved.'
|
|
181
|
-
);
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
**Never** make a test artificially "pass" around a bug. Document with exact expected behavior.
|
|
185
|
-
|
|
186
|
-
### Pattern 6: beforeAll Provisioning Ratio
|
|
187
|
-
|
|
188
|
-
In `beforeAll`, create **at least as many records as the number of tests that consume them**:
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
test.beforeAll(async ({ browser }) => {
|
|
192
|
-
const page = await browser.newPage();
|
|
193
|
-
// If 3 tests each need 1 different pending record:
|
|
194
|
-
const records: string[] = [];
|
|
195
|
-
for (let i = 0; i < 3; i++) {
|
|
196
|
-
const id = await createRecord(page, `Record-${EXEC_IDX}-${i}`);
|
|
197
|
-
records.push(id);
|
|
198
|
-
}
|
|
199
|
-
// Store in closure or page object for use in tests
|
|
200
|
-
});
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
### Pattern 7: Password Injection (Trace Safety)
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
// Passwords must be set via evaluate() to exclude from Playwright traces
|
|
207
|
-
await page.evaluate(
|
|
208
|
-
([selector, pwd]) => {
|
|
209
|
-
(document.querySelector(selector) as HTMLInputElement).value = pwd;
|
|
210
|
-
},
|
|
211
|
-
[process.env.QA_LOGIN_PASSWORD_SELECTOR, process.env.QA_USER_PASSWORD]
|
|
212
|
-
);
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
---
|
|
216
|
-
|
|
217
|
-
## `playwright.config.ts` Checklist
|
|
218
|
-
|
|
219
|
-
Every project Playwright config should configure:
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
export default defineConfig({
|
|
223
|
-
testDir: './tests',
|
|
224
|
-
timeout: 30_000, // Per-test timeout
|
|
225
|
-
actionTimeout: 10_000, // Per-action timeout (REQUIRED — prevents silent hangs)
|
|
226
|
-
navigationTimeout: 60_000, // Per-navigation timeout
|
|
227
|
-
retries: process.env.CI ? 2 : 0,
|
|
228
|
-
workers: process.env.CI ? 1 : 2,
|
|
229
|
-
|
|
230
|
-
// Exclude seeds and debug scripts from normal runs
|
|
231
|
-
testIgnore: ['**/seeds/**', '**/debug-*.spec.ts', '**/seed.spec.ts'],
|
|
232
|
-
|
|
233
|
-
use: {
|
|
234
|
-
baseURL: process.env.QA_BASE_URL,
|
|
235
|
-
storageState: '.auth/session.json',
|
|
236
|
-
locale: 'en-US', // or 'es-CL' for Chilean apps
|
|
237
|
-
screenshot: 'only-on-failure',
|
|
238
|
-
video: 'retain-on-failure',
|
|
239
|
-
trace: 'on-first-retry',
|
|
240
|
-
},
|
|
241
|
-
|
|
242
|
-
reporter: [
|
|
243
|
-
['html', { outputFolder: 'playwright-report' }],
|
|
244
|
-
// ADO reporter: only when integration enabled
|
|
245
|
-
// ['@alex_neo/playwright-azure-reporter', { ... }],
|
|
246
|
-
],
|
|
247
|
-
|
|
248
|
-
projects: [
|
|
249
|
-
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
|
|
250
|
-
// Add firefox, webkit when cross-browser coverage is needed
|
|
251
|
-
],
|
|
252
|
-
|
|
253
|
-
globalSetup: './global-setup.ts',
|
|
254
|
-
outputDir: '../../05-test-execution/automated/test-results',
|
|
255
|
-
});
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
`actionTimeout` is **not optional**. Without it, `textContent()`, `getAttribute()`, and similar calls inherit the full test timeout and can silently hang if the element is slow.
|
|
259
|
-
|
|
260
|
-
---
|
|
261
|
-
|
|
262
|
-
## Stability Criteria
|
|
263
|
-
|
|
264
|
-
A test is only considered stable when:
|
|
265
|
-
|
|
266
|
-
1. It passes ≥ 2 consecutive runs with **different** `EXEC_IDX` values (i.e., at least 60 seconds apart)
|
|
267
|
-
2. It does not rely on another test's side effects
|
|
268
|
-
3. It produces the same result across 3+ independent runs
|
|
269
|
-
4. No `waitForTimeout(N)` longer than 2000ms is used (use `waitForSelector` or `waitForLoadState` instead)
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
## Debugging Failed Tests
|
|
274
|
-
|
|
275
|
-
Use this 5-layer methodology:
|
|
276
|
-
|
|
277
|
-
1. **Environment layer**: Is QA_BASE_URL reachable? Are credentials valid? Run login test first.
|
|
278
|
-
2. **Timeout layer**: Did the test fail with "timeout" or "Timeout exceeded"? Check `actionTimeout`, increase if justified.
|
|
279
|
-
3. **Data layer**: Did `beforeAll` create the expected records? Add `console.log` per step in `beforeAll`.
|
|
280
|
-
4. **Code layer**: Is the selector correct? Use page.pause() or Playwright UI mode to inspect.
|
|
281
|
-
5. **System defect layer**: Is the failure due to a real bug? File a defect and add `test.skip()`.
|
|
282
|
-
|
|
283
|
-
**Diagnostic script pattern**: For complex data discovery, create a diagnostic spec in `helpers/debug/`:
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
// helpers/debug/inspect-{feature}.spec.ts
|
|
287
|
-
test('diagnostic: dump form options', async ({ page }) => {
|
|
288
|
-
await page.goto(`${process.env.QA_BASE_URL}/my-form`);
|
|
289
|
-
const options = await page.$$eval('select option', els =>
|
|
290
|
-
els.map(el => ({ value: el.value, text: el.textContent }))
|
|
291
|
-
);
|
|
292
|
-
console.log(JSON.stringify(options, null, 2));
|
|
293
|
-
});
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
This is not part of the test suite (excluded via `testIgnore`). Use it to discover valid option values.
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## Coverage Mapping Document
|
|
301
|
-
|
|
302
|
-
After writing automation for a module, create `COVERAGE-MAPPING.md` in the test directory:
|
|
303
|
-
|
|
304
|
-
```markdown
|
|
305
|
-
# Coverage Mapping — {Module}
|
|
306
|
-
|
|
307
|
-
| TC ID | Title | Spec file | Playwright spec | Status |
|
|
308
|
-
|-------|-------|-----------|----------------|--------|
|
|
309
|
-
| TC-OPER-CAT-001 | Access catalog list | 01-specifications/.../05-test-scenarios.md | tests/operacion/catalogos/critical.spec.ts | ✅ Automated |
|
|
310
|
-
| TC-OPER-CAT-002 | Create labor type | ... | tests/operacion/... | ✅ Automated |
|
|
311
|
-
| TC-OPER-CAT-003 | Duplicate rejection | ... | tests/operacion/... | ⚠️ Partially (UI only) |
|
|
312
|
-
| TC-OPER-ASI-001 | Access assistance list | ... | — | ⛔ Blocked (BLOCKED-PERMISSIONS) |
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## Module Completion Checklist
|
|
318
|
-
|
|
319
|
-
Run this checklist when all P0 tests for a module are passing.
|
|
320
|
-
|
|
321
|
-
### Stability gate
|
|
322
|
-
- [ ] All P0 tests pass on **2 consecutive runs** with different `EXEC_IDX` values (≥ 60 seconds apart)
|
|
323
|
-
- [ ] No `waitForTimeout(N)` longer than 2000ms left in the suite
|
|
324
|
-
- [ ] All skipped tests have a `DEF-` or ADO WI reference in their skip message
|
|
325
|
-
|
|
326
|
-
### Artifacts
|
|
327
|
-
- [ ] `COVERAGE-MAPPING.md` created or updated in the test directory
|
|
328
|
-
- [ ] Execution report written to `qa/05-test-execution/automated/`
|
|
329
|
-
|
|
330
|
-
### Living Index update — `qa/README.md`
|
|
331
|
-
- [ ] Update the module's row in the status table (TCs automated, date, status → ✅)
|
|
332
|
-
- [ ] Add a row to the `## Sprint History` section with: sprint name, date, submódulos covered, TC count, link to execution report
|
|
333
|
-
|
|
334
|
-
### AGENT-NEXT-STEPS.md — trim
|
|
335
|
-
- [ ] Move the completed sprint checklist block to `qa/README.md` under `## Sprint History`
|
|
336
|
-
- [ ] Delete the completed sprint section from `AGENT-NEXT-STEPS.md`
|
|
337
|
-
- [ ] Verify `AGENT-NEXT-STEPS.md` now contains **only one active sprint** (the next one)
|
|
338
|
-
|
|
339
|
-
### Memory
|
|
340
|
-
- [ ] If new patterns or environment quirks were discovered: add them to `qa/memory/` with a descriptive filename
|
|
341
|
-
- [ ] Update `qa/memory/INDEX.md` to reflect any new or updated files
|
|
342
|
-
|
|
343
|
-
> **Rule**: `AGENT-NEXT-STEPS.md` is a task queue, not a log. Completed sprints live in `qa/README.md`. The file must never accumulate more than one active sprint.
|