@keber/qa-framework 1.10.0 → 1.12.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.
Files changed (113) hide show
  1. package/CHANGELOG.md +63 -18
  2. package/README.md +2 -2
  3. package/docs/architecture.md +30 -26
  4. package/docs/decisions/lane-heartbeat-caller.md +86 -0
  5. package/docs/final-report.md +23 -23
  6. package/docs/folder-structure-guide.md +106 -80
  7. package/docs/installation.md +35 -7
  8. package/docs/skills-architecture.md +23 -23
  9. package/docs/spec-driven-philosophy.md +9 -9
  10. package/docs/usage-with-agent.md +83 -9
  11. package/docs/visuals/diag-01-ejecutivo-1.png +0 -0
  12. package/docs/visuals/diag-02-tactico-1.png +0 -0
  13. package/docs/visuals/diag-03-tecnico-1.png +0 -0
  14. package/docs/visuals/info-01-ejecutivo-1.png +0 -0
  15. package/docs/visuals/info-02-tactico-1.png +0 -0
  16. package/docs/visuals/info-03-tecnico-1.png +0 -0
  17. package/docs/visuals/pres-01-ejecutivo-1.png +0 -0
  18. package/docs/visuals/pres-02-tactico-1.png +0 -0
  19. package/docs/visuals/pres-03-tecnico-1.png +0 -0
  20. package/docs/visuals/qa-01-problema-1.png +0 -0
  21. package/docs/visuals/qa-02-que-es-1.png +0 -0
  22. package/docs/visuals/qa-03-pipeline-1.png +0 -0
  23. package/docs/visuals/qa-04-6-archivos-1.png +0 -0
  24. package/docs/visuals/qa-05-humano-1.png +0 -0
  25. package/docs/visuals/qa-06-agente-1.png +0 -0
  26. package/docs/visuals/qa-07-skills-arch-1.png +0 -0
  27. package/docs/visuals/qa-08-traceability-1.png +0 -0
  28. package/docs/visuals/qa-en-01-problem-1.png +0 -0
  29. package/docs/visuals/qa-en-02-what-is-1.png +0 -0
  30. package/docs/visuals/qa-en-03-pipeline-1.png +0 -0
  31. package/docs/visuals/qa-en-04-6files-1.png +0 -0
  32. package/docs/visuals/qa-en-05-human-1.png +0 -0
  33. package/docs/visuals/qa-en-06-agent-1.png +0 -0
  34. package/docs/visuals/qa-en-07-skills-arch-1.png +0 -0
  35. package/docs/visuals/qa-en-08-traceability-1.png +0 -0
  36. package/examples/module-example/suppliers/00-inventory.md +1 -1
  37. package/examples/module-example/suppliers/suppliers-create.spec.ts +8 -8
  38. package/integrations/ado-powershell/README.md +1 -1
  39. package/integrations/ado-powershell/pipelines/azure-pipeline-qa.yml +92 -25
  40. package/integrations/ado-powershell/scripts/sync-ado-titles.ps1 +2 -2
  41. package/integrations/playwright/README.md +128 -4
  42. package/package.json +9 -6
  43. package/qa-framework.config.json +24 -3
  44. package/scripts/check-forbidden-chars.js +187 -0
  45. package/scripts/check-spanish-accents.js +159 -0
  46. package/scripts/cli.js +1 -1
  47. package/scripts/generate.js +2 -2
  48. package/scripts/init.js +108 -45
  49. package/scripts/lib/claude-agents.js +78 -0
  50. package/scripts/lib/claude-commands.js +56 -0
  51. package/scripts/sync-version.js +36 -0
  52. package/scripts/upgrade.js +461 -30
  53. package/scripts/validate.js +17 -17
  54. package/skills/qa-ado-integration/SKILL.md +19 -19
  55. package/skills/qa-ado-integration/references/scripts-and-config.md +6 -6
  56. package/skills/qa-automation/SKILL.md +49 -27
  57. package/skills/qa-automation/references/config-checklist.md +4 -4
  58. package/skills/qa-automation/references/dom-inspection-template.js +7 -7
  59. package/skills/qa-automation/references/patterns.md +20 -20
  60. package/skills/qa-automation/references/pom-template.md +161 -0
  61. package/skills/qa-maintenance/SKILL.md +11 -11
  62. package/skills/qa-maintenance/references/update-rules.md +8 -8
  63. package/skills/qa-module-analysis/SKILL.md +20 -19
  64. package/skills/qa-module-analysis/references/exploration-checklist.md +4 -4
  65. package/skills/qa-module-analysis/references/output-verification.md +69 -0
  66. package/skills/qa-module-analysis/references/spec-file-formats.md +14 -14
  67. package/skills/qa-spec-generation/SKILL.md +13 -7
  68. package/skills/qa-test-cases/SKILL.md +11 -81
  69. package/skills/qa-test-cases/references/test-case-template.md +5 -5
  70. package/skills/qa-test-plan/SKILL.md +22 -86
  71. package/skills/qa-test-plan/references/plan-de-pruebas-template.md +24 -24
  72. package/skills/qa-test-stabilization/SKILL.md +59 -30
  73. package/skills/qa-test-stabilization/references/classification-protocol.md +35 -35
  74. package/templates/agent-next-steps.md +10 -10
  75. package/templates/agents/qa-analisis.md +142 -0
  76. package/templates/agents/qa-asesoria.md +48 -0
  77. package/templates/agents/qa-informe-resultados.md +234 -0
  78. package/templates/agents/qa-plan.md +131 -0
  79. package/templates/automation-scaffold/.env.example +52 -3
  80. package/templates/automation-scaffold/fixtures/auth.ts +27 -5
  81. package/templates/automation-scaffold/fixtures/base.ts +130 -0
  82. package/templates/automation-scaffold/fixtures/test-helpers.ts +1 -1
  83. package/templates/automation-scaffold/global-setup.ts +196 -37
  84. package/templates/automation-scaffold/playwright.config.ts +74 -10
  85. package/templates/automation-scaffold/scripts/global-setup-guards.js +184 -0
  86. package/templates/automation-scaffold/scripts/lane-config.js +269 -0
  87. package/templates/automation-scaffold/scripts/lane-lock.js +589 -0
  88. package/templates/defect-report.md +18 -4
  89. package/templates/execution-report.md +9 -9
  90. package/templates/integration-scaffold/.env.example +40 -0
  91. package/templates/integration-scaffold/README.md +77 -0
  92. package/templates/integration-scaffold/global-setup.ts +119 -0
  93. package/templates/integration-scaffold/package.json +15 -0
  94. package/templates/integration-scaffold/playwright.config.ts +92 -0
  95. package/templates/integration-scaffold/tests/example.spec.ts +43 -0
  96. package/templates/memory/ci-pipeline-findings.md +36 -0
  97. package/templates/memory/data-volatility-strategies.md +70 -0
  98. package/templates/memory/e2e-stabilization-patterns.md +54 -0
  99. package/templates/qa-framework.instructions.md +16 -7
  100. package/templates/qa-framework.rules.md +53 -0
  101. package/templates/qa-readme.md +26 -5
  102. package/templates/session-summary.md +2 -2
  103. package/templates/specification/00-inventory.md +3 -3
  104. package/templates/specification/01-business-rules.md +6 -6
  105. package/templates/specification/02-workflows.md +1 -1
  106. package/templates/specification/03-roles-permissions.md +1 -1
  107. package/templates/specification/04-test-data.md +8 -8
  108. package/templates/specification/05-test-scenarios.md +5 -5
  109. package/templates/test-case.md +3 -3
  110. package/templates/test-data-guidelines.md +7 -7
  111. package/templates/test-plan-sprint.md +13 -13
  112. package/templates/test-plan.md +3 -3
  113. package/skills/qa-test-plan/references/priority-and-feasibility.md +0 -159
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * scripts/validate.js — Validate qa/ folder structure and conventions
3
+ * scripts/validate.js - Validate qa/ folder structure and conventions
4
4
  *
