@educa-corp/sdd-framework 0.9.3 → 0.9.4

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 (59) hide show
  1. package/bin/build.js +11 -0
  2. package/bin/qc-base-map.json +119 -49
  3. package/bin/self-check.js +30 -0
  4. package/core/FRAMEWORK_VERSION +1 -1
  5. package/core/commands/qc-analyze.md +6 -119
  6. package/core/commands/qc-design-test.md +123 -143
  7. package/core/commands/qc-plan.md +6 -119
  8. package/core/commands/qc-review.md +59 -125
  9. package/core/commands/qc-run-test.md +6 -119
  10. package/core/commands/setup-ai-first.md +5 -5
  11. package/core/commands/update-framework.md +1 -1
  12. package/core/commands/validate-traces.md +1 -1
  13. package/core/rules/workflow.md +1 -1
  14. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
  15. package/core/skills/qc/qa-analyst/spec-breakdown.md +2 -2
  16. package/core/skills/qc/qa-designer/api/auth-chain.md +155 -0
  17. package/core/skills/qc/qa-designer/api/auth-sequence.md +75 -0
  18. package/core/skills/qc/qa-designer/api/common-headers.md +61 -0
  19. package/core/skills/qc/qa-designer/api/crud-sequence.md +122 -0
  20. package/core/skills/qc/qa-designer/api/endpoint.md +231 -0
  21. package/core/skills/qc/qa-designer/api/http-status-codes.md +102 -0
  22. package/core/skills/qc/qa-designer/e2e/journey.md +13 -8
  23. package/core/skills/qc/qa-designer/exploratory/charter.md +2 -0
  24. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +7 -4
  25. package/core/skills/qc/qa-designer/functional/api.md +87 -18
  26. package/core/skills/qc/qa-designer/functional/gui-feature.md +12 -9
  27. package/core/skills/qc/qa-designer/functional/gui-screen.md +12 -10
  28. package/core/skills/qc/qa-designer/integration/api.md +12 -5
  29. package/core/skills/qc/qa-designer/integration/db.md +12 -6
  30. package/core/skills/qc/qa-designer/integration/gui.md +12 -5
  31. package/core/skills/qc/qa-designer/integration/kafka.md +12 -5
  32. package/core/skills/qc/qa-designer/non-functional.md +12 -5
  33. package/core/skills/qc/qa-designer/shared/action-keywords-glossary.md +91 -0
  34. package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +105 -0
  35. package/core/skills/qc/qa-designer/shared/implicit-scenarios.md +22 -0
  36. package/core/skills/qc/qa-designer/shared/precision-rules.md +198 -0
  37. package/core/skills/qc/qa-designer/shared/read-doc-gap-inputs.md +25 -0
  38. package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +93 -0
  39. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +243 -0
  40. package/core/skills/qc/qa-planner/risk-model.md +1 -1
  41. package/core/skills/qc/qa-reviewer/script/e2e.md +9 -1
  42. package/core/skills/qc/qa-reviewer/script/exploratory.md +9 -1
  43. package/core/skills/qc/qa-reviewer/script/functional.md +9 -1
  44. package/core/skills/qc/qa-reviewer/script/integration.md +9 -1
  45. package/core/skills/qc/qa-reviewer/script/non-functional.md +9 -1
  46. package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +26 -0
  47. package/core/skills/qc/qa-reviewer/shared/review-check-groups.md +207 -0
  48. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +228 -0
  49. package/core/skills/qc/qa-reviewer/test-case/e2e.md +71 -13
  50. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +53 -4
  51. package/core/skills/qc/qa-reviewer/test-case/functional.md +63 -15
  52. package/core/skills/qc/qa-reviewer/test-case/integration.md +64 -12
  53. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +72 -13
  54. package/core/skills/qc/qa-runner/e2e.md +1 -1
  55. package/docs/02-concepts/pipeline-steps/09-validate-traces.md +1 -1
  56. package/docs/04-reference/trace-schema.md +1 -1
  57. package/docs/explain/00-setup-ai-first.md +1 -1
  58. package/docs/plans/qc-implementation-log.md +145 -3
  59. package/package.json +1 -1
