@keber/qa-framework 1.3.0-0 → 1.4.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keber/qa-framework",
3
- "version": "1.3.0-0",
3
+ "version": "1.4.0",
4
4
  "description": "Reusable spec-driven QA framework for IDE-agent-assisted automated testing. Installable as an npm package. Provides structure, templates, agent instructions, and optional integrations for Playwright and Azure DevOps.",
5
5
  "keywords": [
6
6
  "qa",
@@ -25,6 +25,7 @@
25
25
  },
26
26
  "files": [
27
27
  "agent-instructions/",
28
+ "skills/",
28
29
  "templates/",
29
30
  "docs/",
30
31
  "examples/",
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: qa-ado-integration
3
+ description: >
4
+ Optional stage of the QA pipeline. Syncs test plans, test cases, and
5
+ automation results with Azure DevOps (ADO) Test Plans. Injects ADO IDs
6
+ back into local spec files and configures the Playwright ADO reporter.
7
+ Use when asked to sync with Azure DevOps, push test cases to ADO, create
8
+ a test plan in ADO, configure ADO reporting, inject ADO IDs, or link
9
+ Playwright results to ADO.
10
+ Requires ADO enabled in qa-framework.config.json with valid PAT in env vars.
11
+ ---
12
+
13
+ # QA Skill: ADO Integration (Optional Stage)
14
+
15
+ **Stage**: Optional — ADO Integration (no pipeline order dependency)
16
+ **Prerequisite**: ADO configuration in `qa/qa-framework.config.json`; valid `ADO_PAT` env var
17
+ **Output**: ADO Test Plan populated + `qa/08-azure-integration/module-registry.json` updated
18
+ **Use any time** after Stage 4 (Test Cases) or Stage 5 (Automation) are ready to sync
19
+
20
+ > **Credential rule**: NEVER hardcode PAT, username, or organization URL in any file. Always read from env vars or `<PLACEHOLDER>` in documentation.
21
+
22
+ ---
23
+
24
+ ## Inputs Required
25
+
26
+ 1. `qa/qa-framework.config.json` — ADO org URL, project name, test plan ID (or "create new")
27
+ 2. `qa/03-test-cases/automated/` — TC files with IDs to sync
28
+ 3. `ADO_PAT` environment variable — personal access token with Test Plans read/write
29
+ 4. Optionally: `qa/08-azure-integration/module-registry.json` for existing ID mapping
30
+
31
+ ---
32
+
33
+ ## Process
34
+
35
+ ### Step 1 — Verify ADO config
36
+
37
+ Check `qa/qa-framework.config.json` for:
38
+ ```json
39
+ "ado": {
40
+ "org": "<ADO_ORG_URL>",
41
+ "project": "<PROJECT_NAME>",
42
+ "planId": <PLAN_ID_OR_NULL>
43
+ }
44
+ ```
45
+ If `planId` is null, a new plan will be created in Step 2.
46
+
47
+ ### Step 2 — Create or verify Test Plan
48
+
49
+ Use the PowerShell script: `integrations/ado-powershell/scripts/create-testplan-from-mapping.ps1`
50
+
51
+ See `references/scripts-and-config.md` for usage, parameters, and required env vars.
52
+
53
+ Required env vars:
54
+ - `$env:ADO_ORG` — organization URL (e.g., `https://dev.azure.com/myorg`)
55
+ - `$env:ADO_PROJECT` — project name
56
+ - `$env:ADO_PAT` — PAT token
57
+
58
+ ### Step 3 — Sync test cases
59
+
60
+ Use `inject-ado-ids.ps1` to push TCs to ADO and write the returned ADO test case IDs back into local TC files.
61
+
62
+ After sync, each TC file must have `adoId: <NNN>` in its YAML frontmatter block.
63
+
64
+ ### Step 4 — Configure Playwright ADO reporter
65
+
66
+ See `references/scripts-and-config.md` for the reporter config block to add to `qa/07-automation/playwright.config.ts`.
67
+
68
+ Required fields:
69
+ - `orgUrl`, `projectName`, `planId`, `runName`
70
+ - All values must come from environment variables — no hardcoded IDs
71
+
72
+ ### Step 5 — Run sync and validate
73
+
74
+ Run `sync-ado-titles.ps1` after automation runs to update ADO test outcomes from Playwright report JSON.
75
+
76
+ ### Step 6 — Update registry
77
+
78
+ Update `qa/08-azure-integration/module-registry.json` with:
79
+ - Module name
80
+ - ADO Plan ID
81
+ - ADO Suite IDs per submodule
82
+ - Sync date
83
+
84
+ ---
85
+
86
+ ## Troubleshooting Quick Reference
87
+
88
+ | Symptom | Likely cause | Fix |
89
+ |---|---|---|
90
+ | 401 Unauthorized | Expired or wrong PAT | Regenerate PAT; check `$env:ADO_PAT` |
91
+ | Plan not found | Wrong planId in config | Verify planId or set to null to create new |
92
+ | TCs not appearing | Wrong suite parent ID | Check `module-registry.json` suite mapping |
93
+ | Reporter not posting | Missing env var at runtime | Pass vars via CI pipeline or `.env` |
94
+ | Duplicate TCs | Re-ran create script | Use `inject-ado-ids.ps1` idempotently |
95
+
96
+ ---
97
+
98
+ ## Outputs
99
+
100
+ - ADO Test Plan populated with test cases
101
+ - `qa/03-test-cases/automated/TC-*.md` — ADO IDs injected
102
+ - `qa/08-azure-integration/module-registry.json` updated
103
+ - `qa/07-automation/playwright.config.ts` updated with reporter config
@@ -0,0 +1,201 @@
1
+ # Reference: ADO Scripts and Configuration
2
+
3
+ > Loaded by `skills/qa-ado-integration/` for PowerShell scripts, reporter config, and CI pipeline.
4
+
5
+ ---
6
+
7
+ ## PowerShell Scripts Usage
8
+
9
+ ### create-testplan-from-mapping.ps1
10
+
11
+ Creates a new ADO Test Plan with suites and test cases from the mapping JSON file.
12
+
13
+ ```powershell
14
+ .\integrations\ado-powershell\scripts\create-testplan-from-mapping.ps1 `
15
+ -Organization $env:ADO_ORG `
16
+ -Project $env:ADO_PROJECT `
17
+ -Token $env:ADO_PAT `
18
+ -MappingFile .\qa\08-azure-integration\ado-ids-mapping-{project}.json
19
+ ```
20
+
21
+ Output: `TestPlanId` and `SuiteIds` — record in `module-registry.json`.
22
+
23
+ ---
24
+
25
+ ### inject-ado-ids.ps1
26
+
27
+ Injects ADO Work Item IDs into Playwright test titles and adds ADO annotations.
28
+
29
+ ```powershell
30
+ # Dry run first
31
+ .\integrations\ado-powershell\scripts\inject-ado-ids.ps1 `
32
+ -MappingFile .\qa\08-azure-integration\ado-ids-mapping-{project}.json `
33
+ -TestDir .\qa\07-automation\e2e\tests `
34
+ -DryRun
35
+
36
+ # Apply
37
+ .\integrations\ado-powershell\scripts\inject-ado-ids.ps1 `
38
+ -MappingFile .\qa\08-azure-integration\ado-ids-mapping-{project}.json `
39
+ -TestDir .\qa\07-automation\e2e\tests
40
+ ```
41
+
42
+ Transforms test titles:
43
+ ```
44
+ # Before
45
+ '[TC-OPER-CAT-001] Access catalog list @P0'
46
+
47
+ # After
48
+ '[22957] Access catalog list @P0'
49
+ ```
50
+
51
+ Adds annotation:
52
+ ```typescript
53
+ test.info().annotations.push({ type: 'TestCase', description: '22957' });
54
+ ```
55
+
56
+ ---
57
+
58
+ ### sync-ado-titles.ps1
59
+
60
+ Syncs ADO TC titles with local spec file titles (detects drift):
61
+
62
+ ```powershell
63
+ .\integrations\ado-powershell\scripts\sync-ado-titles.ps1 `
64
+ -Organization $env:ADO_ORG `
65
+ -Project $env:ADO_PROJECT `
66
+ -Token $env:ADO_PAT `
67
+ -MappingFile .\qa\08-azure-integration\ado-ids-mapping-{project}.json `
68
+ -DryRun
69
+ ```
70
+
71
+ Apply with `-DryRun:$false`.
72
+
73
+ ---
74
+
75
+ ## ADO IDs Mapping File
76
+
77
+ ```json
78
+ {
79
+ "planId": 22304,
80
+ "module": "operacion",
81
+ "specsPath": "qa/07-automation/e2e/tests/operacion",
82
+ "suites": [
83
+ {
84
+ "suiteId": 22956,
85
+ "suiteName": "Suite 1.1 - {Submodule Name}",
86
+ "testCases": [
87
+ { "id": 22957, "title": "Access catalog list @P0", "tags": ["automatable", "playwright"] },
88
+ { "id": 22958, "title": "Create labor type @P1", "tags": ["automatable", "playwright"] }
89
+ ]
90
+ }
91
+ ]
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Module Registry
98
+
99
+ ```json
100
+ {
101
+ "modules": [
102
+ {
103
+ "name": "{module-kebab}",
104
+ "specsPath": "qa/07-automation/e2e/tests/{module-kebab}",
105
+ "planId": 0,
106
+ "suiteId": 0,
107
+ "description": "{Module display name} — {N} submodules"
108
+ }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## playwright-azure-reporter Config
116
+
117
+ Add to `qa/07-automation/playwright.config.ts` reporter array:
118
+
119
+ ```typescript
120
+ ['@alex_neo/playwright-azure-reporter', {
121
+ orgUrl: `https://dev.azure.com/${process.env.ADO_ORG}`,
122
+ token: process.env.ADO_PAT,
123
+ planId: Number(process.env.ADO_PLAN_ID),
124
+ projectName: process.env.ADO_PROJECT,
125
+ isDisabled: !process.env.CI, // only publish in CI
126
+ publishTestResultsMode: 'testRun',
127
+ testRunTitle: `QA Run - ${new Date().toISOString()}`,
128
+ uploadAttachments: true,
129
+ attachmentsType: ['screenshot', 'video', 'trace'],
130
+ }]
131
+ ```
132
+
133
+ **`isDisabled: !process.env.CI`** — prevents publishing from local developer runs.
134
+
135
+ ---
136
+
137
+ ## CI Pipeline Template
138
+
139
+ ```yaml
140
+ trigger:
141
+ branches:
142
+ include:
143
+ - {{CI_TRIGGER_BRANCH}}
144
+
145
+ pool:
146
+ vmImage: 'ubuntu-latest'
147
+
148
+ variables:
149
+ - group: qa-secrets # Must contain: QA_USER_EMAIL, QA_USER_PASSWORD, QA_BASE_URL, ADO_PAT, ADO_PLAN_ID
150
+
151
+ steps:
152
+ - checkout: self
153
+ fetchDepth: 2
154
+
155
+ - task: NodeTool@0
156
+ inputs:
157
+ versionSpec: '20.x'
158
+ displayName: 'Install Node.js 20'
159
+
160
+ - script: |
161
+ cd qa/07-automation/e2e
162
+ npm install
163
+ npx playwright install chromium --with-deps
164
+ displayName: 'Install Playwright'
165
+
166
+ - script: |
167
+ cd qa/07-automation/e2e
168
+ npx playwright test
169
+ displayName: 'Run Playwright tests'
170
+ env:
171
+ QA_BASE_URL: $(QA_BASE_URL)
172
+ QA_USER_EMAIL: $(QA_USER_EMAIL)
173
+ QA_USER_PASSWORD: $(QA_USER_PASSWORD)
174
+ ADO_PAT: $(ADO_PAT)
175
+ ADO_PLAN_ID: $(ADO_PLAN_ID)
176
+ CI: 'true'
177
+
178
+ - task: PublishTestResults@2
179
+ inputs:
180
+ testResultsFormat: 'JUnit'
181
+ testResultsFiles: '**/test-results/*.xml'
182
+ displayName: 'Publish JUnit results'
183
+ condition: always()
184
+
185
+ - task: PublishPipelineArtifact@1
186
+ inputs:
187
+ targetPath: 'qa/07-automation/e2e/playwright-report'
188
+ artifact: 'playwright-html-report'
189
+ displayName: 'Publish HTML report'
190
+ condition: always()
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Credential Security Rules
196
+
197
+ 1. `ADO_PAT` is **never** committed to any file — always from env var or CI variable group
198
+ 2. `ADO_PAT` is **never** logged, printed, or written to any markdown file
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
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: qa-automation
3
+ description: >
4
+ Stage 5 of the QA pipeline. Implements Playwright test automation from
5
+ approved specifications. Generates spec files, page objects, fixtures, and
6
+ configures the test runner.
7
+ Use when asked to automate tests, write Playwright specs, implement automation,
8
+ implement test scripts, code the e2e suite, or generate .spec.ts files.
9
+ Requires completed specifications with no PENDING-CODE sections (Stage 2 complete,
10
+ Stage 4 recommended).
11
+ ---
12
+
13
+ # QA Skill: Automation Generation (Stage 5 of 6)
14
+
15
+ **Stage**: 5 — Automation
16
+ **Prerequisite**: All specs for the target submodule are complete and contain no `PENDING-CODE` sections
17
+ **Output**: `qa/07-automation/e2e/{module}/{submodule}.spec.ts` + supporting files
18
+ **Next stage**: Stage 6 — Maintenance (`qa-maintenance`) or Stage 5b — Stabilization (`qa-test-stabilization`) if tests fail
19
+
20
+ > **Pipeline rule**: Never automate a TC whose spec contains `PENDING-CODE`. Resolve spec gaps first.
21
+
22
+ ---
23
+
24
+ ## Inputs Required
25
+
26
+ 1. `qa/01-specifications/{module}/` — full spec set for target submodule
27
+ 2. `qa/07-automation/playwright.config.ts` — confirm project name maps to submodule tag
28
+ 3. `qa/07-automation/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
+
31
+ ---
32
+
33
+ ## Process
34
+
35
+ ### Step 1 — Scan for blockers
36
+
37
+ Before writing a line of code:
38
+ - Search all spec files for `PENDING-CODE` — stop and flag if found
39
+ - Confirm `playwright.config.ts` exists; scaffold it if missing using `references/config-checklist.md`
40
+ - Verify `fixtures/auth.ts` has the roles required by this submodule
41
+
42
+ ### Step 2 — Scaffold spec file
43
+
44
+ Full spec file template and 7 implementation patterns: `references/patterns.md`
45
+
46
+ Required scaffold elements:
47
+ - `import { test, expect } from '@playwright/test'`
48
+ - `const EXEC_IDX = process.env.EXEC_IDX ?? '0'` (prevents DB conflicts in parallel runs)
49
+ - `test.describe('{Submodule Name}', () => { ... })`
50
+ - Use fixture-based auth (never hardcode credentials)
51
+
52
+ ### Step 3 — Implement tests in priority order
53
+
54
+ Implement P0 TCs first, then P1. Within each priority, follow scenario order from `05-test-scenarios.md`.
55
+
56
+ For each TC:
57
+ 1. Map TC preconditions to `beforeAll`/`beforeEach` setup
58
+ 2. Write navigation to the starting URL (use relative paths, not hardcoded base URL)
59
+ 3. Use `test.step()` to group logical sub-actions — improves traceability
60
+ 4. Assert observable outcomes — avoid asserting internal implementation details
61
+
62
+ ### Step 4 — Apply stability rules
63
+
64
+ - Never use `waitForTimeout` — use `waitForSelector`, `waitForResponse`, or role-based locators
65
+ - Prefer `getByRole`, `getByLabel`, `getByTestId` over CSS selectors
66
+ - Locators attached to dynamic data must use `EXEC_IDX` suffix
67
+ - All test data cleared in `afterAll` — never leave residue
68
+
69
+ ### Step 5 — Module Completion Checklist
70
+
71
+ Before marking the submodule as ✅ Automation Complete:
72
+ - [ ] All P0 TCs passing in CI
73
+ - [ ] All P1 TCs passing or explicitly deferred (with reason in spec)
74
+ - [ ] No `test.skip` without a linked issue or `PENDING-CODE` tag
75
+ - [ ] `playwright.config.ts` project includes submodule tag
76
+ - [ ] `qa/README.md` automation status updated
77
+ - [ ] AGENT-NEXT-STEPS.md active sprint updated (remove completed items)
78
+
79
+ ---
80
+
81
+ ## Key Patterns (reference names for Layer 3)
82
+
83
+ | Pattern | When to use |
84
+ |---|---|
85
+ | `EXEC_IDX` | Any TC that creates persistent data |
86
+ | `auth-fixture` | All authenticated TCs |
87
+ | `fast-fail` | P0 TCs — skip P1+ if P0 fails |
88
+ | `email-intercept` | Email verification flows |
89
+ | `skip-conditional` | Scenarios blocked by PENDING-CODE |
90
+ | `beforeAll-setup` | Shared precondition across TC group |
91
+ | `password-env` | Any credential usage |
92
+
93
+ See `references/patterns.md` for full TypeScript implementations.
94
+
95
+ ---
96
+
97
+ ## Outputs
98
+
99
+ - `qa/07-automation/e2e/{module}/{submodule}.spec.ts`
100
+ - `qa/07-automation/playwright.config.ts` (updated or confirmed)
101
+ - `qa/README.md` automation status updated
@@ -0,0 +1,79 @@
1
+ # Reference: Playwright Config Checklist
2
+
3
+ > Loaded by `skills/qa-automation/` when scaffolding or reviewing `playwright.config.ts`.
4
+
5
+ ---
6
+
7
+ ## Required Configuration Template
8
+
9
+ ```typescript
10
+ import { defineConfig, devices } from '@playwright/test';
11
+
12
+ export default defineConfig({
13
+ testDir: './tests',
14
+ timeout: 30_000, // Per-test timeout
15
+ actionTimeout: 10_000, // Per-action timeout — REQUIRED, prevents silent hangs
16
+ navigationTimeout: 60_000, // Per-navigation timeout (SPAs may need longer)
17
+ retries: process.env.CI ? 2 : 0,
18
+ workers: process.env.CI ? 1 : 2,
19
+
20
+ // Exclude seeds and debug scripts from normal test runs
21
+ testIgnore: ['**/seeds/**', '**/debug-*.spec.ts', '**/seed.spec.ts'],
22
+
23
+ use: {
24
+ baseURL: process.env.QA_BASE_URL,
25
+ storageState: '.auth/session.json',
26
+ locale: 'es-CL', // Adjust to app locale
27
+ screenshot: 'only-on-failure',
28
+ video: 'retain-on-failure',
29
+ trace: 'on-first-retry',
30
+ },
31
+
32
+ reporter: [
33
+ ['html', { outputFolder: 'playwright-report' }],
34
+ // ADO reporter — add only when integration is enabled:
35
+ // ['@alex_neo/playwright-azure-reporter', {
36
+ // orgUrl: process.env.ADO_ORG,
37
+ // projectName: process.env.ADO_PROJECT,
38
+ // planId: Number(process.env.ADO_PLAN_ID),
39
+ // token: process.env.ADO_PAT,
40
+ // runName: `Automated run ${new Date().toISOString()}`,
41
+ // }],
42
+ ],
43
+
44
+ projects: [
45
+ { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
46
+ // Add when cross-browser coverage required:
47
+ // { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
48
+ // { name: 'webkit', use: { ...devices['Desktop Safari'] } },
49
+ ],
50
+
51
+ globalSetup: './global-setup.ts',
52
+ outputDir: '../../05-test-execution/automated/test-results',
53
+ });
54
+ ```
55
+
56
+ ---
57
+
58
+ ## Checklist for Review
59
+
60
+ Before marking automation as complete, confirm:
61
+
62
+ - [ ] `actionTimeout` is set — **not optional**; without it, `textContent()` and similar calls silently hang
63
+ - [ ] `testIgnore` excludes seed scripts and debug files
64
+ - [ ] `baseURL` reads from `process.env.QA_BASE_URL` (never hardcoded)
65
+ - [ ] `storageState` path exists (created by `globalSetup`)
66
+ - [ ] `outputDir` points to `qa/05-test-execution/automated/test-results`
67
+ - [ ] `retries: 2` in CI for flake tolerance
68
+ - [ ] `workers: 1` in CI (or EXEC_IDX used to handle parallel conflicts)
69
+ - [ ] ADO reporter commented out unless ADO integration is active
70
+
71
+ ---
72
+
73
+ ## global-setup.ts Checklist
74
+
75
+ - [ ] Reads every credential from `process.env` — no hardcoded values
76
+ - [ ] Uses `evaluate()` for password input (trace safety)
77
+ - [ ] Saves storageState to `.auth/session.json` (or per-role paths)
78
+ - [ ] Handles login failure explicitly (does not silently save an unauthenticated state)
79
+ - [ ] Runs sequentially for multiple roles (no parallel logins)
@@ -0,0 +1,180 @@
1
+ # Reference: Automation Patterns
2
+
3
+ > Loaded by `skills/qa-automation/` when implementing Playwright tests.
4
+
5
+ ---
6
+
7
+ ## Spec File Template
8
+
9
+ ```typescript
10
+ /**
11
+ * @module {MODULE_CODE}
12
+ * @submodule {SUBMODULE_CODE}
13
+ * @spec qa/01-specifications/module-{name}/submodule-{name}/05-test-scenarios.md
14
+ * @priority P0
15
+ */
16
+
17
+ import { test, expect } from '@playwright/test';
18
+
19
+ const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
20
+
21
+ test.describe('{Feature Suite Name}', () => {
22
+
23
+ test.beforeAll(async ({ browser }) => {
24
+ // Provision data needed by all tests in this suite
25
+ // Rule: provision AT LEAST as many records as tests that consume them
26
+ });
27
+
28
+ test('[TC-{MODULE}-{SUB}-001] {TC title} @P0', async ({ page }) => {
29
+ // Arrange ... Act ... Assert
30
+ });
31
+
32
+ test.skip(
33
+ '[TC-{MODULE}-{SUB}-003] {TC title} @P1 — DEF-{NNN}: {description}. Reactivate when {ADO WI or DEF ID} is resolved.',
34
+ async ({ page }) => {
35
+ // Write test as if bug is fixed — documents expected behavior
36
+ }
37
+ );
38
+
39
+ });
40
+ ```
41
+
42
+ ---
43
+
44
+ ## Pattern 1: EXEC_IDX — Unique Test Data
45
+
46
+ ```typescript
47
+ const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
48
+
49
+ // Titles / names
50
+ const entityName = `Test-Record-${EXEC_IDX}`;
51
+
52
+ // Dates (year 2120+ avoids production data overlap; modular math always valid)
53
+ const year = 2120 + (EXEC_IDX % 10);
54
+ const month = String((EXEC_IDX % 12) + 1).padStart(2, '0');
55
+ const day = String((EXEC_IDX % 28) + 1).padStart(2, '0');
56
+ const testDate = `${year}-${month}-${day}`;
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Pattern 2: Multi-Role Auth with storageState
62
+
63
+ ```typescript
64
+ // global-setup.ts
65
+ import { chromium } from '@playwright/test';
66
+
67
+ export default async function globalSetup() {
68
+ const browser = await chromium.launch();
69
+ const page = await browser.newPage();
70
+
71
+ await page.goto(process.env.QA_BASE_URL + process.env.QA_LOGIN_PATH);
72
+ await page.fill(process.env.QA_LOGIN_EMAIL_SELECTOR, process.env.QA_USER_EMAIL);
73
+ // Use evaluate() for password — excluded from traces
74
+ await page.evaluate(
75
+ ([sel, pwd]) => { (document.querySelector(sel) as HTMLInputElement).value = pwd; },
76
+ [process.env.QA_LOGIN_PASSWORD_SELECTOR, process.env.QA_USER_PASSWORD]
77
+ );
78
+ await page.click(process.env.QA_LOGIN_SUBMIT_SELECTOR);
79
+ await page.waitForURL(url => !url.includes(process.env.QA_LOGIN_PATH));
80
+
81
+ await page.context().storageState({ path: '.auth/session.json' });
82
+ await browser.close();
83
+ }
84
+ ```
85
+
86
+ For multiple roles: run login sequence **sequentially** (not in parallel — apps often reject concurrent sessions).
87
+
88
+ ---
89
+
90
+ ## Pattern 3: Fast-Fail for Status Checks
91
+
92
+ ```typescript
93
+ // BAD — hangs silently for full test timeout
94
+ const status = await page.locator('.status-badge').textContent();
95
+
96
+ // GOOD — fails fast if element not available
97
+ const status = await page.locator('.status-badge').textContent({ timeout: 3_000 });
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Pattern 4: Email Validation — 3-Layer Strategy
103
+
104
+ ```typescript
105
+ // Layer 1: HTTP route interception
106
+ const emailRequests: string[] = [];
107
+ await page.route('**/*mail*', (route) => {
108
+ emailRequests.push(route.request().url());
109
+ route.continue();
110
+ });
111
+ // Perform the action...
112
+ expect(emailRequests.length).toBeGreaterThan(0);
113
+
114
+ // Layer 2: UI confirmation (toast / banner / badge)
115
+ await expect(page.locator('.email-sent-indicator')).toBeVisible();
116
+
117
+ // Layer 3: skip if inbox access not available
118
+ test.fixme(process.env.QA_MAILBOX_ACCESS !== 'true', 'Requires mailbox access');
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Pattern 5: Skip for Known Bugs
124
+
125
+ ```typescript
126
+ test.skip(true,
127
+ 'DEF-001: {Description}. ' +
128
+ 'Expected: {expected behavior}. ' +
129
+ 'Actual: {buggy behavior}. ' +
130
+ 'Reactivate when ADO #{WI_ID} / DEF-001 is resolved.'
131
+ );
132
+ ```
133
+
134
+ Never make a test pass around a bug. Document the expected behavior in the skip body.
135
+
136
+ ---
137
+
138
+ ## Pattern 6: beforeAll Provisioning Ratio
139
+
140
+ ```typescript
141
+ test.beforeAll(async ({ browser }) => {
142
+ const page = await browser.newPage();
143
+ // If 3 tests each consume 1 record, create at least 3
144
+ const records: string[] = [];
145
+ for (let i = 0; i < 3; i++) {
146
+ const id = await createRecord(page, `Record-${EXEC_IDX}-${i}`);
147
+ records.push(id);
148
+ }
149
+ });
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Pattern 7: Password Injection (Trace Safety)
155
+
156
+ ```typescript
157
+ // Passwords must be set via evaluate() to keep them out of Playwright traces
158
+ await page.evaluate(
159
+ ([selector, pwd]) => {
160
+ (document.querySelector(selector) as HTMLInputElement).value = pwd;
161
+ },
162
+ [process.env.QA_LOGIN_PASSWORD_SELECTOR, process.env.QA_USER_PASSWORD]
163
+ );
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Coverage Mapping Template
169
+
170
+ Create `COVERAGE-MAPPING.md` in the test directory after automation is complete:
171
+
172
+ ```markdown
173
+ # Coverage Mapping — {Module}
174
+
175
+ | TC ID | Title | Spec file | Playwright spec | Status |
176
+ |-------|-------|-----------|----------------|--------|
177
+ | TC-MOD-SUB-001 | {title} | 05-test-scenarios.md | tests/{module}/{file}.spec.ts | ✅ Automated |
178
+ | TC-MOD-SUB-002 | {title} | 05-test-scenarios.md | — | ⛔ BLOCKED-PERMISSIONS |
179
+ | TC-MOD-SUB-003 | {title} | 05-test-scenarios.md | — | 🔲 PENDING-CODE |
180
+ ```