5
5
  * Usage:
6
6
  * qa-framework validate
@@ -9,7 +9,7 @@
9
9
  *
10
10
  * Checks:
11
11
  * 1. Required top-level folders exist
12
- * 2. All submodule folders contain the 6 required spec files
12
+ * 2. All submodule folders under 01-specifications/ contain the 6 required spec files
13
13
  * 3. No plaintext credentials in spec files (basic scan)
14
14
  * 4. Test case naming convention (TC-NNN pattern in spec files)
15
15
  * 5. [--strict] Automation spec files exist for every submodule
@@ -47,7 +47,7 @@ const warnings = [];
47
47
  // -----------------------------------------------------------------------
48
48
  const requiredFolders = [
49
49
  '00-standards',
50
- '05-test-plans',
50
+ '05-test-execution',
51
51
  '06-defects',
52
52
  '07-automation',
53
53
  ];
@@ -70,18 +70,18 @@ const SPEC_FILES = [
70
70
  '05-test-scenarios.md',
71
71
  ];
72
72
 
73
- const SKIP_DIRS = new Set([
74
- '00-guides', '00-standards', '05-test-plans',
75
- '06-defects', '07-automation', '08-azure-integration',
76
- ]);
73
+ // Specs live at qa/01-specifications/{module}/{submodule}/. Rooting the scan
74
+ // here keeps it at the right depth and means sibling folders such as
75
+ // 02-test-plans/ or memory/ are never mistaken for modules in the first place.
76
+ const specsRoot = path.join(qaRoot, '01-specifications');
77
77
 
