@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.
- package/CHANGELOG.md +63 -18
- package/README.md +2 -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 +106 -80
- package/docs/installation.md +35 -7
- package/docs/skills-architecture.md +23 -23
- package/docs/spec-driven-philosophy.md +9 -9
- package/docs/usage-with-agent.md +83 -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/pipelines/azure-pipeline-qa.yml +92 -25
- package/integrations/ado-powershell/scripts/sync-ado-titles.ps1 +2 -2
- package/integrations/playwright/README.md +128 -4
- package/package.json +9 -6
- package/qa-framework.config.json +24 -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 +108 -45
- package/scripts/lib/claude-agents.js +78 -0
- package/scripts/lib/claude-commands.js +56 -0
- package/scripts/sync-version.js +36 -0
- package/scripts/upgrade.js +461 -30
- package/scripts/validate.js +17 -17
- 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 +234 -0
- package/templates/agents/qa-plan.md +131 -0
- package/templates/automation-scaffold/.env.example +52 -3
- package/templates/automation-scaffold/fixtures/auth.ts +27 -5
- package/templates/automation-scaffold/fixtures/base.ts +130 -0
- package/templates/automation-scaffold/fixtures/test-helpers.ts +1 -1
- package/templates/automation-scaffold/global-setup.ts +196 -37
- package/templates/automation-scaffold/playwright.config.ts +74 -10
- 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 +18 -4
- package/templates/execution-report.md +9 -9
- package/templates/integration-scaffold/.env.example +40 -0
- package/templates/integration-scaffold/README.md +77 -0
- package/templates/integration-scaffold/global-setup.ts +119 -0
- package/templates/integration-scaffold/package.json +15 -0
- package/templates/integration-scaffold/playwright.config.ts +92 -0
- package/templates/integration-scaffold/tests/example.spec.ts +43 -0
- package/templates/memory/ci-pipeline-findings.md +36 -0
- package/templates/memory/data-volatility-strategies.md +70 -0
- package/templates/memory/e2e-stabilization-patterns.md +54 -0
- package/templates/qa-framework.instructions.md +16 -7
- package/templates/qa-framework.rules.md +53 -0
- package/templates/qa-readme.md +26 -5
- 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
package/docs/usage-with-agent.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# docs/usage-with-agent.md
|
|
2
2
|
|
|
3
|
-
## Using `qa-framework` with an IDE Agent (GitHub Copilot)
|
|
3
|
+
## Using `qa-framework` with an IDE Agent (GitHub Copilot or Claude Code)
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## Overview
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
`init` and `upgrade` always generate artifacts for both GitHub Copilot and Claude Code
|
|
10
|
+
in parallel - there is no agent detection. This framework is designed so that either
|
|
11
|
+
IDE agent can:
|
|
10
12
|
|
|
11
13
|
1. Understand the QA structure by reading the agent instruction files
|
|
12
14
|
2. Navigate the `qa/` directory predictably
|
|
@@ -42,11 +44,11 @@ This framework is designed so that an IDE agent (such as GitHub Copilot in VS Co
|
|
|
42
44
|
|
|
43
45
|
---
|
|
44
46
|
|
|
45
|
-
## Setting Up Agent Instructions in VS Code
|
|
47
|
+
## Setting Up Agent Instructions in VS Code (GitHub Copilot)
|
|
46
48
|
|
|
47
|
-
### Option A
|
|
49
|
+
### Option A - Workspace instructions file (recommended)
|
|
48
50
|
|
|
49
|
-
`init` generates `.github/
|
|
51
|
+
`init` generates `.github/instructions/qa-framework.instructions.md` automatically. It contains the full
|
|
50
52
|
pipeline sequencer with 11 agent behavior rules, the QA pipeline table, and ADO detection.
|
|
51
53
|
No manual setup needed.
|
|
52
54
|
|
|
@@ -56,7 +58,7 @@ To regenerate after an upgrade:
|
|
|
56
58
|
npx qa-framework upgrade
|
|
57
59
|
```
|
|
58
60
|
|
|
59
|
-
### Option B
|
|
61
|
+
### Option B - Reference skills directly in the agent conversation
|
|
60
62
|
|
|
61
63
|
Paste a skill path into the Copilot chat:
|
|
62
64
|
|
|
@@ -64,7 +66,7 @@ Paste a skill path into the Copilot chat:
|
|
|
64
66
|
Read .github/skills/qa-module-analysis/SKILL.md and analyze the module at {URL}
|
|
65
67
|
```
|
|
66
68
|
|
|
67
|
-
### Option C
|
|
69
|
+
### Option C - Individual task prompts
|
|
68
70
|
|
|
69
71
|
For each major QA task, ask the agent to load the relevant skill:
|
|
70
72
|
|
|
@@ -75,6 +77,77 @@ tests for the submodule {name}
|
|
|
75
77
|
|
|
76
78
|
---
|
|
77
79
|
|
|
80
|
+
## Setting Up Agent Instructions in Claude Code
|
|
81
|
+
|
|
82
|
+
`init` and `upgrade` generate two Claude-Code-native artifacts automatically, no manual
|
|
83
|
+
setup needed:
|
|
84
|
+
|
|
85
|
+
- `.claude/rules/qa-framework.md` - the Claude Code equivalent of the Copilot
|
|
86
|
+
`.instructions.md` file. It has no frontmatter, which means it loads unconditionally in
|
|
87
|
+
every session (the same effect as `applyTo: '**'`). It contains the same 11 agent
|
|
88
|
+
behavior rules and pipeline table as the Copilot instructions, with every skill
|
|
89
|
+
reference expressed as a `/qa-{name}` slash command instead of "load this file".
|
|
90
|
+
- `.claude/commands/qa-{name}.md` - one thin wrapper per skill, generated dynamically
|
|
91
|
+
from whatever folders exist under `.github/skills/` at install/upgrade time. Each
|
|
92
|
+
wrapper is a single instruction: `Read the full skill at .github/skills/qa-{name}/SKILL.md
|
|
93
|
+
FIRST, then follow its instructions exactly`, plus the stage prerequisite. There is zero
|
|
94
|
+
duplication of skill content and therefore zero drift - if a skill is updated, every
|
|
95
|
+
command that points to it picks up the change with no regeneration needed.
|
|
96
|
+
|
|
97
|
+
### Using a command
|
|
98
|
+
|
|
99
|
+
In a Claude Code session, invoke the pipeline stage directly:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
/qa-module-analysis
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Claude reads `.github/skills/qa-module-analysis/SKILL.md` and follows it exactly, the
|
|
106
|
+
same way the Copilot pipeline table routes to that file.
|
|
107
|
+
|
|
108
|
+
### Regenerating after an upgrade
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npx qa-framework upgrade
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This refreshes both `.claude/commands/qa-*.md` and `.claude/rules/qa-framework.md` the
|
|
115
|
+
same safe way it refreshes the Copilot artifacts (framework-owned, always overwritten
|
|
116
|
+
with the current version; nothing else under `.claude/` is touched).
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Optional: ANALISIS/PLAN Mode (Claude Code only, ADO-gated)
|
|
121
|
+
|
|
122
|
+
Some teams run a sprint-centric manual testing workflow in parallel with the 6-stage
|
|
123
|
+
pipeline: an analysis document, a test plan trace-linked to Azure DevOps work items,
|
|
124
|
+
ad-hoc QA advisory chat, and a sprint closing results report. This mode is:
|
|
125
|
+
|
|
126
|
+
- **Optional** - off by default.
|
|
127
|
+
- **Gated** by `integrations.azureDevOps.sprintCycle.enabled` in
|
|
128
|
+
`qa/qa-framework.config.json` (it requires Azure DevOps enabled, since three of the
|
|
129
|
+
four agents depend on ADO work items or an ADO-generated execution report).
|
|
130
|
+
- **Claude Code only, by design, not by omission.** Each agent is a Claude Code subagent
|
|
131
|
+
with its own `tools`/`model` frontmatter (e.g. `qa-asesoria` intentionally has no
|
|
132
|
+
`Write`/`Bash`). GitHub Copilot has no equivalent primitive, so no `.github/` artifact
|
|
133
|
+
is generated for this mode.
|
|
134
|
+
|
|
135
|
+
When enabled, `init`/`upgrade` generate four subagents under `.claude/agents/`:
|
|
136
|
+
|
|
137
|
+
| Agent | Purpose |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `qa-analisis.md` | Analysis document: test universe, automation feasibility, P0-P3 prioritization, excluded universe, traceability matrix |
|
|
140
|
+
| `qa-plan.md` | Default mode: executive summary + a trace-linked test case table, executable within the configured manual-testing timebox |
|
|
141
|
+
| `qa-asesoria.md` | Chat-only QA advisory (no `Write`/`Bash`) - answers point questions, redirects to `qa-plan`/`qa-analisis` when a full document is actually needed |
|
|
142
|
+
| `qa-informe-resultados.md` | Narrative sprint closing report built from an execution report already produced by the `qa-ado-integration` skill; updates incrementally, never overwrites prior sections |
|
|
143
|
+
|
|
144
|
+
Sprint duration, manual-testing timebox, date format, and timezone are parameterized
|
|
145
|
+
from `integrations.azureDevOps.sprintCycle` (with neutral defaults - 8-day sprint,
|
|
146
|
+
2-day timebox, `dd-mm-aaaa`, `America/Santiago` - when a field is omitted). See
|
|
147
|
+
[docs/installation.md](installation.md) for the config shape.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
78
151
|
## Typical Agent Session Workflow
|
|
79
152
|
|
|
80
153
|
### Session 1: Initial Module Analysis
|
|
@@ -124,7 +197,7 @@ tests for the submodule {name}
|
|
|
124
197
|
|
|
125
198
|
### DO
|
|
126
199
|
|
|
127
|
-
- Read `qa/AGENT-NEXT-STEPS.md` at the start of each conversation (auto-enforced by
|
|
200
|
+
- Read `qa/AGENT-NEXT-STEPS.md` at the start of each conversation (auto-enforced by `.github/instructions/qa-framework.instructions.md` for Copilot, or `.claude/rules/qa-framework.md` for Claude Code)
|
|
128
201
|
- Load the relevant skill from `.github/skills/` before starting any QA task
|
|
129
202
|
- Save all artifacts in the exact path specified by `qa/QA-STRUCTURE-GUIDE.md`
|
|
130
203
|
- Use TC-ID, RN-ID, FL-ID naming consistently
|
|
@@ -181,7 +254,8 @@ This performs:
|
|
|
181
254
|
## Continuing from a Previous Session
|
|
182
255
|
|
|
183
256
|
The agent reads `qa/AGENT-NEXT-STEPS.md` automatically at the start of every conversation
|
|
184
|
-
(enforced by `.github/
|
|
257
|
+
(enforced by rule 0 in `.github/instructions/qa-framework.instructions.md` for Copilot,
|
|
258
|
+
or `.claude/rules/qa-framework.md` for Claude Code). For additional context:
|
|
185
259
|
|
|
186
260
|
```
|
|
187
261
|
"Read qa/README.md and qa/memory/INDEX.md, then tell me where we left off."
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
import { test, expect } from '@playwright/test';
|
|
17
17
|
|
|
18
|
-
// EXEC_IDX: unique per minute-window
|
|
18
|
+
// EXEC_IDX: unique per minute-window - prevents data collisions between runs
|
|
19
19
|
const EXEC_IDX = Math.floor(Date.now() / 60_000) % 100_000;
|
|
20
20
|
|
|
21
21
|
test.describe('Suppliers > Create @P0', () => {
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* [TC-SUP-CR-001] Create supplier
|
|
24
|
+
* [TC-SUP-CR-001] Create supplier - happy path @P0
|
|
25
25
|
* Verifies the complete create flow for a valid supplier.
|
|
26
26
|
*/
|
|
27
|
-
test('[TC-SUP-CR-001] Create supplier
|
|
27
|
+
test('[TC-SUP-CR-001] Create supplier - happy path @P0', async ({ page }) => {
|
|
28
28
|
const supplierName = `QA-Supplier-${EXEC_IDX}`;
|
|
29
29
|
const supplierRut = `${EXEC_IDX}-K`;
|
|
30
30
|
const supplierEmail = `qa-supplier-${EXEC_IDX}@example.com`;
|
|
@@ -57,10 +57,10 @@ test.describe('Suppliers > Create @P0', () => {
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
* [TC-SUP-CR-002] Create supplier
|
|
60
|
+
* [TC-SUP-CR-002] Create supplier - required fields validation @P0
|
|
61
61
|
* Verifies that the form prevents submission when required fields are empty.
|
|
62
62
|
*/
|
|
63
|
-
test('[TC-SUP-CR-002] Create supplier
|
|
63
|
+
test('[TC-SUP-CR-002] Create supplier - required fields validation @P0', async ({ page }) => {
|
|
64
64
|
await page.goto('/suppliers');
|
|
65
65
|
await page.locator('button:has-text("New Supplier")').click();
|
|
66
66
|
await expect(page.locator('.supplier-modal')).toBeVisible();
|
|
@@ -79,12 +79,12 @@ test.describe('Suppliers > Create @P0', () => {
|
|
|
79
79
|
});
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
|
-
* [TC-SUP-CR-003] Create supplier
|
|
82
|
+
* [TC-SUP-CR-003] Create supplier - duplicate RUT rejected @P0
|
|
83
83
|
*
|
|
84
|
-
* NOTE: test.skip active
|
|
84
|
+
* NOTE: test.skip active - DEF-001: Duplicate RUT check not enforced server-side.
|
|
85
85
|
* Reactivate when ADO #99001 is resolved.
|
|
86
86
|
*/
|
|
87
|
-
test('[TC-SUP-CR-003] Create supplier
|
|
87
|
+
test('[TC-SUP-CR-003] Create supplier - duplicate RUT rejected @P0', async ({ page }) => {
|
|
88
88
|
test.skip(true,
|
|
89
89
|
'DEF-001: Duplicate RUT validation not enforced. Reactivate when ADO #99001 is resolved.'
|
|
90
90
|
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# -----------------------------------------------------------------------
|
|
2
|
-
# keber/qa-framework
|
|
2
|
+
# keber/qa-framework - Azure Pipeline QA Template
|
|
3
3
|
# -----------------------------------------------------------------------
|
|
4
4
|
# Parameterized CI pipeline for running Playwright E2E and API tests and
|
|
5
5
|
# syncing results to Azure DevOps Test Plans via SYSTEM_ACCESSTOKEN.
|
|
@@ -8,28 +8,28 @@
|
|
|
8
8
|
# Update 'resources.repositories.name' to match your org/project/repo.
|
|
9
9
|
#
|
|
10
10
|
# Required Pipeline Library Variable Group: "QA-Variables"
|
|
11
|
-
# Create this group in ADO
|
|
11
|
+
# Create this group in ADO -> Pipelines -> Library and add the following:
|
|
12
12
|
#
|
|
13
|
-
# QA_BASE_URL
|
|
14
|
-
# QA_USER_EMAIL
|
|
15
|
-
# QA_USER_PASSWORD
|
|
16
|
-
# ADO_ORG
|
|
17
|
-
# ADO_PROJECT
|
|
18
|
-
# ADO_E2E_PLAN_ID
|
|
19
|
-
# ADO_API_PLAN_ID
|
|
13
|
+
# QA_BASE_URL - Target application URL (e.g. https://app-qa.example.com)
|
|
14
|
+
# QA_USER_EMAIL - Test user email / RUT
|
|
15
|
+
# QA_USER_PASSWORD - Test user password [secret]
|
|
16
|
+
# ADO_ORG - ADO organization slug (e.g. my-org)
|
|
17
|
+
# ADO_PROJECT - ADO project name (e.g. my-project)
|
|
18
|
+
# ADO_E2E_PLAN_ID - Test Plan ID for the E2E suite
|
|
19
|
+
# ADO_API_PLAN_ID - Test Plan ID for the API/integration suite
|
|
20
20
|
#
|
|
21
|
-
# NOTE on multiple Plan IDs: ADO variable groups store plain strings
|
|
21
|
+
# NOTE on multiple Plan IDs: ADO variable groups store plain strings - there
|
|
22
22
|
# is no array type. Use one variable per suite (ADO_E2E_PLAN_ID / ADO_API_PLAN_ID).
|
|
23
23
|
# If the project has only one suite, a single ADO_PLAN_ID variable is enough.
|
|
24
24
|
# Results are reported to ADO via System.AccessToken (OAuth); no PAT required.
|
|
25
25
|
# -----------------------------------------------------------------------
|
|
26
26
|
|
|
27
|
-
# Cross-project repository
|
|
27
|
+
# Cross-project repository - update <ADO_SOURCE_PROJECT>/<REPO_NAME> as needed
|
|
28
28
|
resources:
|
|
29
29
|
repositories:
|
|
30
30
|
- repository: source
|
|
31
31
|
type: git
|
|
32
|
-
name: <ADO_SOURCE_PROJECT>/<REPO_NAME> # e.g.
|
|
32
|
+
name: <ADO_SOURCE_PROJECT>/<REPO_NAME> # e.g. my-qa-project/my-repo
|
|
33
33
|
ref: refs/heads/main
|
|
34
34
|
|
|
35
35
|
# Trigger: push and PR to main.
|
|
@@ -44,15 +44,34 @@ pr:
|
|
|
44
44
|
include:
|
|
45
45
|
- main
|
|
46
46
|
|
|
47
|
-
# Optional scheduled run
|
|
47
|
+
# Optional scheduled run - uncomment and adjust if a nightly regression is needed:
|
|
48
48
|
# schedules:
|
|
49
|
-
# - cron: '0 6 * * 1-5' # 06:00 UTC Mon
|
|
49
|
+
# - cron: '0 6 * * 1-5' # 06:00 UTC Mon-Fri (03:00 CLT / 02:00 CLST)
|
|
50
50
|
# displayName: Nightly regression
|
|
51
51
|
# branches:
|
|
52
52
|
# include:
|
|
53
53
|
# - main
|
|
54
54
|
# always: true
|
|
55
55
|
|
|
56
|
+
# -----------------------------------------------------------------------
|
|
57
|
+
# Pipeline parameters
|
|
58
|
+
# -----------------------------------------------------------------------
|
|
59
|
+
# suiteFilter controls which tests run when the pipeline is triggered manually
|
|
60
|
+
# or from a PR. Scheduled runs always override this to 'all' automatically
|
|
61
|
+
# (see the "Resolve suite filter" step in each test job).
|
|
62
|
+
#
|
|
63
|
+
# Default is 'all' so a plain manual run executes the full suite.
|
|
64
|
+
# Override at queue time to run a subset (e.g. 'smoke', '[P0]', 'login').
|
|
65
|
+
#
|
|
66
|
+
# The value is passed to Playwright via --grep. Special regex characters such
|
|
67
|
+
# as '[' and ']' are escaped by the bash array pattern in the run step, so
|
|
68
|
+
# values like '[P0]' are safe.
|
|
69
|
+
parameters:
|
|
70
|
+
- name: suiteFilter
|
|
71
|
+
displayName: 'Test suite filter (grep pattern, or "all" to skip filtering)'
|
|
72
|
+
type: string
|
|
73
|
+
default: 'all'
|
|
74
|
+
|
|
56
75
|
pool:
|
|
57
76
|
vmImage: 'ubuntu-latest'
|
|
58
77
|
|
|
@@ -111,6 +130,21 @@ stages:
|
|
|
111
130
|
# -----------------------------------------------------------------------
|
|
112
131
|
# Stage 2: E2E Tests (Playwright/Chromium)
|
|
113
132
|
# -----------------------------------------------------------------------
|
|
133
|
+
# Single-job configuration. For parallel execution with two test users,
|
|
134
|
+
# split this into two jobs and set QA_AUTH_USER per job:
|
|
135
|
+
#
|
|
136
|
+
# - job: E2E_User1
|
|
137
|
+
# variables:
|
|
138
|
+
# QA_AUTH_USER: '1'
|
|
139
|
+
# ...
|
|
140
|
+
# - job: E2E_User2
|
|
141
|
+
# variables:
|
|
142
|
+
# QA_AUTH_USER: '2'
|
|
143
|
+
# ...
|
|
144
|
+
#
|
|
145
|
+
# Each job must use a distinct Playwright project (--project=chromium-user1 /
|
|
146
|
+
# --project=chromium-user2) to avoid session conflicts between parallel users.
|
|
147
|
+
# -----------------------------------------------------------------------
|
|
114
148
|
- stage: E2E
|
|
115
149
|
displayName: 'E2E Tests (Playwright/Chromium)'
|
|
116
150
|
dependsOn: Setup
|
|
@@ -138,11 +172,11 @@ stages:
|
|
|
138
172
|
HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" --max-time 30 "$(QA_BASE_URL)")
|
|
139
173
|
echo "HTTP response: $HTTP_CODE"
|
|
140
174
|
if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 400 ]; then
|
|
141
|
-
echo "##[error]Smoke test failed
|
|
175
|
+
echo "##[error]Smoke test failed - $(QA_BASE_URL) returned HTTP $HTTP_CODE"
|
|
142
176
|
exit 1
|
|
143
177
|
fi
|
|
144
178
|
echo "Smoke test passed (HTTP $HTTP_CODE)"
|
|
145
|
-
displayName: 'Smoke test
|
|
179
|
+
displayName: 'Smoke test - verify QA_BASE_URL is reachable'
|
|
146
180
|
|
|
147
181
|
# ---------------------------------------------------------------
|
|
148
182
|
# Playwright Workspaces (Azure App Testing)
|
|
@@ -159,9 +193,28 @@ stages:
|
|
|
159
193
|
# inlineScript: echo "Authenticated via Entra ID"
|
|
160
194
|
|
|
161
195
|
- script: |
|
|
196
|
+
# Scheduled runs always execute the full suite, regardless of the
|
|
197
|
+
# suiteFilter parameter. This prevents accidental partial runs in
|
|
198
|
+
# nightly regressions when the parameter was changed by a prior
|
|
199
|
+
# manual queue.
|
|
200
|
+
SUITE_FILTER="${{ parameters.suiteFilter }}"
|
|
201
|
+
if [ "$(Build.Reason)" = "Schedule" ]; then
|
|
202
|
+
SUITE_FILTER="all"
|
|
203
|
+
echo "Scheduled run detected - overriding suiteFilter to 'all'"
|
|
204
|
+
fi
|
|
205
|
+
echo "Effective suiteFilter: $SUITE_FILTER"
|
|
206
|
+
|
|
207
|
+
# Build --grep args as a bash array to safely handle patterns that
|
|
208
|
+
# contain special regex characters such as '[' and ']'. Inline
|
|
209
|
+
# string interpolation would break those patterns at the shell level.
|
|
210
|
+
GREP_ARGS=()
|
|
211
|
+
if [ "$SUITE_FILTER" != "all" ]; then
|
|
212
|
+
GREP_ARGS=(--grep "$SUITE_FILTER")
|
|
213
|
+
fi
|
|
214
|
+
|
|
162
215
|
cd $(E2E_DIR)
|
|
163
216
|
npx playwright test --project=chromium --ignore-snapshots \
|
|
164
|
-
--grep-invert "_inspect|_diag"
|
|
217
|
+
--grep-invert "_inspect|_diag" "${GREP_ARGS[@]}"
|
|
165
218
|
displayName: 'Run E2E tests'
|
|
166
219
|
continueOnError: true
|
|
167
220
|
env:
|
|
@@ -173,31 +226,40 @@ stages:
|
|
|
173
226
|
ADO_PLAN_ID: $(ADO_E2E_PLAN_ID)
|
|
174
227
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
|
175
228
|
CI: 'true'
|
|
176
|
-
#
|
|
229
|
+
# QA_AUTH_USER: '1' # Set explicitly when running parallel jobs (user-1 / user-2 model)
|
|
230
|
+
# PLAYWRIGHT_SERVICE_URL: $(PLAYWRIGHT_SERVICE_URL) # Playwright Workspaces endpoint - enable together with the login task
|
|
177
231
|
|
|
232
|
+
# publishRunAttachments is false because screenshots and traces are
|
|
233
|
+
# already uploaded as pipeline artifacts below. Setting it to true
|
|
234
|
+
# would double-publish the same files.
|
|
178
235
|
- task: PublishTestResults@2
|
|
179
236
|
condition: always()
|
|
180
237
|
inputs:
|
|
181
238
|
testResultsFormat: 'JUnit'
|
|
182
|
-
testResultsFiles: '
|
|
239
|
+
testResultsFiles: 'test-results/junit-results.xml'
|
|
183
240
|
searchFolder: $(E2E_DIR)
|
|
184
241
|
mergeTestResults: true
|
|
242
|
+
publishRunAttachments: false
|
|
185
243
|
failTaskOnFailedTests: true
|
|
186
244
|
testRunTitle: '[Auto E2E] $(Build.BuildNumber)'
|
|
187
245
|
displayName: 'Publish E2E test results (JUnit)'
|
|
188
246
|
|
|
247
|
+
# Artifact names include $(System.JobAttempt) to avoid name collisions
|
|
248
|
+
# when the job is retried. ADO rejects duplicate artifact names within
|
|
249
|
+
# the same pipeline run, so without the suffix a retry always fails at
|
|
250
|
+
# the publish step.
|
|
189
251
|
- task: PublishPipelineArtifact@1
|
|
190
252
|
condition: always()
|
|
191
253
|
inputs:
|
|
192
254
|
targetPath: '$(E2E_DIR)/playwright-report'
|
|
193
|
-
artifact: 'e2e-playwright-report'
|
|
255
|
+
artifact: 'e2e-playwright-report-attempt-$(System.JobAttempt)'
|
|
194
256
|
displayName: 'Publish E2E HTML report'
|
|
195
257
|
|
|
196
258
|
- task: PublishPipelineArtifact@1
|
|
197
259
|
condition: always()
|
|
198
260
|
inputs:
|
|
199
261
|
targetPath: '$(E2E_DIR)/test-results'
|
|
200
|
-
artifact: 'e2e-test-results'
|
|
262
|
+
artifact: 'e2e-test-results-attempt-$(System.JobAttempt)'
|
|
201
263
|
displayName: 'Publish E2E trace artifacts'
|
|
202
264
|
|
|
203
265
|
# -----------------------------------------------------------------------
|
|
@@ -237,6 +299,7 @@ stages:
|
|
|
237
299
|
# inlineScript: echo "Authenticated via Entra ID"
|
|
238
300
|
|
|
239
301
|
- script: |
|
|
302
|
+
# API integration tests do not use suite tags - always run all.
|
|
240
303
|
cd $(API_DIR)
|
|
241
304
|
npx playwright test --grep-invert "_inspect|_diag"
|
|
242
305
|
displayName: 'Run API integration tests'
|
|
@@ -250,29 +313,33 @@ stages:
|
|
|
250
313
|
ADO_PLAN_ID: $(ADO_API_PLAN_ID)
|
|
251
314
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
|
252
315
|
CI: 'true'
|
|
253
|
-
# PLAYWRIGHT_SERVICE_URL: $(PLAYWRIGHT_SERVICE_URL) # Playwright Workspaces endpoint
|
|
316
|
+
# PLAYWRIGHT_SERVICE_URL: $(PLAYWRIGHT_SERVICE_URL) # Playwright Workspaces endpoint - enable together with the login task
|
|
254
317
|
|
|
318
|
+
# publishRunAttachments is false because trace artifacts are already
|
|
319
|
+
# uploaded as pipeline artifacts below.
|
|
255
320
|
- task: PublishTestResults@2
|
|
256
321
|
condition: always()
|
|
257
322
|
inputs:
|
|
258
323
|
testResultsFormat: 'JUnit'
|
|
259
|
-
testResultsFiles: '
|
|
324
|
+
testResultsFiles: 'test-results/junit-results.xml'
|
|
260
325
|
searchFolder: $(API_DIR)
|
|
261
326
|
mergeTestResults: true
|
|
327
|
+
publishRunAttachments: false
|
|
262
328
|
failTaskOnFailedTests: true
|
|
263
329
|
testRunTitle: '[Auto API] $(Build.BuildNumber)'
|
|
264
330
|
displayName: 'Publish API test results (JUnit)'
|
|
265
331
|
|
|
332
|
+
# Artifact names include $(System.JobAttempt) to prevent collision on retries.
|
|
266
333
|
- task: PublishPipelineArtifact@1
|
|
267
334
|
condition: always()
|
|
268
335
|
inputs:
|
|
269
336
|
targetPath: '$(API_DIR)/playwright-report'
|
|
270
|
-
artifact: 'api-playwright-report'
|
|
337
|
+
artifact: 'api-playwright-report-attempt-$(System.JobAttempt)'
|
|
271
338
|
displayName: 'Publish API HTML report'
|
|
272
339
|
|
|
273
340
|
- task: PublishPipelineArtifact@1
|
|
274
341
|
condition: always()
|
|
275
342
|
inputs:
|
|
276
343
|
targetPath: '$(API_DIR)/test-results'
|
|
277
|
-
artifact: 'api-test-results'
|
|
344
|
+
artifact: 'api-test-results-attempt-$(System.JobAttempt)'
|
|
278
345
|
displayName: 'Publish API trace artifacts'
|
|
@@ -61,7 +61,7 @@ foreach ($entry in $mapping) {
|
|
|
61
61
|
Select-Object -First 1
|
|
62
62
|
|
|
63
63
|
if (-not $specFile) {
|
|
64
|
-
Write-Warning " [NOT FOUND] $($entry.specFile)
|
|
64
|
+
Write-Warning " [NOT FOUND] $($entry.specFile) - skipping WI $adoId"
|
|
65
65
|
$skipped++
|
|
66
66
|
continue
|
|
67
67
|
}
|
|
@@ -84,7 +84,7 @@ foreach ($entry in $mapping) {
|
|
|
84
84
|
|
|
85
85
|
if ($PSCmdlet.ShouldProcess("WI #$adoId", "Update title to: $newTitle")) {
|
|
86
86
|
Invoke-RestMethod -Method Patch -Uri $patchUrl -Headers $headers -Body $body | Out-Null
|
|
87
|
-
Write-Host " [SYNCED] WI #$adoId
|
|
87
|
+
Write-Host " [SYNCED] WI #$adoId -> $newTitle"
|
|
88
88
|
$synced++
|
|
89
89
|
}
|
|
90
90
|
}
|