spec-lite 1.6.0 → 1.7.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/README.md +6 -0
- package/package.json +1 -1
- package/skills/archive/SKILL.md +63 -52
- package/skills/spec-test-exec/SKILL.md +251 -0
- package/skills-overview.md +20 -7
- package/templates/main/feature/test-design-template.md +14 -2
- package/templates/test-executions/test-exec-dm-template.md +83 -0
- package/templates/test-executions/test-exec-e2e-auto-template.md +299 -0
- package/templates/test-executions/test-exec-e2e-manual-template.md +231 -0
- package/templates/test-executions/test-exec-func-auto-template.md +155 -0
- package/templates/test-executions/test-exec-func-manual-template.md +203 -0
- package/templates/test-executions/test-exec-nfr-template.md +88 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: test-exec-dm-{F-XXX}-{NNN}-{slug}
|
|
3
|
+
type: test-exec-dm
|
|
4
|
+
status: draft
|
|
5
|
+
owner: "{SE / DBA}"
|
|
6
|
+
feature_id: "{F-XXX}"
|
|
7
|
+
test_design_ref: "main/feature/{F-XXX}-{slug}/test-design.md"
|
|
8
|
+
referenced_by:
|
|
9
|
+
- conventions.md > Test Execution Artifacts > test-exec-dm.md
|
|
10
|
+
- terms/003-test-exec-buckets.md
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
Canonical format cho .specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/test-exec-dm.md.
|
|
15
|
+
EXECUTION layer — ephemeral per test cycle, harness "migration script trên dataset prod-like", owner SE/DBA.
|
|
16
|
+
Cover Data & Migration (DM) — backfill, schema migration, data cũ không mất/hỏng. Xem terms/003.
|
|
17
|
+
|
|
18
|
+
KHÔNG versioned: không template_version / migrations, ngoài scope /artifact-audit + /artifact-migrate.
|
|
19
|
+
Derived từ test-design.md → test-design đổi thì REGENERATE.
|
|
20
|
+
|
|
21
|
+
CHỈ TẠO file này khi frd.md có `DM-F*` (test-design § Data & Migration Test Cases không rỗng).
|
|
22
|
+
Feature không đụng migration → KHÔNG tạo test-exec-dm.md.
|
|
23
|
+
|
|
24
|
+
Source of truth: test-design.md > Data & Migration Test Cases.
|
|
25
|
+
- ID = TC-F{NNN}-{seq} inherit từ test-design (Covers DM-F*). KHÔNG tạo ID mới.
|
|
26
|
+
- Coverage master = test-design.md > Traceability Matrix.
|
|
27
|
+
-->
|
|
28
|
+
|
|
29
|
+
# Data & Migration Test Execution: {Feature Name}
|
|
30
|
+
|
|
31
|
+
**Feature**: {F-XXX} | **Owner**: {owner} | **Status**: {status}
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 1. Context
|
|
36
|
+
|
|
37
|
+
| **Field** | **Detail** |
|
|
38
|
+
|---|---|
|
|
39
|
+
| **Feature Summary** | {1–2 câu — migration/backfill scope} |
|
|
40
|
+
| **DM covered** | {DM IDs — `DM-F{NNN}-001`, ...} |
|
|
41
|
+
| **Source** | [test-design.md](../../../main/feature/{F-XXX}-{slug}/test-design.md) — TC IDs (Data & Migration Test Cases) + Traceability Matrix |
|
|
42
|
+
| **Migration artifact** | {ref script/EF migration: `{migration-name}` hoặc path} |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 2. Dataset & Migration Setup
|
|
47
|
+
|
|
48
|
+
> Migration chạy trên dataset **prod-like** — không phải seed nhỏ. Phải snapshot trước để so khớp.
|
|
49
|
+
|
|
50
|
+
| **Field** | **Detail** |
|
|
51
|
+
|---|---|
|
|
52
|
+
| **Dataset** | {vd: 10.000 bản ghi địa chỉ format cũ — nguồn / cách load} |
|
|
53
|
+
| **Pre-condition chung** | Migration script đã review · dataset prod-like đã load vào env test |
|
|
54
|
+
| **Snapshot before** | count + checksum trước migration (baseline để assert) |
|
|
55
|
+
| **Rollback plan** | {cách revert nếu migration fail — backup/restore / down-migration} |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. DM Execution
|
|
60
|
+
|
|
61
|
+
> **Input:** test-design.md § Data & Migration Test Cases (TC ID, expected — đếm/so khớp).
|
|
62
|
+
> **Test Result:** `—` (chưa chạy) | `✅ Pass` | `❌ Fail` | `⛔ Blocked` | `🔴 HOLD`
|
|
63
|
+
|
|
64
|
+
| **TC ID** | **Covers** | **Pre-condition** | **Migration Command** | **Expected** | **Test Result** | **Priority** |
|
|
65
|
+
|---|---|---|---|---|---|---|
|
|
66
|
+
| `TC-F{NNN}-060` | `DM-F{NNN}-001` | Dataset prod-like loaded ({N} bản ghi cũ) · snapshot baseline | `{migration-command}` | count sau = count trước ({N}/{N}) · 0 null · format mới parse đúng | — | 🔴 P0 |
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 4. Exit Criteria
|
|
71
|
+
|
|
72
|
+
- [ ] Mọi DM P0 TC pass — data cũ nguyên vẹn (count + checksum khớp)
|
|
73
|
+
- [ ] 0 bản ghi mất / null / lỗi parse sau migration
|
|
74
|
+
- [ ] Rollback đã verify chạy được (dry-run hoặc trên copy)
|
|
75
|
+
- [ ] Test Result column updated đầy đủ
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 5. Change Log
|
|
80
|
+
|
|
81
|
+
| **Date** | **Cycle** | **Changes** | **Author** |
|
|
82
|
+
|---|---|---|---|
|
|
83
|
+
| {YYYY-MM-DD} | {cycle/release} | Initial DM execution (derive từ test-design.md) | {Author} |
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: test-exec-e2e-auto-{F-XXX}-{NNN}-{slug}
|
|
3
|
+
type: test-exec-e2e-auto
|
|
4
|
+
status: draft
|
|
5
|
+
method: automation
|
|
6
|
+
owner: "{SE}"
|
|
7
|
+
feature_id: "{F-XXX}"
|
|
8
|
+
test_design_ref: "main/feature/{F-XXX}-{slug}/test-design.md"
|
|
9
|
+
alt_harness_manual: "./test-exec-e2e-manual.md"
|
|
10
|
+
platform: web
|
|
11
|
+
runner: playwright
|
|
12
|
+
pom_path: "{e2e-root}/pages/{slug}.page.ts"
|
|
13
|
+
spec_path: "{e2e-root}/{slug}.spec.ts"
|
|
14
|
+
fixtures_path: "{e2e-root}/fixtures/"
|
|
15
|
+
referenced_by:
|
|
16
|
+
- conventions.md > Test Execution Artifacts > test-exec-e2e-auto.md
|
|
17
|
+
- terms/003-test-exec-buckets.md
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<!--
|
|
21
|
+
Canonical format cho .specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/test-exec-e2e-auto.md.
|
|
22
|
+
EXECUTION layer — ephemeral per test cycle. Harness "Playwright / browser automation", owner SE.
|
|
23
|
+
Cover Feature Acceptance Criteria (FAC) end-to-end — journey / consistency / integrity. Xem terms/003.
|
|
24
|
+
|
|
25
|
+
E2E = SCOPE (FAC qua integration boundary), KHÔNG phải "Playwright". File này là bản render
|
|
26
|
+
AUTOMATION của scope đó; bản render MANUAL (QC walk tay) ở ./test-exec-e2e-manual.md.
|
|
27
|
+
- e2e-auto và e2e-manual là HAI HARNESS THAY THẾ cho CÙNG một scope — team chọn MỘT theo
|
|
28
|
+
kỹ năng / độ trưởng thành (manual-only → manual; có automation → auto). KHÔNG chạy song song
|
|
29
|
+
để đối chiếu → KHÔNG có test-exec-e2e-report. (frontmatter dùng alt_harness_*.)
|
|
30
|
+
- Cả hai share cùng spine 8-slot + cùng TC-F* để dễ maintain / dễ chuyển harness.
|
|
31
|
+
- KHÁC func: manual & auto e2e THAY THẾ NHAU HOÀN TOÀN (cùng outcome, cùng cách) — chọn bên nào
|
|
32
|
+
cũng không mất gì. (func thì auto-only lọt exploratory/visual — xem terms/004.)
|
|
33
|
+
|
|
34
|
+
KHÔNG versioned: không template_version / migrations, ngoài scope /artifact-audit + /artifact-migrate.
|
|
35
|
+
Derived từ test-design.md → test-design đổi thì REGENERATE.
|
|
36
|
+
|
|
37
|
+
Source of truth: test-design.md > E2E Test Cases.
|
|
38
|
+
- ID artifact = TC-F{NNN}-{seq} inherit từ test-design (Covers FAC-F*). KHÔNG tạo ID mới.
|
|
39
|
+
- {PREFIX}_E2E_F{NNN}_{TYPE}_{seq} (nếu dùng) CHỈ là title test.describe trong *.spec.ts (code).
|
|
40
|
+
- Coverage master = test-design.md > Traceability Matrix.
|
|
41
|
+
|
|
42
|
+
E2E phải verify BUSINESS OUTCOME qua integration boundary (UI→API→DB), không chỉ UI state.
|
|
43
|
+
UI State: "Success toast visible" ← chưa đủ
|
|
44
|
+
Business Outcome: "Record tồn tại trong DB, hiện trên list, count = N" ← bắt buộc [verify-db]/[verify-api]
|
|
45
|
+
|
|
46
|
+
Kết quả = CI run. Cột Status (CI) ở §5 phản ánh CI run gần nhất — KHÔNG điền tay.
|
|
47
|
+
-->
|
|
48
|
+
|
|
49
|
+
# E2E Test Specification (Automation): {Feature Name}
|
|
50
|
+
|
|
51
|
+
**Feature**: {F-XXX} | **Owner**: {owner} | **Reviewer**: {reviewer} | **Status**: {status}
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 1. Context
|
|
56
|
+
|
|
57
|
+
| **Field** | **Detail** |
|
|
58
|
+
|---|---|
|
|
59
|
+
| **Feature Summary** | {2–3 câu từ frd.md Overview} |
|
|
60
|
+
| **FAC covered** | {FAC IDs — `FAC-F{NNN}-001`, ...} |
|
|
61
|
+
| **E2E Purpose** | Verify business outcome + integration point — không chỉ UI behavior |
|
|
62
|
+
| **Method** | automation — Playwright, Page Object Model, real seeded backend (no API mocking) |
|
|
63
|
+
| **NOT in E2E Scope** | Validation format/length đơn lẻ (→ test-exec-func) · NFR (→ test-exec-nfr) · DM (→ test-exec-dm) |
|
|
64
|
+
| **Source** | [test-design.md](../../../main/feature/{F-XXX}-{slug}/test-design.md) — TC IDs (E2E Test Cases) + Traceability Matrix |
|
|
65
|
+
| **Alt harness** | [test-exec-e2e-manual.md](./test-exec-e2e-manual.md) — bản manual (team chọn 1, không chạy song song) |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 2. Environment & Setup
|
|
70
|
+
|
|
71
|
+
### 2.1 Authentication
|
|
72
|
+
|
|
73
|
+
| **Field** | **Value** |
|
|
74
|
+
|---|---|
|
|
75
|
+
| Auth Setup File | `{e2e-root}/auth.setup.ts` |
|
|
76
|
+
| Primary Storage State | `{e2e-root}/.auth/{role}.json` |
|
|
77
|
+
| Env Var (alt) | `E2E_{ROLE}_STORAGE_STATE` / `E2E_{ROLE}_LOGIN_URL` |
|
|
78
|
+
| Cross-scope test | Storage state thứ hai: `E2E_OTHER_STORAGE_STATE` (out-of-scope user) |
|
|
79
|
+
| Auth Strategy | `storageState` reuse — không re-login mỗi test |
|
|
80
|
+
|
|
81
|
+
### 2.2 Playwright Config
|
|
82
|
+
|
|
83
|
+
| **Field** | **Value** |
|
|
84
|
+
|---|---|
|
|
85
|
+
| Base URL | `process.env.E2E_BASE_URL` |
|
|
86
|
+
| Default / Expect Timeout | 30 000 ms / 10 000 ms |
|
|
87
|
+
| Async Job Timeout | 60 000 ms (background processing) |
|
|
88
|
+
| Retries (CI) / Workers | 2 / {N} (tránh DB contention) |
|
|
89
|
+
| Video | `on-first-retry` |
|
|
90
|
+
|
|
91
|
+
### 2.3 Environment Tiers
|
|
92
|
+
|
|
93
|
+
| **Env** | **Purpose** | **Data** | **Notes** |
|
|
94
|
+
|---|---|---|---|
|
|
95
|
+
| dev | Primary E2E run | Seeded DB | Main E2E environment |
|
|
96
|
+
| stag | Pre-release regression | Anonymized prod data | Gate trước deploy |
|
|
97
|
+
|
|
98
|
+
### 2.4 Seed Data Requirements
|
|
99
|
+
|
|
100
|
+
> Phải tồn tại trong DB trước khi E2E chạy. SE cung cấp seed script / fixture.
|
|
101
|
+
|
|
102
|
+
| **Seed Item** | **Description** | **Required by (TC)** |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| {seed-1} | {vd: Admin user scope A full permission} | All scenarios |
|
|
105
|
+
| {seed-2} | {vd: Out-of-scope user cho guard scenario} | `TC-F{NNN}-0XX` |
|
|
106
|
+
|
|
107
|
+
### 2.5 Platform & Viewport Matrix
|
|
108
|
+
|
|
109
|
+
| **Platform / View** | **Viewport** | **Priority** | **Auth** | **Scenarios** |
|
|
110
|
+
|---|---|---|---|---|
|
|
111
|
+
| Web Desktop | 1440px | P0 | `storageState` | All |
|
|
112
|
+
| Web Tablet | 768px | P1 | `storageState` | journey only |
|
|
113
|
+
| Web Mobile | 375px | P1 | `storageState` | journey only (nếu frd NFR có mobile) |
|
|
114
|
+
|
|
115
|
+
> frd.md không có mobile NFR → skip Tablet/Mobile.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 3. Coverage
|
|
120
|
+
|
|
121
|
+
> FAC → E2E TC mapping. Mỗi `TC-F*` phải xuất hiện ở test-design > Traceability Matrix. Design driver = **FAC**.
|
|
122
|
+
|
|
123
|
+
| **FAC ID** | **Shape** | **Business Outcome cần verify** | **E2E TC** | **Code title (*.spec.ts)** | **Priority** |
|
|
124
|
+
|---|---|---|---|---|---|
|
|
125
|
+
| `FAC-F{NNN}-001` | journey | {vd "Record persisted trong DB"} | `TC-F{NNN}-040` | `{PREFIX}_E2E_F{NNN}_HP_001` | 🔴 P0 |
|
|
126
|
+
| `FAC-F{NNN}-002` | consistency | {vd "Message đồng nhất 3 màn"} | `TC-F{NNN}-041` | `{PREFIX}_E2E_F{NNN}_HP_002` | 🟡 P1 |
|
|
127
|
+
| `FAC-F{NNN}-003` | integrity | {vd "Xóa account → cascade xóa order"} | `TC-F{NNN}-042` | `{PREFIX}_E2E_F{NNN}_SEC_001` | 🔴 P0 |
|
|
128
|
+
|
|
129
|
+
**Excluded TCs (→ manual-only):** {TC ranges + lý do — vd Autoable=NO visual, hoặc validation đơn lẻ → test-exec-func}
|
|
130
|
+
|
|
131
|
+
| **Metric** | **Value** |
|
|
132
|
+
|---|---|
|
|
133
|
+
| FAC covered by E2E | {n} / {total} ({%}) |
|
|
134
|
+
| E2E TC automated | {n} / {total} ({%}) |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## 4. Integration Points & Data Flow
|
|
139
|
+
|
|
140
|
+
> E2E verify **mọi integration boundary** trong business flow, không chỉ UI feedback.
|
|
141
|
+
|
|
142
|
+
### 4.1 Integration Map
|
|
143
|
+
|
|
144
|
+
```mermaid
|
|
145
|
+
flowchart TD
|
|
146
|
+
U([User / Browser]) -->|HTTP| FE[Frontend]
|
|
147
|
+
FE -->|REST| API[Backend API]
|
|
148
|
+
API -->|ORM| DB[(Database)]
|
|
149
|
+
API -.->|async job| Q[Job Queue / Worker]
|
|
150
|
+
Q --> DB
|
|
151
|
+
API -.->|optional| EXT[External Service]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 4.2 Integration Points Table
|
|
155
|
+
|
|
156
|
+
| **ID** | **Integration Point** | **From → To** | **Trigger** | **Playwright Verification** | **Failure Expected** |
|
|
157
|
+
|---|---|---|---|---|---|
|
|
158
|
+
| `INT-01` | {request accepted} | Browser → API | {method + endpoint} | `[assert]` HTTP 2xx via `page.waitForResponse()` | HTTP 4xx → error shown |
|
|
159
|
+
| `INT-02` | {async job completes} | API Queue → DB | background | `[wait]` result element visible (60s) | timeout → job failed |
|
|
160
|
+
| `INT-03` | {data persisted} | DB → API → FE | subsequent GET | `[verify-db]` navigate list → count đúng | missing → data loss |
|
|
161
|
+
| `INT-04` | {scope guard} | Browser → API middleware | cross-scope request | `[assert]` HTTP 403 / redirect | bypassed → security bug |
|
|
162
|
+
|
|
163
|
+
### 4.3 Data Flow Validation
|
|
164
|
+
|
|
165
|
+
| **Data Point** | **Source** | **Expected Value** | **Verification** |
|
|
166
|
+
|---|---|---|---|
|
|
167
|
+
| {records} | DB | {N records, status=X} | navigate list → count = N |
|
|
168
|
+
| {scope isolation} | DB | {out-scope user thấy 0} | login out-scope → list empty / 403 |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 5. Test Cases
|
|
173
|
+
|
|
174
|
+
> **TC ID:** inherit từ test-design (E2E Test Cases) — `TC-F{NNN}-{seq}`, stable. KHÔNG tạo ID mới.
|
|
175
|
+
>
|
|
176
|
+
> **Step prefix:** `[goto]` navigate | `[action]` interact | `[wait]` async state | `[assert]` UI check | `[verify-db]` navigate+confirm DB | `[verify-api]` HTTP status/body | `[download]` file | `[teardown]` afterEach hook ONLY.
|
|
177
|
+
>
|
|
178
|
+
> **Quy tắc `[verify-db]`:** navigate RA KHỎI trang hiện tại → trang khác → assert data tồn tại. Toast/success message KHÔNG đủ (hiện trước khi async job xong).
|
|
179
|
+
> **Quy tắc `[verify-api]`:** dùng `page.request` (không phải `fetch`) để kế thừa auth cookie từ `storageState`.
|
|
180
|
+
>
|
|
181
|
+
> **Status (CI):** `—` (chưa viết) | `🟢 green` | `🔴 red` | `⏭ skipped` | `🟡 flaky`. **Không điền tay** — phản ánh CI run gần nhất.
|
|
182
|
+
|
|
183
|
+
### 5.1 Journey / Happy Path
|
|
184
|
+
|
|
185
|
+
> Verify complete business flow đến outcome cuối. ≥ 1 `[verify-db]` step mỗi scenario.
|
|
186
|
+
|
|
187
|
+
| **E2E TC** | **FAC** | **Persona** | **Pre-Conditions** | **Playwright Steps** | **Business Outcome** | **Status (CI)** | **Priority** |
|
|
188
|
+
|---|---|---|---|---|---|---|---|
|
|
189
|
+
| `TC-F{NNN}-040` | `FAC-F{NNN}-001` | {persona} | 1. {precondition}<br>2. {seed exists} | 1. [goto] `pom.goto{Page}()`<br>2. [action] `pom.{action}({arg})`<br>3. [wait] `pom.{wait}()`<br>4. [assert] `expect(pom.{loc}()).toBeVisible()`<br>5. [action] `pom.{confirm}().click()`<br>6. [verify-db] `pom.goto{List}()` → `expect(pom.{count}()).toContainText('{N}')` | • {N} records persisted<br>• Hiện trên {page} đúng status<br>• State persist qua refresh | — | 🔴 P0 |
|
|
190
|
+
|
|
191
|
+
### 5.2 Consistency (đa màn)
|
|
192
|
+
|
|
193
|
+
> So khớp UI/behavior nhiều màn. Verify identical (text/style/rule) — không cần journey tuần tự.
|
|
194
|
+
|
|
195
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Playwright Steps** | **Expected** | **Status (CI)** | **Priority** |
|
|
196
|
+
|---|---|---|---|---|---|---|
|
|
197
|
+
| `TC-F{NNN}-041` | `FAC-F{NNN}-002` | {N màn accessible} | 1. [action] trigger {behavior} ở màn A<br>2. [action] … ở màn B<br>3. [action] … ở màn C<br>4. [assert] so 3 kết quả | • {behavior} identical across màn A/B/C | — | 🟡 P1 |
|
|
198
|
+
|
|
199
|
+
### 5.3 Integrity (bất biến liên story, không tuần tự)
|
|
200
|
+
|
|
201
|
+
> Assert business invariant sau khi kết hợp nhiều story. Verify trạng thái nhất quán cuối + **no side effect** ngoài invariant.
|
|
202
|
+
|
|
203
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Playwright Steps** | **Expected (invariant)** | **Status (CI)** | **Priority** |
|
|
204
|
+
|---|---|---|---|---|---|---|
|
|
205
|
+
| `TC-F{NNN}-042` | `FAC-F{NNN}-003` | {baseline state} | 1. [verify-db] baseline count/state<br>2. [action] thao tác story X<br>3. [action] thao tác story Y<br>4. [verify-db] assert invariant | • {vd: xóa account → 0 order còn sót ở mọi module}<br>• Tổng/đối soát khớp | — | 🔴 P0 |
|
|
206
|
+
|
|
207
|
+
### 5.4 Negative / Guard *(nếu FAC có)*
|
|
208
|
+
|
|
209
|
+
> Verify guard tại integration boundary — confirm error **VÀ** no side effect (no DB write).
|
|
210
|
+
> Pattern: `[verify-db]` baseline → trigger error → `[assert]` error+guard → `[verify-db]` count = baseline.
|
|
211
|
+
|
|
212
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Playwright Steps** | **Expected** | **Status (CI)** | **Priority** |
|
|
213
|
+
|---|---|---|---|---|---|---|
|
|
214
|
+
| `TC-F{NNN}-0XX` | `FAC-F{NNN}-00N` | {invalid condition} | 1. [verify-db] baseline N<br>2. [action] {invalid}<br>3. [assert] error + guard disabled<br>4. [verify-db] count còn = N | • Error hiển thị<br>• **No new record** (count = N) | — | 🔴 P0 |
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 6. Fixtures & Test Data
|
|
219
|
+
|
|
220
|
+
> Provisioning tự động — fixture file / factory. File tại `{fixtures_path}`. SE tạo trước khi viết test.
|
|
221
|
+
|
|
222
|
+
| **File / Factory** | **Type** | **Content** | **Used by (TC)** |
|
|
223
|
+
|---|---|---|---|
|
|
224
|
+
| `{file-1}` | {Excel/JSON/factory} | {vd: 5 valid rows, no dup} | `TC-F{NNN}-040` |
|
|
225
|
+
| `{file-2}` | {…} | {vd: header mismatch} | `TC-F{NNN}-0XX` |
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## 7. Execution
|
|
230
|
+
|
|
231
|
+
### 7.1 Page Object Index
|
|
232
|
+
|
|
233
|
+
> POM class implement locators/methods dùng ở §5. File: `{pom_path}`
|
|
234
|
+
|
|
235
|
+
#### Class: `{PageObjectClassName}`
|
|
236
|
+
|
|
237
|
+
| **Area** | **Method** | **Returns** | **Description** |
|
|
238
|
+
|---|---|---|---|
|
|
239
|
+
| Navigation | `goto{Page}(): Promise<void>` | void | navigate + `waitForLoadState('networkidle')` |
|
|
240
|
+
| {UI Area} | `{locator}(): Locator` | Locator | {element} |
|
|
241
|
+
| {UI Area} | `{action}(arg): Promise<void>` | void | {action} |
|
|
242
|
+
|
|
243
|
+
> **Selector Strategy** (thứ tự ưu tiên): `getByTestId` → `getByRole` → `getByLabel` → `locator([data-attr])`.
|
|
244
|
+
> Element cần `data-testid` → request FE add attribute.
|
|
245
|
+
|
|
246
|
+
### 7.2 Automation Artifacts
|
|
247
|
+
|
|
248
|
+
| **File** | **Type** | **Description** |
|
|
249
|
+
|---|---|---|
|
|
250
|
+
| `{spec_path}` | Test spec | `test.describe(...)` blocks |
|
|
251
|
+
| `{pom_path}` | Page Object | locators + actions |
|
|
252
|
+
| `{fixtures_path}{files}` | Test data | xem §6 |
|
|
253
|
+
|
|
254
|
+
### 7.3 Commands
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
npx playwright test {slug}.spec.ts # full suite
|
|
258
|
+
npx playwright test {slug}.spec.ts --grep "HP" # journey only
|
|
259
|
+
npx playwright test {slug}.spec.ts --headed # debug
|
|
260
|
+
npx playwright show-report
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### 7.4 CI Gate
|
|
264
|
+
|
|
265
|
+
| **Trigger** | **Scope** | **Gate** |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| PR → develop | journey P0 smoke | block merge nếu fail |
|
|
268
|
+
| Merge → develop | full suite | alert nếu fail |
|
|
269
|
+
| Deploy → staging | full suite on stag | block release nếu P0 fail |
|
|
270
|
+
| Nightly | full + edge | report only |
|
|
271
|
+
|
|
272
|
+
### 7.5 Success Criteria & Exit
|
|
273
|
+
|
|
274
|
+
**Must Have — P0 (block deploy nếu fail):**
|
|
275
|
+
- [ ] Mọi journey scenario pass — business outcome verified (không chỉ UI)
|
|
276
|
+
- [ ] Mọi guard scenario pass — boundary enforced tại API layer
|
|
277
|
+
- [ ] `[verify-db]` steps pass — data thực sự persisted
|
|
278
|
+
- [ ] Không integrity invariant nào vi phạm
|
|
279
|
+
|
|
280
|
+
**Should Have — P1:** consistency pass · negative graceful · no flaky (3/3 runs) · journey pass trên Tablet
|
|
281
|
+
**Nice to Have — P2:** journey pass trên Mobile · suite < 5 phút
|
|
282
|
+
|
|
283
|
+
### 7.6 Risk & Mitigation
|
|
284
|
+
|
|
285
|
+
| **Risk** | **Impact** | **Mitigation** |
|
|
286
|
+
|---|---|---|
|
|
287
|
+
| Flaky: async job timing | High | `waitFor({ state:'visible', timeout })` — không `sleep` |
|
|
288
|
+
| `[verify-db]` false positive (stale cache) | High | navigate + `page.reload()` trước assert |
|
|
289
|
+
| Test data contamination | High | `[teardown]` cleanup mỗi test tạo record |
|
|
290
|
+
| Auth storage state expired | Medium | `auth.setup.ts` chạy trước suite |
|
|
291
|
+
| Locators fragile khi UI refactor | Medium | ưu tiên `data-testid` |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 8. Change Log
|
|
296
|
+
|
|
297
|
+
| **Date** | **Cycle** | **Changes** | **Author** |
|
|
298
|
+
|---|---|---|---|
|
|
299
|
+
| {YYYY-MM-DD} | {cycle/release} | Initial E2E automation spec (derive từ test-design.md E2E Test Cases) | {Author} |
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: test-exec-e2e-manual-{F-XXX}-{NNN}-{slug}
|
|
3
|
+
type: test-exec-e2e-manual
|
|
4
|
+
status: draft
|
|
5
|
+
method: manual
|
|
6
|
+
owner: "{QC}"
|
|
7
|
+
feature_id: "{F-XXX}"
|
|
8
|
+
test_design_ref: "main/feature/{F-XXX}-{slug}/test-design.md"
|
|
9
|
+
alt_harness_auto: "./test-exec-e2e-auto.md"
|
|
10
|
+
platform: web
|
|
11
|
+
referenced_by:
|
|
12
|
+
- conventions.md > Test Execution Artifacts > test-exec-e2e-manual.md
|
|
13
|
+
- terms/003-test-exec-buckets.md
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
<!--
|
|
17
|
+
Canonical format cho .specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/test-exec-e2e-manual.md.
|
|
18
|
+
EXECUTION layer — ephemeral per test cycle. Harness "GUI walk tay (QC) — verify outcome qua điều hướng sản phẩm", owner QC.
|
|
19
|
+
Cover Feature Acceptance Criteria (FAC) end-to-end — journey / consistency / integrity. Xem terms/003.
|
|
20
|
+
|
|
21
|
+
E2E = SCOPE (FAC qua integration boundary), KHÔNG phải "Playwright". File này là bản render
|
|
22
|
+
MANUAL của scope đó; bản render AUTOMATION (SE Playwright) ở ./test-exec-e2e-auto.md.
|
|
23
|
+
- e2e-manual và e2e-auto là HAI HARNESS THAY THẾ cho CÙNG một scope — team chọn MỘT theo
|
|
24
|
+
kỹ năng / độ trưởng thành. KHÔNG chạy song song để đối chiếu → KHÔNG có
|
|
25
|
+
test-exec-e2e-report. (frontmatter dùng alt_harness_*.)
|
|
26
|
+
- Cả hai share cùng spine 8-slot + cùng TC-F* để dễ maintain / dễ chuyển harness.
|
|
27
|
+
- KHÁC func: manual & auto e2e THAY THẾ NHAU HOÀN TOÀN — chọn bên nào cũng không mất gì.
|
|
28
|
+
(func thì auto-only lọt exploratory/visual.)
|
|
29
|
+
|
|
30
|
+
QC verify business outcome KHÔNG bằng code/DB query, mà bằng ĐIỀU HƯỚNG QUA SẢN PHẨM:
|
|
31
|
+
tạo data → RỜI màn hiện tại → sang màn list/detail/admin → xác nhận data thật (count/status).
|
|
32
|
+
Toast/success message KHÔNG đủ làm bằng chứng (hiện trước khi job xong) — đây là [verify-screen] bằng tay.
|
|
33
|
+
3 thứ QC không soi trực tiếp được — raw DB row/checksum · HTTP status/body · queue-level job —
|
|
34
|
+
→ hạ xuống "quan sát qua product", hoặc tab Network của devtools (nhẹ), hoặc nhờ DEV kiểm hộ. Ghi rõ ở Note.
|
|
35
|
+
|
|
36
|
+
KHÔNG versioned: không template_version / migrations, ngoài scope /artifact-audit + /artifact-migrate.
|
|
37
|
+
Derived từ test-design.md → test-design đổi thì REGENERATE (archive cycle cũ trước nếu đã có Test Result).
|
|
38
|
+
|
|
39
|
+
Source of truth: test-design.md > E2E Test Cases.
|
|
40
|
+
- ID = TC-F{NNN}-{seq} inherit từ test-design (Covers FAC-F*). KHÔNG tạo ID mới.
|
|
41
|
+
- Coverage master = test-design.md > Traceability Matrix.
|
|
42
|
+
|
|
43
|
+
Test Result column là nơi DUY NHẤT QC cập nhật trạng thái thực thi (manual).
|
|
44
|
+
-->
|
|
45
|
+
|
|
46
|
+
# E2E Test Specification (Manual): {Feature Name}
|
|
47
|
+
|
|
48
|
+
**Feature**: {F-XXX} | **Owner**: {owner} | **Reviewer**: {reviewer} | **Status**: {status}
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 1. Context
|
|
53
|
+
|
|
54
|
+
| **Field** | **Detail** |
|
|
55
|
+
|---|---|
|
|
56
|
+
| **Feature Summary** | {2–3 câu từ frd.md Overview} |
|
|
57
|
+
| **FAC covered** | {FAC IDs — `FAC-F{NNN}-001`, ...} |
|
|
58
|
+
| **E2E Purpose** | Verify business outcome + integration point — không chỉ UI behavior |
|
|
59
|
+
| **Method** | manual — QC walk journey trên GUI, verify outcome bằng điều hướng qua sản phẩm |
|
|
60
|
+
| **NOT in E2E Scope** | Validation format/length đơn lẻ (→ test-exec-func-manual) · NFR (→ test-exec-nfr) · DM (→ test-exec-dm) |
|
|
61
|
+
| **Source** | [test-design.md](../../../main/feature/{F-XXX}-{slug}/test-design.md) — TC IDs (E2E Test Cases) + Traceability Matrix |
|
|
62
|
+
| **Alt harness** | [test-exec-e2e-auto.md](./test-exec-e2e-auto.md) — bản automation (team chọn 1, không chạy song song) |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 2. Environment & Setup
|
|
67
|
+
|
|
68
|
+
### 2.1 Test Account & Role Matrix
|
|
69
|
+
|
|
70
|
+
> QC login tay bằng các tài khoản dưới đây. Xóa role không dùng.
|
|
71
|
+
|
|
72
|
+
| **Role** | **Username** | **Password** | **Scope / Access** | **Dùng cho** |
|
|
73
|
+
|---|---|---|---|---|
|
|
74
|
+
| {Admin scope A} | {admin@test} | {TBD} | Full trong scope A | journey + integrity |
|
|
75
|
+
| {Out-of-scope user} | {other@test} | {TBD} | Ngoài scope A | guard / isolation |
|
|
76
|
+
|
|
77
|
+
### 2.2 Environment Tiers
|
|
78
|
+
|
|
79
|
+
| **Env** | **Purpose** | **Data** | **Notes** |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| dev | Primary E2E walk | Seeded DB | Môi trường chính |
|
|
82
|
+
| stag | Pre-release regression | Anonymized prod data | Gate trước deploy |
|
|
83
|
+
|
|
84
|
+
### 2.3 Seed Data Requirements
|
|
85
|
+
|
|
86
|
+
> Phải tồn tại trong DB trước khi walk. QC nhờ SE/DEV seed nếu không tạo được bằng GUI.
|
|
87
|
+
|
|
88
|
+
| **Seed Item** | **Description** | **Required by (TC)** |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| {seed-1} | {vd: Admin scope A full permission} | All scenarios |
|
|
91
|
+
| {seed-2} | {vd: Out-of-scope user} | `TC-F{NNN}-0XX` |
|
|
92
|
+
|
|
93
|
+
### 2.4 Platform & Viewport Matrix
|
|
94
|
+
|
|
95
|
+
| **Platform / View** | **Viewport** | **Priority** | **Scenarios** |
|
|
96
|
+
|---|---|---|---|
|
|
97
|
+
| Web Desktop | 1440px | P0 | All |
|
|
98
|
+
| Web Tablet | 768px | P1 | journey only |
|
|
99
|
+
| Web Mobile | 375px | P1 | journey only (nếu frd NFR có mobile) |
|
|
100
|
+
|
|
101
|
+
> frd.md không có mobile NFR → skip Tablet/Mobile.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## 3. Coverage
|
|
106
|
+
|
|
107
|
+
> FAC → E2E TC mapping. Mọi `TC-F*` phải xuất hiện ở test-design > Traceability Matrix. Planning only — execution result track ở §5 cột Test Result.
|
|
108
|
+
|
|
109
|
+
| **FAC ID** | **Shape** | **Business Outcome cần verify** | **E2E TC** | **Priority** |
|
|
110
|
+
|---|---|---|---|---|
|
|
111
|
+
| `FAC-F{NNN}-001` | journey | {vd "5 record persisted, hiện trên list"} | `TC-F{NNN}-040` | 🔴 P0 |
|
|
112
|
+
| `FAC-F{NNN}-002` | consistency | {vd "Message đồng nhất 3 màn"} | `TC-F{NNN}-041` | 🟡 P1 |
|
|
113
|
+
| `FAC-F{NNN}-003` | integrity | {vd "Xóa account → 0 order sót"} | `TC-F{NNN}-042` | 🔴 P0 |
|
|
114
|
+
|
|
115
|
+
**Coverage:** {n}/{total} FAC covered ({%}).
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## 4. Integration Points & Data Flow
|
|
120
|
+
|
|
121
|
+
> E2E verify **mọi integration boundary** trong business flow. QC không gọi API/DB trực tiếp → verify mỗi boundary bằng **quan sát qua sản phẩm**.
|
|
122
|
+
|
|
123
|
+
### 4.1 Integration Map
|
|
124
|
+
|
|
125
|
+
```mermaid
|
|
126
|
+
flowchart TD
|
|
127
|
+
U([User / Browser]) -->|thao tác| FE[Frontend]
|
|
128
|
+
FE -->|gửi request| API[Backend API]
|
|
129
|
+
API -->|lưu| DB[(Database)]
|
|
130
|
+
API -.->|async job| Q[Job Queue / Worker]
|
|
131
|
+
Q --> DB
|
|
132
|
+
API -.->|optional| EXT[External Service]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### 4.2 Integration Points — Manual Verification
|
|
136
|
+
|
|
137
|
+
| **ID** | **Integration Point** | **Trigger** | **Manual Verification (qua product)** | **Nếu hỏng** |
|
|
138
|
+
|---|---|---|---|---|
|
|
139
|
+
| `INT-01` | {request accepted} | {thao tác} | Màn chuyển loading→success **và** record xuất hiện ở bước sau (không chỉ toast) | báo lỗi đỏ / không đổi |
|
|
140
|
+
| `INT-02` | {async job completes} | background | Đợi tới khi element kết quả hiện (≤60s), refresh nếu cần | quá lâu → job failed |
|
|
141
|
+
| `INT-03` | {data persisted} | sau khi submit | **Rời màn hiện tại** → sang màn list → đếm/đọc data đúng | thiếu → data loss |
|
|
142
|
+
| `INT-04` | {scope guard} | login user out-scope | List rỗng / báo 403 / redirect | thấy data → security bug |
|
|
143
|
+
|
|
144
|
+
> 3 boundary QC không soi trực tiếp được (HTTP status, raw DB row, queue) → suy ra qua product như trên, hoặc dùng tab **Network** của devtools (nhẹ), hoặc nhờ DEV kiểm.
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## 5. Test Cases
|
|
149
|
+
|
|
150
|
+
> **TC ID:** inherit từ test-design (E2E Test Cases) — `TC-F{NNN}-{seq}`, stable. KHÔNG tạo ID mới.
|
|
151
|
+
>
|
|
152
|
+
> **Step prefix (manual):** `[goto]` mở trang/URL · `[action]` thao tác (click/nhập) · `[wait]` đợi async / refresh · `[verify-screen]` **rời sang màn khác xác nhận data thật** (= `[verify-db]` bằng tay) · `[check-network]` *(tùy chọn)* xem HTTP status ở devtools · `[teardown]` dọn data sau test.
|
|
153
|
+
>
|
|
154
|
+
> **Quy tắc `[verify-screen]`:** RỜI khỏi màn hiện tại → sang màn list/detail/admin → xác nhận data (count/status). Toast/success message KHÔNG đủ làm bằng chứng.
|
|
155
|
+
>
|
|
156
|
+
> **Test Result:** `—` (chưa chạy) | `✅ Pass` | `❌ Fail` | `⛔ Blocked` | `🔴 HOLD` | `N/A`.
|
|
157
|
+
|
|
158
|
+
### 5.1 Journey / Happy Path
|
|
159
|
+
|
|
160
|
+
> Walk complete business flow đến outcome cuối. ≥ 1 `[verify-screen]` mỗi scenario.
|
|
161
|
+
|
|
162
|
+
| **E2E TC** | **FAC** | **Role** | **Pre-Conditions** | **Manual Steps** | **Business Outcome (Expected)** | **Test Result** | **Priority** |
|
|
163
|
+
|---|---|---|---|---|---|---|---|
|
|
164
|
+
| `TC-F{NNN}-040` | `FAC-F{NNN}-001` | {role} | 1. {precondition}<br>2. {seed exists} | 1. [goto] Mở `{/path}`<br>2. [action] {thao tác + nhập data}<br>3. [wait] Đợi {kết quả} hiện<br>4. [action] Bấm Confirm<br>5. [verify-screen] Sang `{/list}` → đếm/đọc data đúng<br>6. [wait] Refresh → data còn nguyên | • {N} record persisted, hiện trên {màn} đúng status<br>• State persist qua refresh<br>• (Toast KHÔNG dùng làm bằng chứng) | — | 🔴 P0 |
|
|
165
|
+
|
|
166
|
+
### 5.2 Consistency (đa màn)
|
|
167
|
+
|
|
168
|
+
> So khớp UI/behavior nhiều màn. Mắt người so trực tiếp — không cần journey tuần tự.
|
|
169
|
+
|
|
170
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Manual Steps** | **Expected** | **Test Result** | **Priority** |
|
|
171
|
+
|---|---|---|---|---|---|---|
|
|
172
|
+
| `TC-F{NNN}-041` | `FAC-F{NNN}-002` | {N màn accessible} | 1. [action] trigger {behavior} ở màn A<br>2. [action] … màn B<br>3. [action] … màn C<br>4. [verify-screen] so 3 kết quả | • {behavior} identical (text/style/rule) across A/B/C | — | 🟡 P1 |
|
|
173
|
+
|
|
174
|
+
### 5.3 Integrity (bất biến liên story, không tuần tự)
|
|
175
|
+
|
|
176
|
+
> Assert business invariant sau khi kết hợp nhiều story. Verify trạng thái cuối + no side effect.
|
|
177
|
+
|
|
178
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Manual Steps** | **Expected (invariant)** | **Test Result** | **Priority** |
|
|
179
|
+
|---|---|---|---|---|---|---|
|
|
180
|
+
| `TC-F{NNN}-042` | `FAC-F{NNN}-003` | {baseline state} | 1. [verify-screen] ghi baseline count/state<br>2. [action] thao tác story X<br>3. [action] thao tác story Y<br>4. [verify-screen] kiểm invariant ở các màn liên quan | • {vd: xóa account → 0 order sót ở mọi module}<br>• Tổng/đối soát khớp | — | 🔴 P0 |
|
|
181
|
+
|
|
182
|
+
### 5.4 Negative / Guard *(nếu FAC có)*
|
|
183
|
+
|
|
184
|
+
> Verify guard tại boundary — confirm error **VÀ** no side effect.
|
|
185
|
+
> Pattern: `[verify-screen]` baseline → trigger error → `[action]` thấy error+guard → `[verify-screen]` count = baseline.
|
|
186
|
+
|
|
187
|
+
| **E2E TC** | **FAC** | **Pre-Conditions** | **Manual Steps** | **Expected** | **Test Result** | **Priority** |
|
|
188
|
+
|---|---|---|---|---|---|---|
|
|
189
|
+
| `TC-F{NNN}-0XX` | `FAC-F{NNN}-00N` | {invalid condition} | 1. [verify-screen] baseline N<br>2. [action] {invalid}<br>3. [action] thấy error + guard chặn<br>4. [verify-screen] count còn = N | • Error hiển thị<br>• **No new record** (count = N) | — | 🔴 P0 |
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## 6. Fixtures & Test Data
|
|
194
|
+
|
|
195
|
+
> Manual không có factory tự động — file / data chuẩn bị tay (hoặc nhờ SE) trước khi walk.
|
|
196
|
+
|
|
197
|
+
| **File / Data-set** | **Type** | **Content** | **Used by (TC)** |
|
|
198
|
+
|---|---|---|---|
|
|
199
|
+
| `{file-1}` | {Excel/JSON} | {vd: 5 valid rows, no dup} | `TC-F{NNN}-040` |
|
|
200
|
+
| `{file-2}` | {…} | {vd: header mismatch} | `TC-F{NNN}-0XX` |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 7. Execution
|
|
205
|
+
|
|
206
|
+
### 7.1 Entry & Exit Criteria
|
|
207
|
+
|
|
208
|
+
| | Criteria |
|
|
209
|
+
|---|---|
|
|
210
|
+
| **Entry** *(bắt đầu walk khi)* | frd.md approved · test-design.md exists · env running · seed data ready · account configured |
|
|
211
|
+
| **Exit** *(done khi)* | Mọi journey + integrity P0 pass (business outcome verified) · guard pass · không open Critical bug · Test Result updated đầy đủ |
|
|
212
|
+
| **Suspend** *(tạm dừng nếu)* | Bất kỳ P0 blocked · env down · integration boundary hỏng chặn walk |
|
|
213
|
+
|
|
214
|
+
### 7.2 Execution Order
|
|
215
|
+
|
|
216
|
+
> journey (P0) → integrity (P0) → guard → consistency. Bất kỳ P0 fail → STOP, raise bug.
|
|
217
|
+
|
|
218
|
+
### 7.3 Success Criteria
|
|
219
|
+
|
|
220
|
+
- [ ] Mọi journey scenario pass — business outcome verified (`[verify-screen]`, không chỉ toast)
|
|
221
|
+
- [ ] Mọi guard scenario pass — out-scope không thấy / không ghi được data
|
|
222
|
+
- [ ] Không integrity invariant nào vi phạm
|
|
223
|
+
- [ ] Test Result column updated đầy đủ
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## 8. Change Log
|
|
228
|
+
|
|
229
|
+
| **Date** | **Cycle** | **Changes** | **Author** |
|
|
230
|
+
|---|---|---|---|
|
|
231
|
+
| {YYYY-MM-DD} | {cycle/release} | Initial E2E manual spec (derive từ test-design.md E2E Test Cases) | {Author} |
|