@@ -0,0 +1,75 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/api-testcase-designer/api/flows/auth-sequence.md
6
+ upstream_sha: 69d60c12fe6d641638132581cce1dc6c955354a6
7
+ ---
8
+ # Flow — Auth Sequence (login → token → authenticated calls)
9
+
10
+ Mô tả chuỗi gọi API liên tiếp liên quan đến xác thực.
11
+ Load file này khi thiết kế TC cần thực hiện đăng nhập trước khi gọi endpoint chính.
12
+
13
+ ---
14
+
15
+ ## Chuỗi 1 — Login lấy token + gọi 1 endpoint
16
+
17
+ ```
18
+ POST /auth/login → nhận access_token → <METHOD> <protected_endpoint>
19
+ ```
20
+
21
+ **Khi dùng:** TC cần tài khoản đăng nhập trước khi thao tác (tạo/sửa/xóa resource).
22
+
23
+ **Điểm verify:**
24
+ 1. Sau login: HTTP 200, `body.access_token` không rỗng.
25
+ 2. Sau gọi endpoint: status code kỳ vọng, body đúng schema.
26
+
27
+ **TC pattern:** xem `templates/auth-chain.md` (TC AUTH-001).
28
+
29
+ ---
30
+
31
+ ## Chuỗi 2 — Token refresh
32
+
33
+ ```
34
+ POST /auth/login → nhận access_token + refresh_token
35
+ → (sau khi access_token hết hạn)
36
+ → POST /auth/refresh → nhận access_token mới
37
+ → <METHOD> <protected_endpoint> → thành công
38
+ ```
39
+
40
+ **Khi dùng:** API có cơ chế refresh token (nếu plan đề cập).
41
+
42
+ **Điểm verify:**
43
+ 1. Login: nhận cả `access_token` và `refresh_token`.
44
+ 2. Gọi refresh: HTTP 200, `body.access_token` khác token cũ.
45
+ 3. Gọi endpoint bằng token mới: thành công.
46
+
47
+ **TC negative liên quan:**
48
+ - Dùng refresh_token hết hạn → 401.
49
+ - Dùng refresh_token đã dùng lần trước (replay) → 401.
50
+
51
+ ---
52
+
53
+ ## Chuỗi 3 — Multi-role: cùng endpoint, khác role, khác kết quả
54
+
55
+ ```
56
+ POST /auth/login (admin) → token_admin → <METHOD> <endpoint> → 200/201
57
+ POST /auth/login (teacher) → token_teacher → <METHOD> <endpoint> → 200 hoặc 403
58
+ POST /auth/login (student) → token_student → <METHOD> <endpoint> → 403
59
+ ```
60
+
61
+ **Khi dùng:** TC RBAC — verify phân quyền theo role.
62
+
63
+ **Điểm verify:** mỗi role cần TC riêng; Expected ghi rõ mã cho từng role.
64
+
65
+ **TC pattern:** Decision Table (role × endpoint → expected code).
66
+
67
+ ---
68
+
69
+ ## Ghi chú thiết kế TC
70
+
71
+ - **Test isolation:** mỗi TC tự gọi login để lấy token riêng. Không dùng token từ TC khác.
72
+ - **Token fixture (Python):** nếu nhiều TC cùng role, dùng `conftest.py` fixture
73
+ `logged_in_token_<role>` (session scope) để tránh login lặp lại khi chạy test.
74
+ - **Expired token test:** tạo token expired sẵn trong `test_data/tokens.json` thay vì
75
+ đợi token tự hết hạn trong test.
@@ -0,0 +1,61 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/api-testcase-designer/api/references/common-headers.md
6
+ upstream_sha: 74f10a36bec7b40f4d9de2d0928798cb6fad0c2c
7
+ ---
8
+ # Bảng tra cứu — Headers chuẩn
9
+
10
+ Dùng khi điền mục **Test Data > Headers** trong TC API.
11
+ Chỉ ghi header thực sự cần thiết cho TC đó; không copy toàn bộ bảng.
12
+
13
+ ---
14
+
15
+ ## Request headers thường dùng
16
+
17
+ | Header | Giá trị điển hình | Khi nào cần |
18
+ |---|---|---|
19
+ | `Authorization` | `Bearer <access_token>` | Mọi endpoint yêu cầu auth |
20
+ | `Content-Type` | `application/json` | POST / PUT có body JSON |
21
+ | `Content-Type` | `multipart/form-data` | Upload file |
22
+ | `Accept` | `application/json` | Luôn ghi khi API có thể trả nhiều format |
23
+ | `Accept-Language` | `vi` hoặc `en` | Khi test response message theo ngôn ngữ |
24
+ | `X-Request-ID` | `<uuid>` | Nếu API yêu cầu idempotency key |
25
+ | `X-Tenant-ID` | `<tenant_id>` | Nếu LMS hỗ trợ multi-tenant |
26
+
27
+ ---
28
+
29
+ ## Response headers cần verify (ghi vào `[Verify]` step nếu TC liên quan)
30
+
31
+ | Header | Verify khi |
32
+ |---|---|
33
+ | `Content-Type: application/json` | Mọi response trả JSON |
34
+ | `Location: <url>` | POST 201 Created — verify URL tạo mới |
35
+ | `Retry-After: <seconds>` | TC rate limit (429) |
36
+ | `X-RateLimit-Remaining` | TC rate limit — verify còn bao nhiêu request |
37
+
38
+ ---
39
+
40
+ ## TC Negative liên quan header
41
+
42
+ | Kịch bản | Header điều chỉnh | Expected |
43
+ |---|---|---|
44
+ | Không có Authorization | Bỏ header `Authorization` | 401 |
45
+ | Token sai format | `Authorization: InvalidToken abc` | 401 |
46
+ | Content-Type sai | `Content-Type: text/plain` (khi API cần JSON) | 400 hoặc 415 |
47
+ | Token đúng nhưng sai role | Token của role không được phép | 403 |
48
+
49
+ ---
50
+
51
+ ## Quy ước ghi trong Test Data
52
+
53
+ ```
54
+ Headers:
55
+ - Authorization: Bearer <valid_token_admin>
56
+ - Content-Type: application/json
57
+ ```
58
+
59
+ - Dùng placeholder có tên rõ ràng: `<valid_token_admin>`, `<valid_token_teacher>`,
60
+ `<expired_token>`, `<token_wrong_role>` — không dùng `<token>` chung chung.
61
+ - Không ghi header không liên quan đến TC (vd `User-Agent`, `Host`).
@@ -0,0 +1,122 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/api-testcase-designer/api/flows/crud-sequence.md
6
+ upstream_sha: 65bf214d9f9beabe3c40b8697ba7c058adfd8bb5
7
+ ---
8
+ # Flow — CRUD Sequence (create → read → update → delete)
9
+
10
+ Mô tả các chuỗi gọi API CRUD phụ thuộc nhau.
11
+ Load file này khi TC cần tạo resource trước khi thao tác sửa/xóa/đọc chi tiết.
12
+
13
+ ---
14
+
15
+ ## Chuỗi 1 — Create → Read
16
+
17
+ ```
18
+ POST <resource> → HTTP 201, nhận body.id
19
+ → GET <resource>/{id} → HTTP 200, body đúng data đã tạo
20
+ ```
21
+
22
+ **Khi dùng:** Verify GET trả đúng data sau khi tạo; kiểm tra data persistence.
23
+
24
+ **Điểm verify:**
25
+ 1. POST: HTTP 201, `body.id` tồn tại và không rỗng.
26
+ 2. GET bằng `id` từ bước 1: HTTP 200; các field chính (name, status…) = giá trị đã gửi lúc POST.
27
+
28
+ **TC pattern:**
29
+ - 1 TC happy cho chuỗi (P0).
30
+ - Tách TC riêng nếu cần test GET với ID không tồn tại (P1).
31
+
32
+ ---
33
+
34
+ ## Chuỗi 2 — Create → Update → Read
35
+
36
+ ```
37
+ POST <resource> → HTTP 201, nhận id
38
+ → PUT <resource>/{id} → HTTP 200/204
39
+ → GET <resource>/{id} → HTTP 200, body = data đã update
40
+ ```
41
+
42
+ **Khi dùng:** Verify update áp dụng đúng, không mất dữ liệu không liên quan.
43
+
44
+ **Điểm verify:**
45
+ 1. POST: `body.id` tồn tại.
46
+ 2. PUT: HTTP 200 hoặc 204 (theo contract).
47
+ 3. GET sau PUT: field đã update = giá trị mới; field không update = giá trị cũ (unchanged).
48
+
49
+ **TC negative liên quan:**
50
+ - PUT với ID không tồn tại → 404.
51
+ - PUT với body vi phạm validation → 400.
52
+ - PUT sau khi resource đã ở trạng thái không cho sửa (vd đã publish) → 409/422.
53
+
54
+ ---
55
+
56
+ ## Chuỗi 3 — Create → Delete → Read
57
+
58
+ ```
59
+ POST <resource> → HTTP 201, nhận id
60
+ → DELETE <resource>/{id} → HTTP 200/204
61
+ → GET <resource>/{id} → HTTP 404
62
+ ```
63
+
64
+ **Khi dùng:** Verify xóa thực sự xóa resource (không còn truy cập được).
65
+
66
+ **Điểm verify:**
67
+ 1. POST: HTTP 201, `body.id` tồn tại.
68
+ 2. DELETE: HTTP 200 hoặc 204.
69
+ 3. GET sau DELETE: HTTP 404.
70
+
71
+ **TC negative liên quan:**
72
+ - DELETE với ID không tồn tại → 404.
73
+ - DELETE resource đang được tham chiếu (foreign key) → 409/422 (nếu API có bảo vệ).
74
+
75
+ ---
76
+
77
+ ## Chuỗi 4 — List + Pagination
78
+
79
+ ```
80
+ POST <resource> x N lần → tạo N bản ghi
81
+ → GET <resource>?page=1&limit=<L> → trả đúng L bản ghi + pagination
82
+ → GET <resource>?page=2&limit=<L> → trang tiếp theo đúng
83
+ ```
84
+
85
+ **Khi dùng:** TC pagination — verify tổng bản ghi, số trang, dữ liệu mỗi trang.
86
+
87
+ **Điểm verify:**
88
+ 1. `body.total` = N (tổng bản ghi đã tạo).
89
+ 2. `body.data.length` = L (số bản ghi trên trang).
90
+ 3. Trang 2: `body.data` không trùng trang 1.
91
+
92
+ ---
93
+
94
+ ## Chuỗi 5 — Dependent resource (parent → child)
95
+
96
+ ```
97
+ POST <parent> → HTTP 201, nhận parent_id
98
+ → POST <child>?parentId=<parent_id> → HTTP 201, nhận child_id
99
+ → GET <parent>/{parent_id} → body.children chứa child_id
100
+ ```
101
+
102
+ **Khi dùng:** Resource con phụ thuộc resource cha (vd: buổi học phụ thuộc lớp học).
103
+
104
+ **Điểm verify:**
105
+ 1. POST parent: `body.id` tồn tại.
106
+ 2. POST child với `parentId`: HTTP 201.
107
+ 3. GET parent: `body.children` (hoặc trường tương đương) chứa child đã tạo.
108
+
109
+ **TC negative liên quan:**
110
+ - POST child với `parentId` không tồn tại → 404.
111
+ - POST child với parent đã bị xóa/đóng → 422/409.
112
+
113
+ ---
114
+
115
+ ## Ghi chú thiết kế TC
116
+
117
+ - **Cleanup:** Mỗi TC trong chuỗi CRUD cần xóa data đã tạo ở cuối (teardown).
118
+ Ghi rõ bước cleanup trong Test Steps: `**[Action]** Xóa resource id=<id> (cleanup)`.
119
+ - **ID dependency:** Khi TC sau cần ID từ TC trước, ghi rõ trong Preconditions:
120
+ `Đã có <resource> với id=<test_id> trong DB`.
121
+ - **Không nối TC thành chuỗi:** Mỗi TC vẫn độc lập; nếu cần data sẵn → tạo trong
122
+ Preconditions/fixture, không phụ thuộc TC khác đã chạy trước.
@@ -0,0 +1,231 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/api-testcase-designer/api/templates/endpoint.md
6
+ upstream_sha: 7b38edd94e5efd37ff561f53cff92adedabaff7f
7
+ ---
8
+
9
+ > **VIẾT LẠI, không copy** *(B12)*. Bản upstream ra đời **trước** luật ATOMIC (đội QC chốt
10
+ > 2026-07-09) nên mỗi mẫu của nó gộp nhiều kết cục vào một `**Expected:**` nối bằng `;`, và
11
+ > dùng hệ mã `API-<FEATURE>-001` khác với `TC_<FEATURE>_NNN` mà phần còn lại dùng.
12
+ >
13
+ > Port nguyên là **dạy AI làm ngược luật vừa chốt** — mẫu cụ thể luôn thắng luật trừu tượng.
14
+ > Nội dung phủ (5 nhóm ca) giữ nguyên; cấu trúc TC theo `shared/tc-metadata-format.md`.
15
+
16
+ # Khuôn TC — một endpoint đơn
17
+
18
+ Mẫu khi viết TC cho 1 endpoint (GET / POST / PUT / DELETE). Thay mọi `<placeholder>` bằng giá
19
+ trị thật từ `TEST_PLAN.md` + hợp đồng API §4 của tech-doc gộp.
20
+
21
+ Phủ **5 nhóm ca**: happy · validation · auth thiếu token · auth sai quyền · not found.
22
+ Mã lỗi tra ở `http-status-codes.md`; header tra ở `common-headers.md`.
23
+
24
+ ---
25
+
26
+ ## Nhóm ca 1 — Happy case
27
+
28
+ ⚠️ **Một request thành công sinh RA NHIỀU kết cục → nhiều TC độc lập.** Upstream gộp
29
+ `HTTP 201; body.id = x; bản ghi có trong DB` vào một dòng — đó là **ba** kết cục:
30
+
31
+ ### TC_<FEATURE>_001 — <METHOD> <path> trả về <success_code>
32
+
33
+ - **Title:** <METHOD> <path> với request hợp lệ trả về <success_code>
34
+ - **Feature:** <TICKET-ID> — <Tên feature>
35
+ - **Priority:** P0
36
+ - **Status:** Draft
37
+ - **Author:** AI
38
+ - **Tags:** api, happy-path, <feature-tag>
39
+ - **Trace:** BR-xx
40
+ - **@trace.verifies:** {UC-ID}-SC{N}
41
+
42
+ #### Preconditions
43
+ - Tài khoản role `<role>` đã có token hợp lệ.
44
+ - <Dữ liệu nền cần có, vd "đã tồn tại course id = 123">
45
+
46
+ #### Test Data
47
+ - Method: <GET|POST|PUT|DELETE>
48
+ - Path: `<path>`
49
+ - Headers:
50
+ - Authorization: Bearer `<valid_token_<role>>`
51
+ - Content-Type: application/json
52
+ - Body:
53
+ ```json
54
+ { "<field1>": "<valid_value>", "<field2>": "<valid_value>" }
55
+ ```
56
+
57
+ #### Test Steps
58
+ 1. **[Action]** Gửi `<METHOD> <path>` với headers và body trên.
59
+ 2. **[Verify]** Đọc status code của response.
60
+
61
+ #### Expected Result
62
+ - HTTP `<success_code>`
63
+
64
+ #### Teardown
65
+ - `DELETE <base_path>/{body.id}` — xoá bản ghi vừa tạo *(chỉ khi TC này tạo bản ghi thật)*
66
+
67
+ ### TC_<FEATURE>_002 — body response chứa `<key_field>` đúng
68
+
69
+ - **Title:** <METHOD> <path> — body response có `<key_field>` = `<expected_value>`
70
+ - **Feature:** <TICKET-ID> — <Tên feature>
71
+ - **Priority:** P0
72
+ - **Status:** Draft
73
+ - **Author:** AI
74
+ - **Tags:** api, happy-path, <feature-tag>
75
+ - **Trace:** BR-xx
76
+ - **@trace.verifies:** {UC-ID}-SC{N}
77
+
78
+ #### Preconditions
79
+ - *(copy nguyên từ TC_001 — mỗi TC tách là testcase ĐỘC LẬP, giữ FULL steps)*
80
+
81
+ #### Test Data
82
+ - *(copy nguyên từ TC_001)*
83
+
84
+ #### Test Steps
85
+ 1. **[Action]** Gửi `<METHOD> <path>` với headers và body trên.
86
+ 2. **[Verify]** Đọc trường `<key_field>` trong body response.
87
+
88
+ #### Expected Result
89
+ - `body.<key_field>` = `<expected_value>`
90
+
91
+ #### Teardown
92
+ - `DELETE <base_path>/{body.id}` *(chỉ khi TC này tạo bản ghi thật)*
93
+
94
+ ### TC_<FEATURE>_003 — side-effect được ghi
95
+
96
+ *Chỉ viết khi có side-effect cần verify. Nếu side-effect nằm ở DB/Kafka, TC này thuộc
97
+ **nhóm Integration API/DB/Kafka**, không thuộc nhóm Endpoint.*
98
+
99
+ - **Title:** <METHOD> <path> — bản ghi xuất hiện trong `<bảng>` với id = body.id
100
+ - **Priority:** P0
101
+ - **Tags:** api, integration, <feature-tag>
102
+ - **Trace:** BR-xx
103
+
104
+ #### Expected Result
105
+ - `<bảng>.id` = `body.id` AND `<bảng>.<cột>` = `<giá trị>`
106
+
107
+ > ✅ Bullet compound `A AND B` ở đây **hợp lệ**: cả hai vế nói về **cùng một** kết cục
108
+ > ("bản ghi đã được ghi đúng"). Còn `HTTP 201; body.id = x` là **hai** kết cục — phải tách.
109
+ > Phép soi nhanh: bullet nối bằng `;`, hoặc nối một khẳng định với một phủ định, là 2 kết cục.
110
+
111
+ ---
112
+
113
+ ## Nhóm ca 2 — Validation: field bắt buộc để trống
114
+
115
+ ### TC_<FEATURE>_004 — thiếu `<required_field>` trả về 400
116
+
117
+ - **Title:** POST <path> — thiếu `<required_field>` trả về 400
118
+ - **Priority:** P1
119
+ - **Status:** Draft
120
+ - **Author:** AI
121
+ - **Tags:** api, negative, validation, ep
122
+ - **Trace:** BR-xx
123
+
124
+ #### Test Data
125
+ - Method: POST
126
+ - Path: `<path>`
127
+ - Headers:
128
+ - Authorization: Bearer `<valid_token_<role>>`
129
+ - Content-Type: application/json
130
+ - Body: `{ }` — bỏ hẳn `<required_field>`
131
+
132
+ #### Test Steps
133
+ 1. **[Action]** Gửi POST không có `<required_field>`.
134
+ 2. **[Verify]** Đọc status code.
135
+
136
+ #### Expected Result
137
+ - HTTP 400
138
+
139
+ **Thông báo lỗi là một TC RIÊNG** — nội dung thông báo là oracle khác với mã trạng thái:
140
+
141
+ ### TC_<FEATURE>_005 — thông báo lỗi nêu đúng field thiếu
142
+
143
+ #### Expected Result
144
+ - `body.message` contains `"<chuỗi nguyên văn từ PRD/tech-doc>"`
145
+
146
+ > ⚠️ Chuỗi này phải **có thật** trong PRD hoặc tech-doc của **chính feature này**. Chưa chốt →
147
+ > để trống + gắn `🚫 Block: [GAP-UC{N}-{nnn}](../DOC_GAP.md)`, **đừng bịa oracle**.
148
+
149
+ *Mỗi field bắt buộc là một cặp TC như trên. Field có ràng buộc độ dài/khoảng giá trị → thêm TC
150
+ BVA riêng, số giá trị biên tra ở `../shared/precision-rules.md` §7.*
151
+
152
+ ---
153
+
154
+ ## Nhóm ca 3 — Auth: không có token
155
+
156
+ ### TC_<FEATURE>_006 — thiếu Authorization header trả về 401
157
+
158
+ - **Priority:** P0
159
+ - **Tags:** api, negative, auth, security
160
+ - **Trace:** BR-xx
161
+
162
+ #### Test Data
163
+ - Method: <METHOD>
164
+ - Path: `<path>`
165
+ - Headers: Content-Type: application/json — **bỏ hẳn** `Authorization`
166
+
167
+ #### Test Steps
168
+ 1. **[Action]** Gửi `<METHOD> <path>` không kèm header `Authorization`.
169
+ 2. **[Verify]** Đọc status code.
170
+
171
+ #### Expected Result
172
+ - HTTP 401
173
+
174
+ *Biến thể theo `common-headers.md` §"TC Negative liên quan header": token sai định dạng → 401 ·
175
+ `Content-Type` sai → 400 hoặc 415. Mỗi cái một TC.*
176
+
177
+ ---
178
+
179
+ ## Nhóm ca 4 — Auth: đúng token, sai quyền
180
+
181
+ ### TC_<FEATURE>_007 — token role `<wrong_role>` trả về 403
182
+
183
+ - **Priority:** P0
184
+ - **Tags:** api, negative, auth, security
185
+ - **Trace:** BR-xx
186
+
187
+ #### Test Data
188
+ - Headers: Authorization: Bearer `<valid_token_<wrong_role>>`
189
+
190
+ #### Test Steps
191
+ 1. **[Action]** Gửi `<METHOD> <path>` bằng token của role không được phép.
192
+ 2. **[Verify]** Đọc status code.
193
+
194
+ #### Expected Result
195
+ - HTTP 403
196
+
197
+ > **401 vs 403 là hai chuyện khác nhau** — 401 = chưa xác thực được anh là ai; 403 = biết anh
198
+ > là ai nhưng anh không được phép. Trộn hai cái là bỏ mất một lớp bảo mật khỏi phạm vi test.
199
+
200
+ ---
201
+
202
+ ## Nhóm ca 5 — Not found
203
+
204
+ ### TC_<FEATURE>_008 — ID không tồn tại trả về 404
205
+
206
+ - **Priority:** P1
207
+ - **Tags:** api, negative, not-found
208
+ - **Trace:** BR-xx
209
+
210
+ #### Test Data
211
+ - Method: <GET|PUT|DELETE>
212
+ - Path: `<base_path>/<nonexistent_id>` (vd `/api/v1/courses/999999`)
213
+ - Headers: Authorization: Bearer `<valid_token_<role>>`
214
+
215
+ #### Test Steps
216
+ 1. **[Action]** Gửi `<METHOD>` với ID chắc chắn không tồn tại trong hệ thống.
217
+ 2. **[Verify]** Đọc status code.
218
+
219
+ #### Expected Result
220
+ - HTTP 404
221
+
222
+ ---
223
+
224
+ ## Nhắc lại ba luật hay bị bỏ
225
+
226
+ 1. **Placeholder có tên rõ nghĩa** — `<valid_token_admin>`, `<expired_token>`,
227
+ `<token_wrong_role>`; **không** dùng `<token>` chung chung *(`common-headers.md` §Quy ước)*.
228
+ 2. **`#### Teardown` là section riêng, KHÔNG phải bullet của Expected Result.** TC tạo bản ghi
229
+ thật thì bắt buộc có; TC chỉ GET hoặc chỉ cấu hình mock thì **không cần**.
230
+ 3. **Mọi TC tách vẫn giữ FULL Test Steps** — lặp đủ bước để tới trạng thái assert. Không cắt
231
+ bước theo từng bullet, không đánh `(1/N)`, không hậu tố `001a`/`001b`.
@@ -0,0 +1,102 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-04
4
+ ported_from: ui-automation-testing
5
+ upstream_path: skills/qa-tc-designer/api-testcase-designer/api/references/http-status-codes.md
6
+ upstream_sha: a82baa99350f63955245764a6aa57c9dca6d055f
7
+ ---
8
+ # Bảng tra cứu — HTTP Status Codes
9
+
10
+ Dùng để điền chính xác mã lỗi vào cột Expected của TC API.
11
+ Tra theo nhóm (2xx/4xx/5xx) hoặc theo tình huống.
12
+
13
+ ---
14
+
15
+ ## 2xx — Thành công
16
+
17
+ | Mã | Tên | Dùng khi | Expected điển hình |
18
+ |---|---|---|---|
19
+ | 200 | OK | GET, PUT thành công; login | Body chứa data/resource |
20
+ | 201 | Created | POST tạo bản ghi mới | Body chứa `id` + resource mới |
21
+ | 204 | No Content | DELETE thành công; PUT không trả body | Body rỗng |
22
+
23
+ ---
24
+
25
+ ## 4xx — Lỗi phía client
26
+
27
+ | Mã | Tên | Dùng khi | Expected điển hình |
28
+ |---|---|---|---|
29
+ | 400 | Bad Request | Body/params sai format, thiếu field bắt buộc, giá trị không hợp lệ | `body.message` hoặc `body.errors` mô tả field lỗi |
30
+ | 401 | Unauthorized | Không có token, token hết hạn, token sai | `body.message` = "Unauthorized" hoặc "Token invalid/expired" |
31
+ | 403 | Forbidden | Token hợp lệ nhưng không đủ quyền (sai role) | `body.message` = "Forbidden" hoặc "Access denied" |
32
+ | 404 | Not Found | Resource ID không tồn tại | `body.message` = "Not found" |
33
+ | 409 | Conflict | Tạo trùng bản ghi (unique constraint) | `body.message` mô tả field trùng |
34
+ | 422 | Unprocessable Entity | Business rule validation (vd: ngày end < ngày start) | `body.errors` liệt kê vi phạm |
35
+ | 429 | Too Many Requests | Vượt rate limit | `Retry-After` header; body thông báo limit |
36
+
37
+ ---
38
+
39
+ ## 5xx — Lỗi phía server (không test chủ động; ghi vào TC edge nếu plan đề cập)
40
+
41
+ | Mã | Tên | Ghi chú |
42
+ |---|---|---|
43
+ | 500 | Internal Server Error | Không nên trigger trong test bình thường; ghi vào TC nếu plan có scenario |
44
+ | 503 | Service Unavailable | Chỉ test trong integration/availability scope |
45
+
46
+ ---
47
+
48
+ ## Mapping tình huống → mã (LMS Edupia)
49
+
50
+ | Tình huống | Mã kỳ vọng | Ghi chú |
51
+ |---|---|---|
52
+ | Login đúng | 200 | Body có `access_token` |
53
+ | Login sai password | 401 hoặc 400 | Xác nhận lại với dev |
54
+ | Tạo mới thành công | 201 | Body có `id` |
55
+ | Lấy danh sách | 200 | Body có `data[]` + `pagination` |
56
+ | Lấy 1 record hợp lệ | 200 | Body có đầy đủ fields |
57
+ | Xóa thành công | 200 hoặc 204 | Xác nhận lại với dev |
58
+ | Field bắt buộc để trống | 400 | `body.errors` có field name |
59
+ | Vượt độ dài tối đa | 400 | `body.errors` có field name + giới hạn |
60
+ | Format sai (email/phone) | 400 | `body.errors` mô tả format |
61
+ | Token không có | 401 | — |
62
+ | Token hết hạn | 401 | — |
63
+ | Role không đủ quyền | 403 | — |
64
+ | ID không tồn tại | 404 | — |
65
+ | Tên/code trùng | 409 | Xác nhận field unique với dev |
66
+ | Ngày end trước ngày start | 422 | Business rule validation |
67
+
68
+ ---
69
+
70
+ ## Cấu trúc body lỗi chuẩn (tham khảo)
71
+
72
+ ```json
73
+ // 400 / 422 — validation error
74
+ {
75
+ "statusCode": 400,
76
+ "message": "Validation failed",
77
+ "errors": [
78
+ { "field": "name", "message": "Trường này là bắt buộc" },
79
+ { "field": "startDate", "message": "Ngày bắt đầu không được để trống" }
80
+ ]
81
+ }
82
+
83
+ // 401 — unauthorized
84
+ {
85
+ "statusCode": 401,
86
+ "message": "Unauthorized"
87
+ }
88
+
89
+ // 403 — forbidden
90
+ {
91
+ "statusCode": 403,
92
+ "message": "Forbidden resource"
93
+ }
94
+
95
+ // 404 — not found
96
+ {
97
+ "statusCode": 404,
98
+ "message": "Resource not found"
99
+ }
100
+ ```
101
+
102
+ > Cấu trúc thực tế có thể khác — xác nhận với dev/API spec trước khi điền vào TC.
@@ -17,11 +17,14 @@ Skill **tự chứa** để viết TC end-to-end: hành trình đầu→cuối x
17
17
 