78
- if (fs.existsSync(qaRoot)) {
79
- const topDirs = fs.readdirSync(qaRoot).filter(d => {
80
- return fs.statSync(path.join(qaRoot, d)).isDirectory() && !SKIP_DIRS.has(d);
81
- });
78
+ if (fs.existsSync(specsRoot)) {
79
+ const moduleDirs = fs.readdirSync(specsRoot).filter(d =>
80
+ fs.statSync(path.join(specsRoot, d)).isDirectory()
81
+ );
82
82
 
83
- for (const moduleDir of topDirs) {
84
- const modulePath = path.join(qaRoot, moduleDir);
83
+ for (const moduleDir of moduleDirs) {
84
+ const modulePath = path.join(specsRoot, moduleDir);
85
85
  const subDirs = fs.readdirSync(modulePath).filter(d =>
86
86
  fs.statSync(path.join(modulePath, d)).isDirectory()
87
87
  );
@@ -90,15 +90,15 @@ if (fs.existsSync(qaRoot)) {
90
90
  const subPath = path.join(modulePath, subDir);
91
91
  for (const specFile of SPEC_FILES) {
92
92
  if (!fs.existsSync(path.join(subPath, specFile))) {
93
- errors.push(`Missing spec file: qa/${moduleDir}/${subDir}/${specFile}`);
93
+ errors.push(`Missing spec file: qa/01-specifications/${moduleDir}/${subDir}/${specFile}`);
94
94
  }
95
95
  }
96
96
 
97
97
  // Strict: automation spec must exist
98
98
  if (strict) {
99
- const specTs = path.join(qaRoot, '07-automation', 'e2e', moduleDir, `${subDir}.spec.ts`);
99
+ const specTs = path.join(qaRoot, '07-automation', 'e2e', 'tests', moduleDir, `${subDir}.spec.ts`);
100
100
  if (!fs.existsSync(specTs)) {
101
- warnings.push(`[STRICT] No automation spec found: qa/07-automation/e2e/${moduleDir}/${subDir}.spec.ts`);
101
+ warnings.push(`[STRICT] No automation spec found: qa/07-automation/e2e/tests/${moduleDir}/${subDir}.spec.ts`);
102
102
  }
103
103
  }
104
104
  }
@@ -147,7 +147,7 @@ for (const f of specFiles) {
147
147
  // -----------------------------------------------------------------------
148
148
  console.log('');
149
149
  if (errors.length === 0 && warnings.length === 0) {
150
- console.log('✅ Validation passed — no issues found.');
150
+ console.log('✅ Validation passed - no issues found.');
151
151
  process.exit(0);
152
152
  }
153
153
 
@@ -12,31 +12,31 @@ description: >
12
12
 
13
13
  # QA Skill: ADO Integration (Optional Stage)
14
14
 
15
- **Stage**: Optional — ADO Integration (no pipeline order dependency)
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 — Stage 4 and 5 are not required
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 — run Stage 4 first to expand them.
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` — 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
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 — do not use it as input for ADO scripts.
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 — Verify ADO config
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 — Create or verify Test Plan
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` — organization URL (e.g., `https://dev.azure.com/myorg`)
59
- - `$env:ADO_PROJECT` — project name
60
- - `$env:ADO_PAT` — PAT token
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 — Sync test cases from Plan de Pruebas
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 → each becomes one ADO step)
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 — Configure Playwright ADO reporter
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 — no hardcoded IDs
84
+ - All values must come from environment variables - no hardcoded IDs
85
85
 
86
- ### Step 5 — Run sync and validate
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 — Update registry
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` — ADO IDs injected
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` — record in `module-registry.json`.
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} — {N} submodules"
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`** — prevents publishing from local developer runs.
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 — always from env var or CI variable group
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 — no project-wide access
201
- 5. PAT minimum scopes: `Work Items (Read, Write)`, `Test Management (Read, Write)` — never use full-access PATs
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 — Automation
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 — Maintenance (`qa-maintenance`) or Stage 5b — Stabilization (`qa-test-stabilization`) if tests fail
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}/` — 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
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 — Pre-inspection (MANDATORY before writing any test code)
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` — copy, set the 4 constants at the top, run.
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` → `qa/07-automation/e2e/_inspect-{submodule}.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` — 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`
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 — Scan for blockers
62
+ ### Step 1 - Scan for blockers
63
63
 
64
64
  Before writing a line of code:
65
- - Search all spec files for `PENDING-CODE` — stop and flag if found
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 — Decide POM vs inline locators
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 — Scaffold spec file
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 — Implement tests in priority order
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 — improves traceability
98
- 4. Assert observable outcomes — avoid asserting internal implementation details
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 — Apply stability rules
100
+ ### Step 4 - Apply stability rules
101
101
 
102
- - Never use `waitForTimeout` — use `waitForSelector`, `waitForResponse`, or role-based locators
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` — never leave residue
105
+ - All test data cleared in `afterAll` - never leave residue
106
106
 
107
- ### Step 4b — Assertion polarity check (MANDATORY before committing any test)
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 — do not adapt the assertion to match the app.
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 — Module Completion Checklist
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 — REQUIRED, prevents silent hangs
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 — add only when integration is enabled:
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 — **not optional**; without it, `textContent()` and similar calls silently hang
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` — no hardcoded values
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 — {SUBMODULE_DISPLAY_NAME}
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 — edit these 4 constants, leave the rest ───────────────────
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 — runs passively throughout the entire session ──
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 — uses ARIA roles (framework-agnostic)
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 — submit empty form to capture required-field messages
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 — inspect a specific tab:
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 — app may use WASM-level data, not REST calls)');
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 — DEF-{NNN}: {description}. Reactivate when {ADO WI or DEF ID} is resolved.',
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 — documents expected behavior
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 — Unique Test Data
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 — excluded from traces
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 — apps often reject concurrent sessions).
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 — hangs silently for full test timeout
93
+ // BAD - hangs silently for full test timeout
94
94
  const status = await page.locator('.status-badge').textContent();
95
95
 
96
- // GOOD — fails fast if element not available
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 — 3-Layer Strategy
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 — otherwise the second run finds a different state and fails.
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 — retrofitting it costs as many runs as the test itself.
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 — Path-bound Artifacts
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 — capture state for diagnosis:
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) — always use the same dir:
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 — 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
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 — {Module}
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 | — | ⛔ BLOCKED-PERMISSIONS |
231
- | TC-MOD-SUB-003 | {title} | 05-test-scenarios.md | — | 🔲 PENDING-CODE |
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
  ```