@keber/qa-framework 1.11.3 → 1.13.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/CHANGELOG.md +340 -0
- package/README.md +42 -2
- package/docs/architecture.md +30 -26
- package/docs/decisions/lane-heartbeat-caller.md +86 -0
- package/docs/final-report.md +23 -23
- package/docs/folder-structure-guide.md +100 -80
- package/docs/installation.md +42 -7
- package/docs/skills-architecture.md +23 -23
- package/docs/spec-driven-philosophy.md +9 -9
- package/docs/usage-with-agent.md +88 -9
- package/docs/visuals/diag-01-ejecutivo-1.png +0 -0
- package/docs/visuals/diag-02-tactico-1.png +0 -0
- package/docs/visuals/diag-03-tecnico-1.png +0 -0
- package/docs/visuals/info-01-ejecutivo-1.png +0 -0
- package/docs/visuals/info-02-tactico-1.png +0 -0
- package/docs/visuals/info-03-tecnico-1.png +0 -0
- package/docs/visuals/pres-01-ejecutivo-1.png +0 -0
- package/docs/visuals/pres-02-tactico-1.png +0 -0
- package/docs/visuals/pres-03-tecnico-1.png +0 -0
- package/docs/visuals/qa-01-problema-1.png +0 -0
- package/docs/visuals/qa-02-que-es-1.png +0 -0
- package/docs/visuals/qa-03-pipeline-1.png +0 -0
- package/docs/visuals/qa-04-6-archivos-1.png +0 -0
- package/docs/visuals/qa-05-humano-1.png +0 -0
- package/docs/visuals/qa-06-agente-1.png +0 -0
- package/docs/visuals/qa-07-skills-arch-1.png +0 -0
- package/docs/visuals/qa-08-traceability-1.png +0 -0
- package/docs/visuals/qa-en-01-problem-1.png +0 -0
- package/docs/visuals/qa-en-02-what-is-1.png +0 -0
- package/docs/visuals/qa-en-03-pipeline-1.png +0 -0
- package/docs/visuals/qa-en-04-6files-1.png +0 -0
- package/docs/visuals/qa-en-05-human-1.png +0 -0
- package/docs/visuals/qa-en-06-agent-1.png +0 -0
- package/docs/visuals/qa-en-07-skills-arch-1.png +0 -0
- package/docs/visuals/qa-en-08-traceability-1.png +0 -0
- package/examples/module-example/suppliers/00-inventory.md +1 -1
- package/examples/module-example/suppliers/suppliers-create.spec.ts +8 -8
- package/integrations/ado-powershell/README.md +1 -1
- package/integrations/ado-powershell/scripts/sync-ado-titles.ps1 +2 -2
- package/integrations/playwright/README.md +4 -4
- package/package.json +7 -3
- package/qa-framework.config.json +25 -3
- package/scripts/check-forbidden-chars.js +187 -0
- package/scripts/check-spanish-accents.js +159 -0
- package/scripts/cli.js +1 -1
- package/scripts/generate.js +2 -2
- package/scripts/init.js +101 -12
- package/scripts/lib/claude-agents.js +347 -0
- package/scripts/lib/claude-commands.js +56 -0
- package/scripts/lib/module-keys.js +54 -0
- package/scripts/sync-version.js +63 -0
- package/scripts/upgrade.js +369 -20
- package/scripts/validate.js +46 -21
- package/skills/qa-ado-integration/SKILL.md +19 -19
- package/skills/qa-ado-integration/references/scripts-and-config.md +6 -6
- package/skills/qa-automation/SKILL.md +49 -27
- package/skills/qa-automation/references/config-checklist.md +4 -4
- package/skills/qa-automation/references/dom-inspection-template.js +7 -7
- package/skills/qa-automation/references/patterns.md +20 -20
- package/skills/qa-automation/references/pom-template.md +161 -0
- package/skills/qa-maintenance/SKILL.md +11 -11
- package/skills/qa-maintenance/references/update-rules.md +8 -8
- package/skills/qa-module-analysis/SKILL.md +20 -19
- package/skills/qa-module-analysis/references/exploration-checklist.md +4 -4
- package/skills/qa-module-analysis/references/output-verification.md +69 -0
- package/skills/qa-module-analysis/references/spec-file-formats.md +14 -14
- package/skills/qa-spec-generation/SKILL.md +13 -7
- package/skills/qa-test-cases/SKILL.md +11 -81
- package/skills/qa-test-cases/references/test-case-template.md +5 -5
- package/skills/qa-test-plan/SKILL.md +22 -86
- package/skills/qa-test-plan/references/plan-de-pruebas-template.md +24 -24
- package/skills/qa-test-stabilization/SKILL.md +59 -30
- package/skills/qa-test-stabilization/references/classification-protocol.md +35 -35
- package/templates/agent-next-steps.md +10 -10
- package/templates/agents/qa-analisis.md +142 -0
- package/templates/agents/qa-asesoria.md +48 -0
- package/templates/agents/qa-informe-resultados.md +236 -0
- package/templates/agents/qa-investigador.md +143 -0
- package/templates/agents/qa-plan.md +131 -0
- package/templates/agents/qa-reporte-ejecucion.md +138 -0
- package/templates/automation-scaffold/.env.example +36 -6
- package/templates/automation-scaffold/fixtures/auth.ts +27 -5
- package/templates/automation-scaffold/fixtures/base.ts +23 -1
- package/templates/automation-scaffold/fixtures/test-helpers.ts +1 -1
- package/templates/automation-scaffold/global-setup.ts +117 -48
- package/templates/automation-scaffold/playwright.config.ts +72 -32
- package/templates/automation-scaffold/scripts/global-setup-guards.js +184 -0
- package/templates/automation-scaffold/scripts/lane-config.js +269 -0
- package/templates/automation-scaffold/scripts/lane-lock.js +589 -0
- package/templates/defect-report.md +17 -3
- package/templates/execution-report.md +9 -9
- package/templates/integration-scaffold/.env.example +1 -1
- package/templates/integration-scaffold/global-setup.ts +21 -1
- package/templates/integration-scaffold/playwright.config.ts +15 -1
- package/templates/qa-framework.instructions.md +9 -8
- package/templates/qa-framework.rules.md +53 -0
- package/templates/qa-readme.md +8 -8
- package/templates/session-summary.md +2 -2
- package/templates/specification/00-inventory.md +3 -3
- package/templates/specification/01-business-rules.md +6 -6
- package/templates/specification/02-workflows.md +1 -1
- package/templates/specification/03-roles-permissions.md +1 -1
- package/templates/specification/04-test-data.md +8 -8
- package/templates/specification/05-test-scenarios.md +5 -5
- package/templates/test-case.md +3 -3
- package/templates/test-data-guidelines.md +7 -7
- package/templates/test-plan-sprint.md +13 -13
- package/templates/test-plan.md +3 -3
- package/skills/qa-test-plan/references/priority-and-feasibility.md +0 -159
|
@@ -12,31 +12,31 @@ description: >
|
|
|
12
12
|
|
|
13
13
|
# QA Skill: ADO Integration (Optional Stage)
|
|
14
14
|
|
|
15
|
-
**Stage**: Optional
|
|
15
|
+
**Stage**: Optional - ADO Integration (no pipeline order dependency)
|
|
16
16
|
**Prerequisite**: `Plan-de-Pruebas-{proyecto}-Sprint-{N}-{modulo}.md` exists with a complete Tabla de Pruebas (steps filled in); valid `ADO_PAT` env var
|
|
17
17
|
**Output**: ADO Test Plan populated with Test Suites and Test Cases (with steps) + `qa/08-azure-integration/module-registry.json` updated
|
|
18
|
-
**Use any time** after Stage 3 (Plan de Pruebas) is ready
|
|
18
|
+
**Use any time** after Stage 3 (Plan de Pruebas) is ready - Stage 4 and 5 are not required
|
|
19
19
|
|
|
20
20
|
> **Credential rule**: NEVER hardcode PAT, username, or organization URL in any file. Always read from env vars or `<PLACEHOLDER>` in documentation.
|
|
21
|
-
> **Steps rule**: ADO Test Cases must have steps. Do not sync TCs from a Plan de Pruebas with empty or summary-only steps
|
|
21
|
+
> **Steps rule**: ADO Test Cases must have steps. Do not sync TCs from a Plan de Pruebas with empty or summary-only steps - run Stage 4 first to expand them.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
25
|
## Inputs Required
|
|
26
26
|
|
|
27
|
-
1. `qa/qa-framework.config.json`
|
|
28
|
-
2. `qa/02-test-plans/sprints/Sprint-{N}/Plan-de-Pruebas-{proyecto}-Sprint-{N}-{modulo}.md`
|
|
29
|
-
3. `ADO_PAT` environment variable
|
|
27
|
+
1. `qa/qa-framework.config.json` - ADO org URL, project name, test plan ID (or "create new")
|
|
28
|
+
2. `qa/02-test-plans/sprints/Sprint-{N}/Plan-de-Pruebas-{proyecto}-Sprint-{N}-{modulo}.md` - one file per module; each file's Tabla de Pruebas becomes one Test Suite in ADO
|
|
29
|
+
3. `ADO_PAT` environment variable - personal access token with Test Plans read/write
|
|
30
30
|
4. Optionally: `qa/08-azure-integration/module-registry.json` for existing ID mapping
|
|
31
31
|
|
|
32
32
|
> **Note**: The consolidated `Plan-de-Pruebas-{proyecto}-Sprint-{N}.md` (without module suffix)
|
|
33
|
-
> is for human reference only
|
|
33
|
+
> is for human reference only - do not use it as input for ADO scripts.
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
37
|
## Process
|
|
38
38
|
|
|
39
|
-
### Step 1
|
|
39
|
+
### Step 1 - Verify ADO config
|
|
40
40
|
|
|
41
41
|
Check `qa/qa-framework.config.json` for:
|
|
42
42
|
```json
|
|
@@ -48,25 +48,25 @@ Check `qa/qa-framework.config.json` for:
|
|
|
48
48
|
```
|
|
49
49
|
If `planId` is null, a new plan will be created in Step 2.
|
|
50
50
|
|
|
51
|
-
### Step 2
|
|
51
|
+
### Step 2 - Create or verify Test Plan
|
|
52
52
|
|
|
53
53
|
Use the PowerShell script: `integrations/ado-powershell/scripts/create-testplan-from-mapping.ps1`
|
|
54
54
|
|
|
55
55
|
See `references/scripts-and-config.md` for usage, parameters, and required env vars.
|
|
56
56
|
|
|
57
57
|
Required env vars:
|
|
58
|
-
- `$env:ADO_ORG`
|
|
59
|
-
- `$env:ADO_PROJECT`
|
|
60
|
-
- `$env:ADO_PAT`
|
|
58
|
+
- `$env:ADO_ORG` - organization URL (e.g., `https://dev.azure.com/myorg`)
|
|
59
|
+
- `$env:ADO_PROJECT` - project name
|
|
60
|
+
- `$env:ADO_PAT` - PAT token
|
|
61
61
|
|
|
62
|
-
### Step 3
|
|
62
|
+
### Step 3 - Sync test cases from Plan de Pruebas
|
|
63
63
|
|
|
64
64
|
For each `Plan-de-Pruebas-{proyecto}-Sprint-{N}-{modulo}.md` file:
|
|
65
65
|
1. Read the Tabla de Pruebas
|
|
66
66
|
2. Create one **Test Suite** in ADO named after the module (or use the suite groupings from section 5 of the plan)
|
|
67
67
|
3. For each row in the table, create one **Test Case** with:
|
|
68
68
|
- Title: the Título column value
|
|
69
|
-
- Steps: the Steps column value (numbered steps, `<br>`-separated
|
|
69
|
+
- Steps: the Steps column value (numbered steps, `<br>`-separated -> each becomes one ADO step)
|
|
70
70
|
- Expected result: the Resultado Esperado column value
|
|
71
71
|
- Tags: Tipo + Prioridad values
|
|
72
72
|
4. Write the returned ADO Test Case IDs back into the table (column "ADO WI") and into `module-registry.json`
|
|
@@ -75,19 +75,19 @@ Use `inject-ado-ids.ps1` to automate the create + inject cycle.
|
|
|
75
75
|
|
|
76
76
|
After sync, each row in the Plan de Pruebas table must have an ADO WI ID.
|
|
77
77
|
|
|
78
|
-
### Step 4
|
|
78
|
+
### Step 4 - Configure Playwright ADO reporter
|
|
79
79
|
|
|
80
80
|
See `references/scripts-and-config.md` for the reporter config block to add to `qa/07-automation/e2e/playwright.config.ts`.
|
|
81
81
|
|
|
82
82
|
Required fields:
|
|
83
83
|
- `orgUrl`, `projectName`, `planId`, `runName`
|
|
84
|
-
- All values must come from environment variables
|
|
84
|
+
- All values must come from environment variables - no hardcoded IDs
|
|
85
85
|
|
|
86
|
-
### Step 5
|
|
86
|
+
### Step 5 - Run sync and validate
|
|
87
87
|
|
|
88
88
|
Run `sync-ado-titles.ps1` after automation runs to update ADO test outcomes from Playwright report JSON.
|
|
89
89
|
|
|
90
|
-
### Step 6
|
|
90
|
+
### Step 6 - Update registry
|
|
91
91
|
|
|
92
92
|
Update `qa/08-azure-integration/module-registry.json` with:
|
|
93
93
|
- Module name
|
|
@@ -112,6 +112,6 @@ Update `qa/08-azure-integration/module-registry.json` with:
|
|
|
112
112
|
## Outputs
|
|
113
113
|
|
|
114
114
|
- ADO Test Plan populated with test cases
|
|
115
|
-
- `qa/03-test-cases/automated/TC-*.md`
|
|
115
|
+
- `qa/03-test-cases/automated/TC-*.md` - ADO IDs injected
|
|
116
116
|
- `qa/08-azure-integration/module-registry.json` updated
|
|
117
117
|
- `qa/07-automation/e2e/playwright.config.ts` updated with reporter config
|
|
@@ -18,7 +18,7 @@ Creates a new ADO Test Plan with suites and test cases from the mapping JSON fil
|
|
|
18
18
|
-MappingFile .\qa\08-azure-integration\ado-ids-mapping-{project}.json
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
Output: `TestPlanId` and `SuiteIds`
|
|
21
|
+
Output: `TestPlanId` and `SuiteIds` - record in `module-registry.json`.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
@@ -104,7 +104,7 @@ Apply with `-DryRun:$false`.
|
|
|
104
104
|
"specsPath": "qa/07-automation/e2e/tests/{module-kebab}",
|
|
105
105
|
"planId": 0,
|
|
106
106
|
"suiteId": 0,
|
|
107
|
-
"description": "{Module display name}
|
|
107
|
+
"description": "{Module display name} - {N} submodules"
|
|
108
108
|
}
|
|
109
109
|
]
|
|
110
110
|
}
|
|
@@ -130,7 +130,7 @@ Add to `qa/07-automation/playwright.config.ts` reporter array:
|
|
|
130
130
|
}]
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
**`isDisabled: !process.env.CI`**
|
|
133
|
+
**`isDisabled: !process.env.CI`** - prevents publishing from local developer runs.
|
|
134
134
|
|
|
135
135
|
---
|
|
136
136
|
|
|
@@ -194,8 +194,8 @@ steps:
|
|
|
194
194
|
|
|
195
195
|
## Credential Security Rules
|
|
196
196
|
|
|
197
|
-
1. `ADO_PAT` is **never** committed to any file
|
|
197
|
+
1. `ADO_PAT` is **never** committed to any file - always from env var or CI variable group
|
|
198
198
|
2. `ADO_PAT` is **never** logged, printed, or written to any markdown file
|
|
199
199
|
3. If a PAT appears in any log or output: revoke it immediately in ADO Portal, generate new one
|
|
200
|
-
4. Variable group `qa-secrets` must be scoped to the pipeline only
|
|
201
|
-
5. PAT minimum scopes: `Work Items (Read, Write)`, `Test Management (Read, Write)`
|
|
200
|
+
4. Variable group `qa-secrets` must be scoped to the pipeline only - no project-wide access
|
|
201
|
+
5. PAT minimum scopes: `Work Items (Read, Write)`, `Test Management (Read, Write)` - never use full-access PATs
|
|
@@ -12,10 +12,10 @@ description: >
|
|
|
12
12
|
|
|
13
13
|
# QA Skill: Automation Generation (Stage 5 of 6)
|
|
14
14
|
|
|
15
|
-
**Stage**: 5
|
|
15
|
+
**Stage**: 5 - Automation
|
|
16
16
|
**Prerequisite**: All specs for the target submodule are complete and contain no `PENDING-CODE` sections
|
|
17
17
|
**Output**: `qa/07-automation/e2e/tests/{module}/{submodule}.spec.ts` + supporting files
|
|
18
|
-
**Next stage**: Stage 6
|
|
18
|
+
**Next stage**: Stage 6 - Maintenance (`qa-maintenance`) or Stage 5b - Stabilization (`qa-test-stabilization`) if tests fail
|
|
19
19
|
|
|
20
20
|
> **Pipeline rule**: Never automate a TC whose spec contains `PENDING-CODE`. Resolve spec gaps first.
|
|
21
21
|
|
|
@@ -23,27 +23,27 @@ description: >
|
|
|
23
23
|
|
|
24
24
|
## Inputs Required
|
|
25
25
|
|
|
26
|
-
1. `qa/01-specifications/{module}/`
|
|
27
|
-
2. `qa/07-automation/e2e/playwright.config.ts`
|
|
28
|
-
3. `qa/07-automation/e2e/fixtures/auth.ts`
|
|
29
|
-
4. TC list (from test plan or Stage 4)
|
|
30
|
-
5. `qa/qa-framework.config.json`
|
|
26
|
+
1. `qa/01-specifications/{module}/` - full spec set for target submodule
|
|
27
|
+
2. `qa/07-automation/e2e/playwright.config.ts` - confirm project name maps to submodule tag
|
|
28
|
+
3. `qa/07-automation/e2e/fixtures/auth.ts` - identify available auth fixtures
|
|
29
|
+
4. TC list (from test plan or Stage 4) - defines which TCs to automate in this session
|
|
30
|
+
5. `qa/qa-framework.config.json` -> screenshotPath, automationRoot
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
34
|
## Process
|
|
35
35
|
|
|
36
|
-
### Step 0
|
|
36
|
+
### Step 0 - Pre-inspection (MANDATORY before writing any test code)
|
|
37
37
|
|
|
38
38
|
For every new submodule, run a dedicated inspection script before writing tests.
|
|
39
|
-
**Template**: `references/dom-inspection-template.js`
|
|
39
|
+
**Template**: `references/dom-inspection-template.js` - copy, set the 4 constants at the top, run.
|
|
40
40
|
|
|
41
|
-
1. Copy `references/dom-inspection-template.js`
|
|
41
|
+
1. Copy `references/dom-inspection-template.js` -> `qa/07-automation/e2e/_inspect-{submodule}.js`
|
|
42
42
|
2. Set the 4 constants at the top of the script:
|
|
43
|
-
- `MODULE_ROUTE`
|
|
44
|
-
- `APP_SHELL_SEL`
|
|
45
|
-
- `CREATE_BTN`
|
|
46
|
-
- `BASE_URL`
|
|
43
|
+
- `MODULE_ROUTE` - the submodule's URL path (e.g. `'/Users'`, `'/Products/list'`)
|
|
44
|
+
- `APP_SHELL_SEL` - a selector that confirms the SPA has loaded (nav, sidebar, app shell)
|
|
45
|
+
- `CREATE_BTN` - regex matching the create/new button label in this app
|
|
46
|
+
- `BASE_URL` - already read from `process.env.QA_BASE_URL`
|
|
47
47
|
3. Run: `QA_BASE_URL=<env> node _inspect-{submodule}.js`
|
|
48
48
|
4. Paste key findings as a comment block at the **top of the `.spec.ts` file** before writing any test:
|
|
49
49
|
```
|
|
@@ -59,14 +59,14 @@ The template covers 5 inspection areas automatically: SPA warmup, list view (gri
|
|
|
59
59
|
**Never skip this step for submodules inside complex forms (tabs, dialogs, nested entities).
|
|
60
60
|
The cost of one inspection run is far lower than 10+ debugging iterations.**
|
|
61
61
|
|
|
62
|
-
### Step 1
|
|
62
|
+
### Step 1 - Scan for blockers
|
|
63
63
|
|
|
64
64
|
Before writing a line of code:
|
|
65
|
-
- Search all spec files for `PENDING-CODE`
|
|
65
|
+
- Search all spec files for `PENDING-CODE` - stop and flag if found
|
|
66
66
|
- Confirm `playwright.config.ts` exists; scaffold it if missing using `references/config-checklist.md`
|
|
67
67
|
- Verify `fixtures/auth.ts` has the roles required by this submodule
|
|
68
68
|
|
|
69
|
-
### Step 1b
|
|
69
|
+
### Step 1b - Decide POM vs inline locators
|
|
70
70
|
|
|
71
71
|
Create a Page Object in `qa/07-automation/e2e/page-objects/{SubmoduleName}Page.ts` when ANY of these is true:
|
|
72
72
|
- The submodule has a form with 5+ fields (locators will be reused across P0 + P1 suites)
|
|
@@ -77,7 +77,7 @@ Otherwise, inline locators are acceptable for simple catalog submodules (single
|
|
|
77
77
|
|
|
78
78
|
POM template: `references/pom-template.md`
|
|
79
79
|
|
|
80
|
-
### Step 2
|
|
80
|
+
### Step 2 - Scaffold spec file
|
|
81
81
|
|
|
82
82
|
Full spec file template and 7 implementation patterns: `references/patterns.md`
|
|
83
83
|
|
|
@@ -87,30 +87,30 @@ Required scaffold elements:
|
|
|
87
87
|
- `test.describe('{Submodule Name}', () => { ... })`
|
|
88
88
|
- Use fixture-based auth (never hardcode credentials)
|
|
89
89
|
|
|
90
|
-
### Step 3
|
|
90
|
+
### Step 3 - Implement tests in priority order
|
|
91
91
|
|
|
92
92
|
Implement P0 TCs first, then P1. Within each priority, follow scenario order from `05-test-scenarios.md`.
|
|
93
93
|
|
|
94
94
|
For each TC:
|
|
95
95
|
1. Map TC preconditions to `beforeAll`/`beforeEach` setup
|
|
96
96
|
2. Write navigation to the starting URL (use relative paths, not hardcoded base URL)
|
|
97
|
-
3. Use `test.step()` to group logical sub-actions
|
|
98
|
-
4. Assert observable outcomes
|
|
97
|
+
3. Use `test.step()` to group logical sub-actions - improves traceability
|
|
98
|
+
4. Assert observable outcomes - avoid asserting internal implementation details
|
|
99
99
|
|
|
100
|
-
### Step 4
|
|
100
|
+
### Step 4 - Apply stability rules
|
|
101
101
|
|
|
102
|
-
- Never use `waitForTimeout`
|
|
102
|
+
- Never use `waitForTimeout` - use `waitForSelector`, `waitForResponse`, or role-based locators
|
|
103
103
|
- Prefer `getByRole`, `getByLabel`, `getByTestId` over CSS selectors
|
|
104
104
|
- Locators attached to dynamic data must use `EXEC_IDX` suffix
|
|
105
|
-
- All test data cleared in `afterAll`
|
|
105
|
+
- All test data cleared in `afterAll` - never leave residue
|
|
106
106
|
|
|
107
|
-
### Step 4b
|
|
107
|
+
### Step 4b - Assertion polarity check (MANDATORY before committing any test)
|
|
108
108
|
|
|
109
109
|
Every assertion must be verified against the spec, not against the app's
|
|
110
110
|
observed output.
|
|
111
111
|
|
|
112
112
|
**Rule**: if the app does X but the spec requires NOT X, use `test.fail()`
|
|
113
|
-
with the correct assertion
|
|
113
|
+
with the correct assertion - do not adapt the assertion to match the app.
|
|
114
114
|
|
|
115
115
|
Red flags that require review before proceeding:
|
|
116
116
|
- `expect(X).toBe(false)` where the spec describes a positive condition
|
|
@@ -118,7 +118,27 @@ Red flags that require review before proceeding:
|
|
|
118
118
|
- Assertions inside an `if (condition)` that only execute on the happy path
|
|
119
119
|
- A test that starts passing after a refactor without a clear spec justification
|
|
120
120
|
|
|
121
|
-
### Step 5
|
|
121
|
+
### Step 5 - Static Check, Smoke Run & Completion Checklist
|
|
122
|
+
|
|
123
|
+
Two gates run **before** the checklist below. Both must come back clean.
|
|
124
|
+
|
|
125
|
+
**Gate 1 - static check.** From the automation root (`qa/07-automation/e2e`):
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
npx tsc --noEmit
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Must exit 0. Do not proceed with pending TypeScript errors.
|
|
132
|
+
|
|
133
|
+
**Gate 2 - smoke run.** Run every new or modified spec at least once against the official runner:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
npx playwright test {spec} --project={module} --reporter=list
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The goal is to surface reference, import and syntax errors that only appear at execution time - a variable used but never declared passes every review and fails only when the line runs. A full green suite is Stage 5b's job, not this gate's: a test that fails on a real assertion has still cleared Gate 2.
|
|
140
|
+
|
|
141
|
+
Only when both gates are clean, continue:
|
|
122
142
|
|
|
123
143
|
Before marking the submodule as ✅ Automation Complete:
|
|
124
144
|
- [ ] All P0 TCs passing in CI
|
|
@@ -127,6 +147,8 @@ Before marking the submodule as ✅ Automation Complete:
|
|
|
127
147
|
- [ ] `playwright.config.ts` project includes submodule tag
|
|
128
148
|
- [ ] `qa/README.md` automation status updated
|
|
129
149
|
- [ ] AGENT-NEXT-STEPS.md active sprint updated (remove completed items)
|
|
150
|
+
- [ ] `npx tsc --noEmit` run, exit 0
|
|
151
|
+
- [ ] New/modified specs run at least once via `npx playwright test` (smoke)
|
|
130
152
|
|
|
131
153
|
---
|
|
132
154
|
|
|
@@ -12,7 +12,7 @@ import { defineConfig, devices } from '@playwright/test';
|
|
|
12
12
|
export default defineConfig({
|
|
13
13
|
testDir: './tests',
|
|
14
14
|
timeout: 30_000, // Per-test timeout
|
|
15
|
-
actionTimeout: 10_000, // Per-action timeout
|
|
15
|
+
actionTimeout: 10_000, // Per-action timeout - REQUIRED, prevents silent hangs
|
|
16
16
|
navigationTimeout: 60_000, // Per-navigation timeout (SPAs may need longer)
|
|
17
17
|
retries: process.env.CI ? 2 : 0,
|
|
18
18
|
workers: process.env.CI ? 1 : 2,
|
|
@@ -31,7 +31,7 @@ export default defineConfig({
|
|
|
31
31
|
|
|
32
32
|
reporter: [
|
|
33
33
|
['html', { outputFolder: 'playwright-report' }],
|
|
34
|
-
// ADO reporter
|
|
34
|
+
// ADO reporter - add only when integration is enabled:
|
|
35
35
|
// ['@alex_neo/playwright-azure-reporter', {
|
|
36
36
|
// orgUrl: process.env.ADO_ORG,
|
|
37
37
|
// projectName: process.env.ADO_PROJECT,
|
|
@@ -59,7 +59,7 @@ export default defineConfig({
|
|
|
59
59
|
|
|
60
60
|
Before marking automation as complete, confirm:
|
|
61
61
|
|
|
62
|
-
- [ ] `actionTimeout` is set
|
|
62
|
+
- [ ] `actionTimeout` is set - **not optional**; without it, `textContent()` and similar calls silently hang
|
|
63
63
|
- [ ] `testIgnore` excludes seed scripts and debug files
|
|
64
64
|
- [ ] `baseURL` reads from `process.env.QA_BASE_URL` (never hardcoded)
|
|
65
65
|
- [ ] `storageState` path exists (created by `globalSetup`)
|
|
@@ -72,7 +72,7 @@ Before marking automation as complete, confirm:
|
|
|
72
72
|
|
|
73
73
|
## global-setup.ts Checklist
|
|
74
74
|
|
|
75
|
-
- [ ] Reads every credential from `process.env`
|
|
75
|
+
- [ ] Reads every credential from `process.env` - no hardcoded values
|
|
76
76
|
- [ ] Uses `evaluate()` for password input (trace safety)
|
|
77
77
|
- [ ] Saves storageState to `.auth/session.json` (or per-role paths)
|
|
78
78
|
- [ ] Handles login failure explicitly (does not silently save an unauthenticated state)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* DOM / API Inspection Script
|
|
2
|
+
* DOM / API Inspection Script - {SUBMODULE_DISPLAY_NAME}
|
|
3
3
|
*
|
|
4
4
|
* Purpose: Capture real UI structure before writing automation specs.
|
|
5
5
|
* Run ONCE per submodule. Output drives selector and fixture decisions.
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
const { chromium } = require('@playwright/test');
|
|
33
33
|
const path = require('path');
|
|
34
34
|
|
|
35
|
-
// ── Configuration
|
|
35
|
+
// ── Configuration - edit these 4 constants, leave the rest ───────────────────
|
|
36
36
|
const STATE_FILE = path.resolve(__dirname, '.auth/user-default.json');
|
|
37
37
|
const BASE_URL = process.env.QA_BASE_URL || '';
|
|
38
38
|
const MODULE_ROUTE = '/{EntityRoute}'; // e.g. '/Users', '/Orders/list'
|
|
@@ -54,7 +54,7 @@ async function run() {
|
|
|
54
54
|
console.log('BASE_URL:', BASE_URL);
|
|
55
55
|
console.log('MODULE_ROUTE:', MODULE_ROUTE);
|
|
56
56
|
|
|
57
|
-
// ── 0. Intercept API calls
|
|
57
|
+
// ── 0. Intercept API calls - runs passively throughout the entire session ──
|
|
58
58
|
const apiCalls = [];
|
|
59
59
|
page.on('request', req => {
|
|
60
60
|
try {
|
|
@@ -148,7 +148,7 @@ async function run() {
|
|
|
148
148
|
).catch(() => []);
|
|
149
149
|
console.log(' <select> elements:', JSON.stringify(selects, null, 2));
|
|
150
150
|
|
|
151
|
-
// Custom dropdowns
|
|
151
|
+
// Custom dropdowns - uses ARIA roles (framework-agnostic)
|
|
152
152
|
const customDDs = await page.$$eval(
|
|
153
153
|
'[role="combobox"], [role="listbox"], [aria-haspopup="listbox"]',
|
|
154
154
|
dds => dds.map((dd, i) => ({
|
|
@@ -181,7 +181,7 @@ async function run() {
|
|
|
181
181
|
).catch(() => []);
|
|
182
182
|
if (tabs.length > 0) console.log(' Tabs:', JSON.stringify(tabs));
|
|
183
183
|
|
|
184
|
-
// Validation
|
|
184
|
+
// Validation - submit empty form to capture required-field messages
|
|
185
185
|
const saveBtn = page.getByRole('button', { name: /guardar|save|submit|crear|create/i }).first();
|
|
186
186
|
if (await saveBtn.isVisible({ timeout: 3_000 }).catch(() => false)) {
|
|
187
187
|
await saveBtn.click();
|
|
@@ -194,7 +194,7 @@ async function run() {
|
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
// ── ADD EXTRA STEPS HERE for tabbed/nested forms ──────────────────────
|
|
197
|
-
// Example
|
|
197
|
+
// Example - inspect a specific tab:
|
|
198
198
|
// await page.getByRole('tab', { name: /identif/i }).click();
|
|
199
199
|
// await page.waitForTimeout(1_000);
|
|
200
200
|
// const tabDDs = await page.locator('[role="tab"][aria-selected="true"] + ... .rz-dropdown')...
|
|
@@ -227,7 +227,7 @@ async function run() {
|
|
|
227
227
|
console.log('\n[STEP 5] API calls captured during session:');
|
|
228
228
|
const unique = [...new Map(apiCalls.map(c => [`${c.method} ${c.url}`, c])).values()];
|
|
229
229
|
if (unique.length === 0) {
|
|
230
|
-
console.log(' (none captured
|
|
230
|
+
console.log(' (none captured - app may use WASM-level data, not REST calls)');
|
|
231
231
|
} else {
|
|
232
232
|
unique.forEach(c => {
|
|
233
233
|
console.log(` ${c.method} ${c.url}`);
|
|
@@ -30,9 +30,9 @@ test.describe('{Feature Suite Name}', () => {
|
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test.skip(
|
|
33
|
-
'[TC-{MODULE}-{SUB}-003] {TC title} @P1
|
|
33
|
+
'[TC-{MODULE}-{SUB}-003] {TC title} @P1 - DEF-{NNN}: {description}. Reactivate when {ADO WI or DEF ID} is resolved.',
|
|
34
34
|
async ({ page }) => {
|
|
35
|
-
// Write test as if bug is fixed
|
|
35
|
+
// Write test as if bug is fixed - documents expected behavior
|
|
36
36
|
}
|
|
37
37
|
);
|
|
38
38
|
|
|
@@ -41,7 +41,7 @@ test.describe('{Feature Suite Name}', () => {
|
|
|
41
41
|
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
## Pattern 1: EXEC_IDX
|
|
44
|
+
## Pattern 1: EXEC_IDX - Unique Test Data
|
|
45
45
|
|
|
46
46
|
```typescript
|
|
47
47
|
const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
|
|
@@ -70,7 +70,7 @@ export default async function globalSetup() {
|
|
|
70
70
|
|
|
71
71
|
await page.goto(process.env.QA_BASE_URL + process.env.QA_LOGIN_PATH);
|
|
72
72
|
await page.fill(process.env.QA_LOGIN_EMAIL_SELECTOR, process.env.QA_USER_EMAIL);
|
|
73
|
-
// Use evaluate() for password
|
|
73
|
+
// Use evaluate() for password - excluded from traces
|
|
74
74
|
await page.evaluate(
|
|
75
75
|
([sel, pwd]) => { (document.querySelector(sel) as HTMLInputElement).value = pwd; },
|
|
76
76
|
[process.env.QA_LOGIN_PASSWORD_SELECTOR, process.env.QA_USER_PASSWORD]
|
|
@@ -83,23 +83,23 @@ export default async function globalSetup() {
|
|
|
83
83
|
}
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
For multiple roles: run login sequence **sequentially** (not in parallel
|
|
86
|
+
For multiple roles: run login sequence **sequentially** (not in parallel - apps often reject concurrent sessions).
|
|
87
87
|
|
|
88
88
|
---
|
|
89
89
|
|
|
90
90
|
## Pattern 3: Fast-Fail for Status Checks
|
|
91
91
|
|
|
92
92
|
```typescript
|
|
93
|
-
// BAD
|
|
93
|
+
// BAD - hangs silently for full test timeout
|
|
94
94
|
const status = await page.locator('.status-badge').textContent();
|
|
95
95
|
|
|
96
|
-
// GOOD
|
|
96
|
+
// GOOD - fails fast if element not available
|
|
97
97
|
const status = await page.locator('.status-badge').textContent({ timeout: 3_000 });
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
---
|
|
101
101
|
|
|
102
|
-
## Pattern 4: Email Validation
|
|
102
|
+
## Pattern 4: Email Validation - 3-Layer Strategy
|
|
103
103
|
|
|
104
104
|
```typescript
|
|
105
105
|
// Layer 1: HTTP route interception
|
|
@@ -168,7 +168,7 @@ await page.evaluate(
|
|
|
168
168
|
## Pattern 8: afterAll Cleanup for Data-Mutating Tests
|
|
169
169
|
|
|
170
170
|
When a test assigns, creates, or modifies persistent data (e.g., assigning a role, linking a record),
|
|
171
|
-
always implement `afterAll` cleanup
|
|
171
|
+
always implement `afterAll` cleanup - otherwise the second run finds a different state and fails.
|
|
172
172
|
|
|
173
173
|
```typescript
|
|
174
174
|
afterAll(async () => {
|
|
@@ -184,11 +184,11 @@ afterAll(async () => {
|
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
Rule: if beforeAll sets up a fixture by reading state from the API, afterAll must restore that same state.
|
|
187
|
-
Design cleanup from the start
|
|
187
|
+
Design cleanup from the start - retrofitting it costs as many runs as the test itself.
|
|
188
188
|
|
|
189
189
|
---
|
|
190
190
|
|
|
191
|
-
### Pattern 9: Debug Screenshots
|
|
191
|
+
### Pattern 9: Debug Screenshots - Path-bound Artifacts
|
|
192
192
|
|
|
193
193
|
Screenshots MUST always be saved to `agentSettings.screenshotPath` defined in `qa/qa-framework.config.json`. Never save to the workspace root or any ad-hoc path.
|
|
194
194
|
|
|
@@ -196,23 +196,23 @@ Screenshots MUST always be saved to `agentSettings.screenshotPath` defined in `q
|
|
|
196
196
|
// Read screenshotPath from config or use default
|
|
197
197
|
const DIAG_DIR = 'qa/07-automation/e2e/diagnosis';
|
|
198
198
|
|
|
199
|
-
// On test failure
|
|
199
|
+
// On test failure - capture state for diagnosis:
|
|
200
200
|
await page.screenshot({ path: `${DIAG_DIR}/${SUBMODULE}-${tcId}-fail-${Date.now()}.png` });
|
|
201
201
|
|
|
202
202
|
// In beforeAll for warm-up verification:
|
|
203
203
|
await page.screenshot({ path: `${DIAG_DIR}/{submodule}-warmup.png` });
|
|
204
204
|
|
|
205
|
-
// In inspection scripts (_inspect-*.js)
|
|
205
|
+
// In inspection scripts (_inspect-*.js) - always use the same dir:
|
|
206
206
|
await page.screenshot({ path: `${DIAG_DIR}/_inspect-${SUBMODULE}.png`, fullPage: true });
|
|
207
207
|
```
|
|
208
208
|
|
|
209
209
|
Naming convention: {submodule}-{context}-{optional-timestamp}.png
|
|
210
210
|
When to capture:
|
|
211
211
|
|
|
212
|
-
* End of beforeAll warmup
|
|
213
|
-
* Inside catch blocks in beforeAll/beforeEach
|
|
214
|
-
* Inside inspection scripts
|
|
215
|
-
* Never inside individual test() bodies
|
|
212
|
+
* End of beforeAll warmup - confirms the app state before tests run
|
|
213
|
+
* Inside catch blocks in beforeAll/beforeEach - documents the failure condition
|
|
214
|
+
* Inside inspection scripts - captures the rendered UI state at each navigation step
|
|
215
|
+
* Never inside individual test() bodies - Playwright's built-in trace (--trace on) already captures this
|
|
216
216
|
* Enforcement: The diagnosis/ folder is gitignored. Screenshots are local-only artifacts, never committed to the repo.
|
|
217
217
|
|
|
218
218
|
---
|
|
@@ -222,11 +222,11 @@ When to capture:
|
|
|
222
222
|
Create `COVERAGE-MAPPING.md` in the test directory after automation is complete:
|
|
223
223
|
|
|
224
224
|
```markdown
|
|
225
|
-
# Coverage Mapping
|
|
225
|
+
# Coverage Mapping - {Module}
|
|
226
226
|
|
|
227
227
|
| TC ID | Title | Spec file | Playwright spec | Status |
|
|
228
228
|
|-------|-------|-----------|----------------|--------|
|
|
229
229
|
| TC-MOD-SUB-001 | {title} | 05-test-scenarios.md | tests/{module}/{file}.spec.ts | ✅ Automated |
|
|
230
|
-
| TC-MOD-SUB-002 | {title} | 05-test-scenarios.md |
|
|
231
|
-
| TC-MOD-SUB-003 | {title} | 05-test-scenarios.md |
|
|
230
|
+
| TC-MOD-SUB-002 | {title} | 05-test-scenarios.md | - | ⛔ BLOCKED-PERMISSIONS |
|
|
231
|
+
| TC-MOD-SUB-003 | {title} | 05-test-scenarios.md | - | 🔲 PENDING-CODE |
|
|
232
232
|
```
|