18
18
  ---
19
19
 
20
- ## Format file TC (bắt buộc)
21
- - Metadata **list**: Title · Feature · Priority · Status(Draft) · Author(AI) · Tags · **Trace** `[BR-xx](REQUIREMENT_ANALYSIS.md#3-business-rules)` (không có → `⚠️ Chưa có Business Rule`) · **🚫 Block** `[GAP-xx](DOC_GAP.md)`.
22
- - **Test Data** dạng list (tài khoản/role, dữ liệu lớp/buổi…) · **Steps** `[Action]`/`[Verify]` xuyên các màn ·
23
- **Expected** 1 bullet = chuỗi verify point (tạo thành công, đúng, định tuyến đúng, đồng bộ đúng, hiển thị danh sách).
24
- - ID journey `E2E-<FEATURE>-NN` · cuối file: Trace matrix + bảng TC block · bỏ nội dung gạch ngang.
20
+ ## Format file TC
21
+
22
+ > **Nạp `{paths.qc_skills_dir}/qa-designer/shared/tc-metadata-format.md`** khuôn TC, luật
23
+ > ATOMIC (1 kết cục = 1 TC), cách phân nhóm, hai file `.Test.md`, Trace + `@trace.verifies`,
24
+ > `🚫 Block`, dòng `Test-ID attribute`. **Không lặp lại luật format đây.**
25
+ >
26
+ > Khi viết Expected Result / Test Data: nạp thêm `shared/precision-rules.md` (cấm từ mơ hồ,
27
+ > đơn vị, toán tử) + `shared/action-keywords-glossary.md` (một hành động một từ).
25
28
 
26
29
  ## Kỹ thuật áp dụng
27
30
  - **Use Case/Scenario:** mỗi journey = main + alternate + exception flow.
@@ -34,8 +37,10 @@ Lấy danh sách journey + trục bao phủ + verify points từ TEST_PLAN · m
34
37
 
35
38
  ## Phase 2 — Write
36
39
  Mỗi journey → 1 TC bám Format; Expected = chuỗi verify point; chuẩn bị tiền điều kiện & cleanup, mỗi journey độc lập.
37
- **Journey phụ thuộc gap vẫn viết + 🚫 Block: GAP-xx**, định tuyến ghi "dự kiến theo BR". Trace BR.
40
+ **Journey phụ thuộc gap vẫn viết + 🚫 Block: [GAP-UC{N}-{nnn}]**, định tuyến ghi "dự kiến theo BR". Trace BR.
38
41
 
39
42
  ## Output
40
- File TC e2e (hoặc nhóm E2E trong file feature) trong `{qc_artifact_dir}test-cases/`.
41
- In bảng `E2E-ID | Journey | Pri | Trace | Block` + bảng TC block. Bàn giao `qa-reviewer`.
43
+
44
+ Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` **Nhóm 6 E2E**. Mỗi journey một TC; tiền điều kiện · kết quả/định tuyến kỳ vọng · BR · phụ thuộc gap · priority ghi dạng trường danh sách.
45
+
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.
@@ -66,3 +66,5 @@ Sinh 10-15 câu hỏi cho dev/BA (assumptions, edge case, error handling, securi
66
66
  Charter files: {paths.qc_dir}/exploratory/charters/<feature>_01.md, _02.md...
67
67
  Ideas file: {paths.qc_dir}/exploratory/ideas/<feature>.md
68
68
  Bảng tổng kết: STT | Charter | Tour | Risk | Time-box
69
+
70
+ *(Charter KHÔNG phải file TC — luật "không bảng" chỉ áp cho `*.Test.md`. Charter chuyển thành TC ở `explore-to-functional.md`, lúc đó mới theo luật đó.)*
@@ -32,12 +32,15 @@ So requirement vs draft: requirement chưa phủ → thêm TC · TC sai logic
32
32
  chỉnh Priority theo business. Không có requirement → giữ draft Phase 2.
33
33
 
34
34
  ## Phase 4 — Convert to Functional (format chuẩn)
35
- Chuyển draft → TC chính thức bám **format file `TC_<FEATURE>.md`**:
35
+ Chuyển draft → TC chính thức bám **format file `TC_<FEATURE>.Test.md`**:
36
36
  - Metadata **list**: Title · Feature · Priority(P0/P1/P2) · Status(Draft) · Author(AI) · Tags ·
37
- **Trace** `[BR-xx](REQUIREMENT_ANALYSIS.md#3-business-rules)` (không có BR → `⚠️ Chưa có Business Rule`) · **🚫 Block** `[GAP-xx]` nếu chặn.
37
+ **Trace** `[BR-xx](../REQUIREMENT_ANALYSIS.md#3-business-rules)` (không có BR → `⚠️ Chưa có Business Rule`) · **🚫 Block** `[GAP-UC{N}-{nnn}]` nếu chặn.
38
38
  - **Test Data** dạng list · **Steps** `[Action]`/`[Verify]` · **Expected** 1 bullet cụ thể.
39
39
  - Phân nhóm GUI/Functional · cuối file: Trace matrix + bảng TC block · bỏ nội dung gạch ngang.
40
- - Đặt file `{qc_artifact_dir}test-cases/TC_<FEATURE>.md`.
40
+ - Đặt file `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` (nhóm 3 Functional).
41
41
 
42
42
  ## Output
43
- File TC functional + bảng `TC_ID | Title | Priority | Technique | Trace`. Bàn giao `qa-reviewer`.
43
+
44
+ Ghi TC đã chuyển thành functional vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 3 Functional**.
45
+
46
+ **Dạng danh sách, KHÔNG bảng** — file TC không được có ký tự `|` (`shared/tc-metadata-format.md` §Nguyên tắc format file). Cuối file: Trace matrix + danh sách TC bị block, cũng dạng danh sách. Bàn giao `/qc-review`.