@educa-corp/sdd-framework 0.9.6 → 0.9.8

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 (147) hide show
  1. package/bin/lint-trace.js +4 -4
  2. package/bin/qc-base-map.json +13 -11
  3. package/bin/self-check.js +497 -16
  4. package/bin/trace-schema.json +3226 -2656
  5. package/core/FRAMEWORK_VERSION +1 -1
  6. package/core/commands/amend-prd.md +7 -1
  7. package/core/commands/debug.md +8 -2
  8. package/core/commands/define-product.md +38 -1
  9. package/core/commands/dev-gen-test.md +9 -3
  10. package/core/commands/dev-run-test.md +8 -2
  11. package/core/commands/dev-smoke-test.md +7 -1
  12. package/core/commands/extend-prd.md +7 -1
  13. package/core/commands/fix-bug.md +11 -5
  14. package/core/commands/generate-architecture.md +9 -1
  15. package/core/commands/generate-bdd.md +45 -5
  16. package/core/commands/generate-code.md +43 -4
  17. package/core/commands/generate-design-spec.md +7 -1
  18. package/core/commands/generate-prd.md +9 -1
  19. package/core/commands/generate-spec-manifest.md +7 -1
  20. package/core/commands/generate-tech-docs.md +41 -1
  21. package/core/commands/learn.md +7 -1
  22. package/core/commands/map-testids.md +11 -5
  23. package/core/commands/propose-scenario.md +7 -1
  24. package/core/commands/qc-analyze.md +12 -6
  25. package/core/commands/qc-automation-assess.md +356 -0
  26. package/core/commands/qc-design-script.md +430 -0
  27. package/core/commands/qc-design-test.md +98 -20
  28. package/core/commands/qc-plan.md +9 -3
  29. package/core/commands/qc-report.md +92 -77
  30. package/core/commands/qc-review-script.md +342 -0
  31. package/core/commands/{qc-review.md → qc-review-testcase.md} +86 -54
  32. package/core/commands/qc-run-manualtest.md +401 -0
  33. package/core/commands/qc-run-script.md +421 -0
  34. package/core/commands/refine-prd.md +7 -1
  35. package/core/commands/report-bug.md +9 -3
  36. package/core/commands/review-code.md +9 -3
  37. package/core/commands/review-context.md +11 -3
  38. package/core/commands/review-tech-docs.md +11 -3
  39. package/core/commands/setup-ai-first.md +7 -1
  40. package/core/commands/validate-traces.md +10 -4
  41. package/core/modules/qc-playwright-ts/module.yaml +13 -0
  42. package/core/modules/qc-playwright-ts/stack-profile.yaml +99 -0
  43. package/core/modules/qc-wdio-appium/module.yaml +20 -0
  44. package/core/modules/qc-wdio-appium/stack-profile.yaml +107 -0
  45. package/core/rules/workflow.md +2 -2
  46. package/core/skills/qc/_shared/self-review-principles.md +2 -2
  47. package/core/skills/qc/qa-analyst/DOC_GAP.template.md +1 -1
  48. package/core/skills/qc/qa-analyst/data-flow.md +1 -1
  49. package/core/skills/qc/qa-analyst/spec-issue-reporter.md +1 -1
  50. package/core/skills/qc/qa-automation-assess/matrix.md +123 -0
  51. package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
  52. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
  53. package/core/skills/qc/{qa-runner → qa-designer}/exploratory/session.md +8 -2
  54. package/core/skills/qc/qa-designer/functional/api.md +2 -2
  55. package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
  56. package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
  57. package/core/skills/qc/qa-designer/functional/job.md +128 -0
  58. package/core/skills/qc/qa-designer/integration/api.md +2 -2
  59. package/core/skills/qc/qa-designer/integration/db.md +2 -2
  60. package/core/skills/qc/qa-designer/integration/gui.md +1 -1
  61. package/core/skills/qc/qa-designer/integration/{kafka.md → queue.md} +21 -5
  62. package/core/skills/qc/qa-designer/non-functional.md +1 -1
  63. package/core/skills/qc/qa-designer/shared/skill-decision-tree.md +17 -0
  64. package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +28 -6
  65. package/core/skills/qc/qa-reviewer/script/_shared/review-rules.md +121 -0
  66. package/core/skills/qc/qa-reviewer/script/api/auth.md +49 -0
  67. package/core/skills/qc/qa-reviewer/script/api/endpoint.md +89 -0
  68. package/core/skills/qc/qa-reviewer/script/api/security.md +46 -0
  69. package/core/skills/qc/qa-reviewer/script/exploratory.md +3 -3
  70. package/core/skills/qc/qa-reviewer/script/mobile/e2e.md +41 -0
  71. package/core/skills/qc/qa-reviewer/script/mobile/functional.md +90 -0
  72. package/core/skills/qc/qa-reviewer/script/mobile/integration.md +41 -0
  73. package/core/skills/qc/qa-reviewer/script/mobile/non-functional.md +43 -0
  74. package/core/skills/qc/qa-reviewer/script/web/e2e.md +46 -0
  75. package/core/skills/qc/qa-reviewer/script/web/functional.md +111 -0
  76. package/core/skills/qc/qa-reviewer/script/web/integration.md +46 -0
  77. package/core/skills/qc/qa-reviewer/script/web/non-functional.md +49 -0
  78. package/core/skills/qc/qa-reviewer/shared/read-doc-gap-inputs.md +1 -1
  79. package/core/skills/qc/qa-reviewer/shared/review-file-template.md +29 -10
  80. package/core/skills/qc/qa-reviewer/test-case/e2e.md +2 -2
  81. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
  82. package/core/skills/qc/qa-reviewer/test-case/functional.md +2 -2
  83. package/core/skills/qc/qa-reviewer/test-case/integration.md +2 -2
  84. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +2 -2
  85. package/core/skills/qc/qa-script-designer/_shared/api-conventions.md +94 -0
  86. package/core/skills/qc/qa-script-designer/_shared/file-naming-and-folders.md +109 -0
  87. package/core/skills/qc/qa-script-designer/_shared/mobile-conventions.md +196 -0
  88. package/core/skills/qc/qa-script-designer/_shared/web-conventions.md +257 -0
  89. package/core/skills/qc/qa-script-designer/api/auth.md +43 -0
  90. package/core/skills/qc/qa-script-designer/api/endpoint.md +61 -0
  91. package/core/skills/qc/qa-script-designer/api/security.md +41 -0
  92. package/core/skills/qc/qa-script-designer/mobile/e2e.md +35 -0
  93. package/core/skills/qc/qa-script-designer/mobile/functional/feature.md +32 -0
  94. package/core/skills/qc/qa-script-designer/mobile/functional/screen.md +42 -0
  95. package/core/skills/qc/qa-script-designer/mobile/integration.md +39 -0
  96. package/core/skills/qc/qa-script-designer/mobile/non-functional.md +39 -0
  97. package/core/skills/qc/qa-script-designer/web/e2e.md +36 -0
  98. package/core/skills/qc/qa-script-designer/web/functional/api.md +39 -0
  99. package/core/skills/qc/qa-script-designer/web/functional/gui-feature.md +34 -0
  100. package/core/skills/qc/qa-script-designer/web/functional/gui-screen.md +42 -0
  101. package/core/skills/qc/qa-script-designer/web/integration.md +43 -0
  102. package/core/skills/qc/qa-script-designer/web/non-functional.md +42 -0
  103. package/core/skills/qc/qa-script-runner/mobile/run.md +38 -0
  104. package/core/skills/qc/qa-script-runner/report.md +41 -0
  105. package/core/skills/qc/qa-script-runner/web/run.md +48 -0
  106. package/core/steps/context-loader.md +1 -1
  107. package/core/steps/gate.md +7 -1
  108. package/core/steps/qc-scope.md +45 -2
  109. package/core/steps/qc-stamp.md +4 -4
  110. package/core/steps/report-footer.md +10 -9
  111. package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +1 -1
  112. package/docs/02-concepts/pipeline-steps/08-qc-automation.md +13 -12
  113. package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +3 -3
  114. package/docs/02-concepts/traceability.md +1 -1
  115. package/docs/03-guides/developer.md +1 -1
  116. package/docs/03-guides/tester-qa.md +40 -11
  117. package/docs/04-reference/commands.md +4 -2
  118. package/docs/04-reference/modules.md +2 -1
  119. package/docs/04-reference/trace-schema.md +4 -4
  120. package/docs/explain/17-qc-design-test.md +5 -5
  121. package/docs/explain/18-qc-review.md +42 -20
  122. package/docs/explain/19-qc-run-test.md +13 -10
  123. package/docs/explain/20-qc-report.md +3 -3
  124. package/docs/explain/23-fix-bug.md +2 -2
  125. package/docs/explain/README.md +2 -2
  126. package/docs/plans/qc-surgery/01-checklist.md +86 -21
  127. package/docs/plans/qc-surgery/PLAN_v2.md +295 -0
  128. package/docs/plans/qc-surgery/exec-S-ap-stack-typescript.md +420 -0
  129. package/docs/plans/qc-surgery/exec-S0-guard-cam-stack-cu.md +400 -0
  130. package/docs/plans/qc-surgery/exec-S1-hai-module-thay-qc-playwright.md +267 -0
  131. package/docs/plans/qc-surgery/exec-S2-qa-runner-thanh-script-designer-runner.md +340 -0
  132. package/docs/plans/qc-surgery/exec-S3-viet-lai-tieu-chi-review-script.md +322 -0
  133. package/docs/plans/qc-surgery/exec-S5-an-theo-don-dau-vet-stack-cu.md +292 -0
  134. package/package.json +1 -1
  135. package/core/commands/qc-run-test.md +0 -561
  136. package/core/modules/qc-playwright/stack-profile.yaml +0 -66
  137. package/core/skills/qc/qa-reviewer/script/e2e.md +0 -95
  138. package/core/skills/qc/qa-reviewer/script/functional.md +0 -109
  139. package/core/skills/qc/qa-reviewer/script/integration.md +0 -99
  140. package/core/skills/qc/qa-reviewer/script/non-functional.md +0 -134
  141. package/core/skills/qc/qa-runner/e2e.md +0 -49
  142. package/core/skills/qc/qa-runner/functional/api.md +0 -35
  143. package/core/skills/qc/qa-runner/functional/gui-feature.md +0 -57
  144. package/core/skills/qc/qa-runner/functional/gui-screen.md +0 -61
  145. package/core/skills/qc/qa-runner/integration.md +0 -47
  146. package/core/skills/qc/qa-runner/non-functional.md +0 -49
  147. package/core/skills/qc/qa-runner/report/report.md +0 -37
@@ -0,0 +1,128 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-17
4
+ ---
5
+
6
+ # Test Case — Job chạy ngầm *(tự chạy theo lịch hoặc điều kiện)*
7
+
8
+ Skill **tự chứa** để viết TC cho một việc **không ai gọi**: nó tự thức dậy theo lịch, theo ngưỡng,
9
+ hoặc theo một cờ trong dữ liệu. Chỉ cần load file này.
10
+
11
+ ## Khi nào trigger
12
+ - Nền `system`, và hình dạng đã chốt là **job** *(xem `/qc-design-test` §Nền `system`)*.
13
+ - Ví dụ: dọn dữ liệu quá hạn lúc 2h sáng · tổng hợp báo cáo cuối ngày · gửi nhắc hạn ·
14
+ đồng bộ định kỳ với hệ ngoài · batch/ETL.
15
+
16
+ ## Khi KHÔNG trigger
17
+ - Có endpoint, ai đó gọi vào → `functional/api.md`
18
+ - Nằm chờ message rồi xử lý → `integration/queue.md`
19
+ - Chỉ verify bản ghi DB sau **một thao tác của người** → `integration/db.md`
20
+
21
+ ---
22
+
23
+ ## Format file TC
24
+
25
+ > **Nạp `{paths.qc_skills_dir}/qa-designer/shared/tc-metadata-format.md`** — khuôn TC, luật
26
+ > ATOMIC (1 kết cục = 1 TC), phân nhóm, Trace + `@trace.verifies`, `🚫 Block`.
27
+ > **Không lặp lại luật format ở đây.**
28
+ >
29
+ > Khi viết Expected Result / Test Data: nạp thêm `shared/precision-rules.md` +
30
+ > `shared/action-keywords-glossary.md`.
31
+
32
+ **`Tags` của mọi TC ở đây mang lane `job`.** Trạm 5 và trạm 6 đọc nó để không phải hỏi lại.
33
+
34
+ ---
35
+
36
+ ## 1 · Ba thứ phải chốt TRƯỚC khi viết TC
37
+
38
+ Job khác API ở chỗ **không có request để mô tả**. Thay vào đó phải chốt ba thứ, và **thiếu cái
39
+ nào thì dừng hỏi, đừng đoán**:
40
+
41
+ | | Chốt gì | Nếu thiếu |
42
+ |---|---|---|
43
+ | **Kích hoạt** | Trong môi trường test, job được làm cho chạy bằng cách nào? *(lịch bắn thật · gọi tay qua CLI/endpoint quản trị · cắm cờ trong DB · đẩy một message)* | Ghi `🚫 Block: [GAP-…]` — không có cách kích hoạt thì **không TC nào chạy được** |
44
+ | **Cửa sổ dữ liệu** | Lượt chạy này **nhặt những bản ghi nào**? *(tạo trước mốc nào · trạng thái nào · giới hạn bao nhiêu bản ghi một lượt)* | Không biết cửa sổ thì không dựng được Test Data, và Expected Result thành *"xử lý đúng"* — một cụm bị cấm |
45
+ | **Dấu vết quan sát được** | Sau khi chạy xong, **nhìn vào đâu** để biết nó đã làm? *(bản ghi đổi trạng thái · file sinh ra · message phát đi · thông báo gửi đi · số liệu/log)* | Không có dấu vết thì TC không có oracle — nó không đỗ/trượt được |
46
+
47
+ > **Đây là chỗ job hay bị viết hụt nhất.** Người viết quen với API: có request, có response, oracle
48
+ > hiển nhiên. Job **không trả gì cả** — oracle nằm ở **thay đổi trạng thái**, và nếu không chốt
49
+ > trước thì Expected Result sẽ trôi về *"job chạy thành công"*, một câu không kiểm được.
50
+
51
+ ---
52
+
53
+ ## 2 · Chín nhóm TC bắt buộc soi
54
+
55
+ Sáu nhóm từ **4** trở xuống là **rủi ro riêng của job** — không skill nào khác trong framework
56
+ phủ chúng. Bỏ nhóm nào thì nêu rõ **vì sao bỏ**, đừng im lặng.
57
+
58
+ ### 1 · Đường thuận
59
+ Có dữ liệu đúng trong cửa sổ → chạy → **từng dấu vết ở §1 đổi đúng như mong đợi**.
60
+ Assert cả ba mặt nếu có: bản ghi · message phát ra · thông báo.
61
+
62
+ ### 2 · Không nhặt thứ ngoài cửa sổ
63
+ Bản ghi **ngoài** điều kiện *(sai trạng thái, tạo sau mốc)* → chạy → **bản ghi đó KHÔNG đổi**.
64
+ Đây là assert **phủ định**, và là nhóm hay bị đánh rơi nhất khi rút gọn TC.
65
+
66
+ ### 3 · Lượt chạy rỗng
67
+ Không có bản ghi nào để làm → chạy → **không lỗi, không phát message, không gửi thông báo**.
68
+ Job báo lỗi khi rỗng là bug; job gửi thông báo *"đã xử lý 0 bản ghi"* mỗi đêm cũng là bug.
69
+
70
+ ### 4 · Chạy lại lần hai cùng dữ liệu *(idempotency)*
71
+ Chạy xong lần 1 → chạy lại ngay lần 2 trên cùng dữ liệu → **hiệu ứng chỉ xảy ra một lần**:
72
+ không trừ tiền hai lần, không gửi mail hai lần, không tạo bản ghi trùng.
73
+
74
+ > **Đây là bug kinh điển nhất của job chạy ngầm.** Nó xuất hiện thật khi lịch chạy chồng, khi
75
+ > có người kích tay lúc job đang chạy, hoặc khi hệ thống khởi động lại giữa chừng.
76
+
77
+ ### 5 · Hỏng giữa chừng
78
+ Cho lỗi ở bản ghi thứ **k** của **n** *(k nằm giữa)* → phải trả lời được **hai** câu, và TC phải
79
+ ghi rõ thiết kế chọn đường nào:
80
+
81
+ | Đường | Kỳ vọng |
82
+ |---|---|
83
+ | **Dừng cả lượt** | k−1 bản ghi đầu **đã xong** phải giữ nguyên, hay bị rollback hết? |
84
+ | **Bỏ qua bản lỗi, chạy tiếp** | bản thứ k có được ghi lại ở đâu không? Lượt sau có nhặt lại nó không? |
85
+
86
+ Chạy lại sau khi hỏng: **k−1 bản đầu KHÔNG được xử lý lần thứ hai** *(nối với nhóm 4)*.
87
+
88
+ ### 6 · Hai tiến trình cùng lúc
89
+ Kích hai lượt chạy chồng nhau → **không bản ghi nào bị xử lý hai lần**. Hoặc job phải **từ chối**
90
+ lượt thứ hai *(có khoá)*, hoặc hai lượt chia nhau bản ghi — **thiết kế chọn đường nào phải ghi
91
+ trong TC**, vì hai đường có Expected Result khác hẳn.
92
+
93
+ ### 7 · Biên của cửa sổ
94
+ Bản ghi tạo **đúng mốc** · **trước mốc một đơn vị** · **sau mốc một đơn vị** → nhặt đúng cái phải
95
+ nhặt. Và ca khó hơn: bản ghi **được tạo trong lúc job đang chạy** — lượt này lấy hay để lượt sau?
96
+
97
+ > Nêu **đơn vị** tường minh *(giây? ngày? theo múi giờ nào?)* — `precision-rules.md` cấm mốc mơ hồ.
98
+
99
+ ### 8 · Bản ghi độc
100
+ Một bản ghi hỏng *(dữ liệu sai định dạng, tham chiếu chết)* → nó **không được làm chết cả lượt**,
101
+ trừ khi thiết kế cố ý thế. Ghi rõ đường nào, và bản ghi độc đi đâu.
102
+
103
+ ### 9 · Thử lại và trần
104
+ Job gọi ra ngoài mà bên kia lỗi → thử lại mấy lần, cách nhau bao lâu, **trần ở đâu**?
105
+ Không có trần là job treo tới khi có người tắt.
106
+
107
+ ---
108
+
109
+ ## 3 · Phân nhóm trong file TC
110
+
111
+ ```
112
+ 1 Đường thuận ← nhóm 1
113
+ 2 Cửa sổ & biên ← nhóm 2, 7
114
+ 3 Chạy lặp & đồng thời ← nhóm 4, 6
115
+ 4 Hỏng & phục hồi ← nhóm 5, 8, 9
116
+ 5 Lượt rỗng ← nhóm 3
117
+ ```
118
+
119
+ ---
120
+
121
+ ## 4 · Test Data — khác API ở chỗ nào
122
+
123
+ Job **không nhận payload**; dữ liệu của nó là **trạng thái có sẵn trong hệ thống**. Nên Test Data
124
+ của TC job là một **bảng bản ghi phải seed trước**, kèm ba cột tối thiểu: định danh · trạng thái ·
125
+ mốc thời gian liên quan tới cửa sổ.
126
+
127
+ Và phải nêu **dọn thế nào** — job đổi trạng thái thật, nên chạy hai lần liên tiếp mà không dọn
128
+ thì lượt sau đã không còn ở điều kiện ban đầu *(và đó chính là nhóm 4 nếu cố ý, là nhiễu nếu vô ý)*.
@@ -15,7 +15,7 @@ verify luồng dữ liệu & contract giữa các thành phần. Chỉ cần loa
15
15
 
16
16
  ## Khi KHÔNG trigger
17
17
  - Chỉ verify request/response 1 endpoint → `functional/api`
18
- - Verify riêng trạng thái DB → `integration/db` · message/event → `integration/kafka`
18
+ - Verify riêng trạng thái DB → `integration/db` · message/event → `integration/queue`
19
19
 
20
20
  ---
21
21
 
@@ -46,4 +46,4 @@ Nhóm TC: happy (dữ liệu đúng đầu→cuối) → contract negative (inpu
46
46
 
47
47
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ưu tiên P0 cho định tuyến & tiền-dữ liệu. Chuỗi gọi phụ thuộc nhau: `../api/crud-sequence.md`.
48
48
 
49
- **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`.
49
+ **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-testcase`.
@@ -13,7 +13,7 @@ insert/update/soft-delete đúng giá trị, side-effect, toàn vẹn. Chỉ c
13
13
  - Kiểm tra bản ghi DB sau thao tác (tạo ticket → ghi đúng bảng/cột); soft-delete, default, audit log
14
14
 
15
15
  ## Khi KHÔNG trigger
16
- - Chỉ verify response API → `functional/api`/`integration/api` · message/event → `integration/kafka`
16
+ - Chỉ verify response API → `functional/api`/`integration/api` · message/event → `integration/queue`
17
17
 
18
18
  ---
19
19
 
@@ -42,4 +42,4 @@ Nhóm TC: ghi đúng giá trị (happy) → default/null đúng → update khôn
42
42
 
43
43
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Ghi rõ query kiểm tra DB + yêu cầu cleanup; không hardcode ID, chuẩn bị/dọn data qua fixture (3 mức teardown: `../shared/precision-rules.md` §8).
44
44
 
45
- **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`.
45
+ **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-testcase`.
@@ -44,4 +44,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` — **Nhóm 4 Integration (qua UI)**. Đây là tầng verify dòng dữ liệu API → giao diện, nên **vẫn thuộc file giao diện**: bỏ UI đi thì TC mất nghĩa.
46
46
 
47
- **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`.
47
+ **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-testcase`.
@@ -4,16 +4,32 @@ updated: 2026-06-11
4
4
  ported_from: ui-automation-testing
5
5
  ---
6
6
 
7
- # Test Case — Integration Kafka (Message/Event)
7
+ # Test Case — Integration hàng đợi (Message/Event)
8
8
 
9
- Skill **tự chứa** để viết TC tích hợp qua Kafka: producer phát event đúng, consumer xử
10
- đúng, đảm bảo ordering/idempotency/retry. Chỉ cần load file này.
9
+ Skill **tự chứa** để viết TC tích hợp qua hàng đợi/message bus Kafka, RabbitMQ, SQS, hay bất
10
+ kỳ chế nào **người gửi** **người nhận** tách rời: producer phát event đúng, consumer xử
11
+ lý đúng, đảm bảo ordering/idempotency/retry. Chỉ cần load file này.
12
+
13
+ > **Tên file đổi từ `kafka.md` (2026-09-17):** nội dung chưa bao giờ phụ thuộc Kafka — nó nói về
14
+ > **hình dạng hàng đợi**. Giữ tên một công nghệ cụ thể làm người dùng RabbitMQ/SQS tưởng không
15
+ > áp dụng được.
11
16
 
12
17
  ## Khi nào trigger
13
- - Action sinh event Kafka (vd tạo ticket → phát event sang service/CRM); verify topic/payload/thứ tự/khử trùng
18
+
19
+ Hai phía, **cùng một file** — nêu rõ TC đang đứng ở phía nào:
20
+
21
+ | Phía | Khi nào | Ví dụ |
22
+ |---|---|---|
23
+ | **Người gửi** *(producer)* | một action sinh ra event | tạo ticket → phát event sang CRM; verify topic · key · payload · điều kiện phát |
24
+ | **Người nhận** *(consumer)* | service **nằm chờ**, có message tới thì xử lý — **không action nào của người đứng trước** | đơn hàng mới vào hàng đợi → service kho trừ tồn; verify xử lý đúng · khử trùng · lỗi thì đi đâu |
25
+
26
+ > **Phía người nhận là chỗ hay bị bỏ sót.** Khung cũ chỉ viết *"Action sinh event"* — tức luôn
27
+ > giả định có một thao tác đứng trước. Một consumer thuần thì **không có thao tác đó**, và TC
28
+ > phải bắt đầu bằng *"có message X trên hàng đợi Y"*, không phải bằng một hành động của người.
14
29
 
15
30
  ## Khi KHÔNG trigger
16
31
  - Tích hợp đồng bộ qua API → `integration/api` · verify DB → `integration/db`
32
+ - **Tự chạy theo lịch, không có message nào kích** → `functional/job.md`
17
33
 
18
34
  ---
19
35
 
@@ -44,4 +60,4 @@ Mỗi TC bám Format; trace BR; gap chặn → 🚫 Block.
44
60
 
45
61
  Ghi vào `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md` — **Nhóm 2 Integration API/DB/Kafka**. Mỗi TC ghi topic, key, payload cần verify + hành vi consumer.
46
62
 
47
- **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`.
63
+ **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-testcase`.
@@ -44,4 +44,4 @@ Trace BR; gap chặn → 🚫 Block.
44
44
 
45
45
  Ghi vào file theo cùng câu hỏi phân file *"verify được mà không cần UI?"*: a11y · responsive · touch-target → `{qc_artifact_dir}test-cases/TC_<FEATURE>.Test.md` **Nhóm 5 NFR**; tải/hiệu năng/bảo mật ở tầng API → `{qc_artifact_dir}test-cases/TC_<FEATURE>_API.Test.md`. Mỗi TC ghi tiêu chí đo + ngưỡng + công cụ, đơn vị theo `../shared/precision-rules.md` §3.
46
46
 
47
- **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`.
47
+ **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-testcase`.
@@ -11,6 +11,21 @@ upstream_sha: 57125f0c21512f2abcc55d00420e92c84c95fc8f
11
11
 
12
12
  ---
13
13
 
14
+ ## Bước 0 — TC đã có lane chưa? *(hỏi TRƯỚC mọi câu khác)*
15
+
16
+ Nếu `Tags` của TC đã mang một `<lane>` — `ui` · `api` · `job` · `queue` · `db` · `e2e` · `nfr` —
17
+ thì **ĐỌC nó, dừng ở đây, không suy lại**. Bảng lane ↔ skill ở
18
+ `shared/tc-metadata-format.md` §Tags.
19
+
20
+ > **Vì sao dừng chứ không "kiểm tra lại cho chắc".** Với nền `system`, lane là **câu trả lời của
21
+ > QC** ở trạm 3 cho một câu mà máy không suy được *(xem `/qc-design-test` §Nền `system`)*. Suy lại
22
+ > là đặt phán đoán của máy lên trên câu trả lời của người — và khi hai bên lệch, TC và script sẽ
23
+ > kiểm hai thứ khác nhau mà **cả hai đều chạy được**.
24
+ >
25
+ > Chưa có lane → đi tiếp Bước 1.
26
+
27
+ ---
28
+
14
29
  ## Bước 1 — Đối tượng test là gì?
15
30
 
16
31
  ```
@@ -18,6 +33,8 @@ upstream_sha: 57125f0c21512f2abcc55d00420e92c84c95fc8f
18
33
  ├── Hiển thị / validation / state của 1 screen → [A] Xét tiếp Bước 2 (UI vs Integration GUI)
19
34
  ├── User thực hiện workflow có mục tiêu nghiệp vụ → [B] Xét tiếp Bước 3 (E2E vs Integration)
20
35
  ├── 1 API endpoint (request/response/mã lỗi) → api-testcase-designer
36
+ ├── Việc TỰ CHẠY theo lịch/điều kiện, không ai gọi → functional/job.md
37
+ ├── Nằm chờ message rồi xử lý → integration/queue.md
21
38
  ├── NFR (performance/security/a11y/i18n) → nfr-testcase-designer
22
39
  └── Luồng đa màn nằm trong 1 feature, không xuyên hệ thống → ui-testcase-designer (gui-feature)
23
40
  ```
@@ -5,7 +5,12 @@ ported_from: ui-automation-testing
5
5
  upstream_path: skills/qa-tc-designer/shared/tc-metadata-format.md
6
6
  upstream_sha: a31d66a7a8dab19cf821c9102a88282b09e16cb9
7
7
  ---
8
- # TC Metadata Format (Chuẩn chung)
8
+ # TC Metadata Format
9
+
10
+ > **`Automatable` KHÔNG phải một field của `.Test.md`.** Quyết định *"TC này máy chạy được hay
11
+ > phải chạy tay"* sống ở **đúng một chỗ**: `{qc_artifact_dir}AUTOMATION_ASSESSMENT.md`, do
12
+ > `/qc-automation-assess` ghi. Đừng chép giá trị đó vào đây — hai nơi ghi cùng một quyết định
13
+ > thì một nơi sẽ lệch, và lúc đó không ai biết nơi nào đúng. (Chuẩn chung)
9
14
 
10
15
  ## ⚠️ Nguyên tắc format file TC (BẮT BUỘC — QC yêu cầu)
11
16
 
@@ -56,6 +61,23 @@ Mỗi trường 1 dòng, không bảng, không emoji dư:
56
61
  - **Status:** Draft
57
62
  - **Author:** AI
58
63
  - **Tags:** <lane>, <loại: smoke|sanity|regression>, <feature-tag>
64
+
65
+ **`<lane>` — giá trị hợp lệ** *(khai 2026-09-17; trước đó để ngỏ nên mỗi file viết một kiểu)*:
66
+
67
+ | Lane | Khi nào | Skill thiết kế |
68
+ |---|---|---|
69
+ | `ui` | có màn hình | `functional/gui-screen` · `gui-feature` |
70
+ | `api` | có endpoint, ai đó gọi vào | `functional/api` · `integration/api` |
71
+ | `job` | **tự chạy** theo lịch/điều kiện, không ai gọi | `functional/job` |
72
+ | `queue` | nằm chờ message rồi xử lý | `integration/queue` |
73
+ | `db` | verify trạng thái dữ liệu sau thao tác | `integration/db` |
74
+ | `e2e` | hành trình xuyên nhiều màn/hệ | `e2e/journey` |
75
+ | `nfr` | hiệu năng · bảo mật · a11y · i18n | `non-functional` |
76
+
77
+ > **Lane là câu trả lời đã chốt, không phải nhãn trang trí.** Với nền `system`, nó do **QC trả
78
+ > lời** ở trạm 3 khi không suy được hình dạng *(xem `/qc-design-test` §Nền `system`)*. Trạm 5 và
79
+ > trạm 6 **ĐỌC** lane này, **không suy lại** — suy lại là mở đường cho hai trạm kết luận khác nhau
80
+ > về cùng một TC.
59
81
  - **Trace:** BR-xx (ID gốc trong PRD/BDD ở `{paths.specs_dir}`)
60
82
  - **@trace.verifies:** {UC-ID}-SC{N}
61
83
  - **🚫 Block:** [GAP-UC{N}-{nnn}](../DOC_GAP.md) — <lý do> *(chỉ khi có)*
@@ -205,7 +227,7 @@ Mọi thứ trên là chuẩn của đội QC. Bốn thứ dưới đây là **c
205
227
  **Câu hỏi phân file:** *"TC này verify được mà **không cần UI** không?"*
206
228
  → **có** = file API · **không** = file giao diện. *(Trùng Bước 2 của `skill-decision-tree.md`.)*
207
229
 
208
- ⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-run-test` và `/qc-review` tìm `*.Test.md`;
230
+ ⚠️ **Đuôi file là `.Test.md`, không phải `.md`.** `/qc-design-script` và `/qc-review-testcase` tìm `*.Test.md`;
209
231
  ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm thấy**, và không có gì báo lỗi.
210
232
 
211
233
  Đánh số `TC_<FEATURE>_NNN` **liên tục toàn file**, không đánh lại theo từng nhóm.
@@ -215,7 +237,7 @@ ghi ra file thiếu phần `.Test` là ghi ra thứ **không trạm nào tìm th
215
237
  | Trường | Dạng | Vì sao cần |
216
238
  |---|---|---|
217
239
  | `**Trace:**` | `[BR-xx](../REQUIREMENT_ANALYSIS.md#3-business-rules)` — không có BR → `⚠️ Chưa có Business Rule` | truy về luật nghiệp vụ |
218
- | `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-test` ghi `qc_status` theo từng kịch bản vào sổ trace |
240
+ | `**@trace.verifies:**` | `{UC-ID}-SC{N}` (lấy từ `@trace.scenario` của file `.feature`) | **join key** để `/qc-run-script` ghi `qc_status` theo từng kịch bản vào sổ trace |
219
241
 
220
242
  Một `SC` map được nhiều TC. **Thiếu `@trace.verifies` thì kết quả chạy không vào được sổ** — TC
221
243
  vẫn chạy, vẫn pass/fail, nhưng không ai biết nó phủ kịch bản nào.
@@ -241,7 +263,7 @@ Nguồn & phiên bản: BDD {UC-ID} `<vX.Y>` · tech-doc `<rev | —>`
241
263
  ```
242
264
 
243
265
  Lấy `<vX.Y>` từ `| **Version** |` ở header `.feature` của **chính UC này**, và `<rev>` từ header
244
- tech-doc gộp. `/qc-review` và `/qc-run-test` **so** khối này với version hiện tại để biết bộ TC còn
266
+ tech-doc gộp. `/qc-review-testcase` và `/qc-design-script` **so** khối này với version hiện tại để biết bộ TC còn
245
267
  khớp spec không (`steps/qc-stamp.md` · `bin/trace-schema.json` → `qc_artifact_stamp`).
246
268
 
247
269
  **Vì sao cần, khi sổ trace đã có `qc_status`.** `/generate-bdd` hạ `qc_status → not_run` khi spec đổi
@@ -259,8 +281,8 @@ Test-ID attribute: {attr}
259
281
  ```
260
282
 
261
283
  Đọc `@trace.testid_attr` từ header tech-doc gộp (do `/map-testids` ghi). Bảng §4.5.6 chỉ cho
262
- **giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-run-test` cần nó để cấu hình
263
- locator, `/qc-review` cần nó để biết selector trong script có đúng hợp đồng không.
284
+ **giá trị** test-id; đây là **tên thuộc tính** chứa chúng. `/qc-design-script` cần nó để cấu hình
285
+ locator, `/qc-review-script` cần nó để biết selector trong script có đúng hợp đồng không.
264
286
 
265
287
  Thiếu field trong tech-doc → ghi `Test-ID attribute: — (thiếu @trace.testid_attr, chạy /map-testids)`.
266
288
  **Đừng bỏ trống và đừng tự đoán** — đoán sai thì mọi locator trượt 100%, và trượt vì lý do
@@ -0,0 +1,121 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-17
4
+ source: upstream/qc-base-new/AGT-006-code_reviewer.md §3.1 §3.2 §3.3 §4 (Draft) · §5 Boundary
5
+ ---
6
+
7
+ # Luật soát script — dùng chung cho mọi nền
8
+
9
+ **Nạp file này TRƯỚC file lane.** Lane chỉ nói *"nền này soát thêm gì"*; mọi thứ ở đây đúng cho
10
+ cả `web` · `mobile` · `api`. Viết một bản vì 11 file lane đều cần — 11 bản của một luật là nơi
11
+ drift sống.
12
+
13
+ ---
14
+
15
+ ## 1 · Bảy luật của lượt soát *(R01–R07)*
16
+
17
+ | Mã | Luật | Nghĩa khi soát |
18
+ |---|---|---|
19
+ | **R01** | **Review All Files** | Soát **mọi** file được đưa: spec · Page/Screen/API Object · data. Soát một phần rồi kết luận là kết luận về một thứ chưa đọc |
20
+ | **R02** | **Evidence-Based Findings** | Mỗi lỗi phải có đủ **bốn**: tên file · số dòng (hoặc đoạn code) · mô tả vấn đề · cách sửa đề nghị. Thiếu một trong bốn thì đó là cảm tưởng, không phải finding |
21
+ | **R03** | **No Silent Pass** | Không `APPROVED` một script chưa soát kỹ. Soát đủ mà không thấy lỗi → `APPROVED` là **đúng**, không phải lười |
22
+ | **R04** | **No Rewriting** | Chỉ báo cáo, **không sửa code**. Đề xuất phải đủ rõ để người viết tự sửa được mà không hỏi lại |
23
+ | **R05** | **Positive Observations Required** | Mỗi lượt soát ghi **ít nhất 2–3 điểm tốt**. Một biên bản chỉ có lỗi là biên bản mất cân bằng — người đọc không biết phần nào đang đúng để giữ |
24
+ | **R06** | **Verdict Consistency** | Verdict suy ra từ **số đếm** finding theo §3, không tự nâng/hạ |
25
+ | **R07** | **Traceability First** | Thiếu/sai header artifact ID *(TC-ID · `@trace.verifies`)* ⇒ **BLOCKER ngay, dừng soát**. Không soát tiếp một file không biết nó phục vụ scenario nào |
26
+
27
+ > **R07 chặn cửa TRƯỚC, không phải sau.** Một lượt soát trên file không có trace tag vẫn chạy
28
+ > trót lọt và vẫn in ra verdict — nhưng verdict đó nói về một thứ không neo vào scenario nào.
29
+ > Đó là kiểu hỏng **Nói dối**: biên bản trông hợp lệ, nội dung vô nghĩa.
30
+
31
+ ---
32
+
33
+ ## 2 · Bốn mức nặng-nhẹ của một lỗi *(severity)*
34
+
35
+ | Mức | Định nghĩa | Ví dụ |
36
+ |---|---|---|
37
+ | **BLOCKER** | Ngăn test chạy đúng, hoặc vi phạm chuẩn lõi | selector thô trong spec · thiếu `await` · lỗi cú pháp · **không có header block** |
38
+ | **MAJOR** | Ảnh hưởng nặng tới khả năng bảo trì hoặc độ tin cậy | hard-code test data · `waitForTimeout` · locator bám class CSS tự sinh |
39
+ | **MINOR** | Vấn đề chất lượng code, script **vẫn chạy được** | thiếu type annotation · đặt tên không nhất quán · logic lặp có thể tách |
40
+ | **SUGGESTION** | Cơ hội cải thiện — **không bắt buộc** | tên biến rõ hơn · thông điệp assertion mô tả hơn |
41
+
42
+ **Ranh giới BLOCKER ↔ MAJOR đo được, không cảm tính:** BLOCKER là *"chạy sẽ sai hoặc không chạy"*;
43
+ MAJOR là *"chạy đúng hôm nay, hỏng khi có người sửa"*.
44
+
45
+ ---
46
+
47
+ ## 3 · Bốn verdict — suy ra từ số đếm, **không override**
48
+
49
+ | Verdict | Điều kiện bắt buộc | Đi tiếp? |
50
+ |---|---|:-:|
51
+ | **APPROVED** | 0 BLOCKER, 0 MAJOR | ✅ |
52
+ | **APPROVED_WITH_SUGGESTIONS** | 0 BLOCKER, 0 MAJOR, ≥1 MINOR hoặc SUGGESTION | ✅ |
53
+ | **REVISION_REQUIRED** | 0 BLOCKER, ≥1 MAJOR | ❌ sửa rồi soát lại |
54
+ | **REJECTED** | ≥1 BLOCKER | ❌ sửa rồi soát lại |
55
+
56
+ **Ngưỡng qua cửa: `≥ APPROVED_WITH_SUGGESTIONS`** — khai ở `AGT-005:132` và `AGT-010:130`.
57
+ Hai mức trên đi tiếp, hai mức dưới quay lại. Các trạm sau *(`/qc-run-script`)* đọc **hai luồng
58
+ này**, không đọc bốn tên.
59
+
60
+ > **Vì sao lane QC dùng 4 mức còn lane DEV *(`/review-code`)* giữ 2.** Lane QC có tài liệu chuẩn
61
+ > định nghĩa severity thành bốn ô đếm được *(§2)*, nên bốn verdict chỉ là **tên của bốn ô đó** —
62
+ > không thêm phán quyết nào. Lane DEV chưa có bảng severity tương ứng, nên 4 tên ở đó sẽ là bốn
63
+ > nhãn phải tự đoán. Đây là **một bất đối xứng có lý do**, không phải chỗ quên đồng bộ.
64
+
65
+ ---
66
+
67
+ ## 4 · Ranh giới — soát cái gì, KHÔNG soát cái gì
68
+
69
+ | | |
70
+ |---|---|
71
+ | ✅ **Soát** | code test đã sinh · Page/Screen/API Object · file data · khớp với `.Test.md` gốc |
72
+ | ❌ **KHÔNG soát** | **cấu trúc file test case** — đó là việc của `/qc-review-testcase`. Áp checklist cấu trúc TC vào một Page Object là bảo người soát đi tìm `#### Expected Result` trong code |
73
+ | ❌ **KHÔNG sửa** | *(R04)* — kể cả lỗi hiển nhiên một dòng |
74
+ | ❌ **KHÔNG chạy** | chạy test là việc của `/qc-run-script`. Ở đây chỉ compile/list để biết script **dịch được** và **thấy đủ số test** |
75
+
76
+ ---
77
+
78
+ ## 5 · Phép kiểm cơ học bắt buộc — trước khi kết luận
79
+
80
+ Chạy đủ hai lệnh, **dán output vào biên bản**:
81
+
82
+ ```
83
+ npx tsc --noEmit ← dịch được? (BLOCKER nếu lỗi)
84
+ npx playwright test <spec> --list ← đếm số test collect được (web · api)
85
+ npx wdio <config> --dry-run ← tương đương cho mobile
86
+ ```
87
+
88
+ **Số test collect được phải bằng số TC `Automatable: Y`** của phạm vi này trong
89
+ `AUTOMATION_ASSESSMENT.md`. Lệch là **BLOCKER** — không phải MINOR:
90
+
91
+ - collect **ít hơn** ⇒ có TC không được sinh, và nó sẽ nằm `not_run` vĩnh viễn trong sổ trace
92
+ - collect **nhiều hơn** ⇒ có test không neo vào TC nào, `qc_status` sẽ ghi cho một scenario không tồn tại
93
+
94
+ > Đây là chỗ duy nhất trong lượt soát mà **máy trả lời thay vì người** — nên nó là chỗ đáng tin
95
+ > nhất, và là lý do hai lệnh trên không được bỏ qua kể cả khi "nhìn code thấy ổn".
96
+
97
+ ---
98
+
99
+ ## 6 · Đường dẫn — lấy từ `§layout` của module, KHÔNG viết cứng
100
+
101
+ Nền đang soát đã được `steps/qc-scope.md` §2b phân giải. Gốc thư mục lấy từ `§layout` của
102
+ module tương ứng:
103
+
104
+ ```
105
+ web automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
106
+ automation/pages/<feature>.page.ts
107
+ api api-automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
108
+ api-automation/api/<resource>.api.ts
109
+ mobile mobile-automation/tests/{TICKET-ID}/<feature>-<scenario>.spec.ts
110
+ mobile-automation/screens/<feature>.screen.ts
111
+ ```
112
+
113
+ > **`tests/` chia theo `{TICKET-ID}`, `pages/`·`api/`·`screens/` để phẳng — có chủ ý.** Một spec
114
+ > **thuộc về** một PRD; một Page Object **được dùng bởi** nhiều PRD. Nhét Page Object vào thư mục
115
+ > PRD là ép nhân bản nó cho mỗi PRD — đúng thứ Page Object Pattern sinh ra để tránh.
116
+ >
117
+ > Thiếu segment `{TICKET-ID}` ở `tests/` thì hai PRD cùng có feature `login` ghi vào **cùng một
118
+ > đường dẫn** và đè nhau **im lặng**. Đó là lý do framework lệch khỏi bố cục phẳng của
119
+ > `Automation-Standards §2.3`: chuẩn giả định `tests/` soi gương theo `test-suites/`, còn ở đây
120
+ > test case sống ở `{qc_dir}/{TICKET-ID}/{platform}/test-cases/` — áp đúng **nguyên tắc** của
121
+ > chuẩn vào layout này thì ra hình dạng trên.
@@ -0,0 +1,49 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-17
4
+ source: upstream/qc-base-new/API-Testing-Standards.md §5.5 §9.1 (Approved)
5
+ ---
6
+
7
+ # Soát script — API xác thực & phân quyền
8
+
9
+ **Nạp `../_shared/review-rules.md` rồi `endpoint.md` cùng lane.** Đây là phần thêm.
10
+
11
+ ## Khi nào trigger
12
+ - Soát script kiểm đăng nhập, token, và **quyền truy cập** của từng vai lên từng endpoint.
13
+
14
+ ---
15
+
16
+ ## Thêm gì so với endpoint
17
+
18
+ ### A · Fixture token dùng chung *(§5.5)*
19
+
20
+ - Mỗi test tự đăng nhập lại ⇒ **MINOR** — chậm và dễ chạm rate-limit; dùng `fixtures/api.fixture.ts`
21
+ - Token hard-code / token thật commit vào repo ⇒ **BLOCKER**
22
+ - Fixture không phân biệt **vai** ⇒ **MAJOR**: một token dùng cho mọi test thì không kiểm được phân quyền
23
+
24
+ ### B · Mọi endpoint được bảo vệ phải có đủ ba ca *(§9.1)*
25
+
26
+ | Ca | Mong đợi |
27
+ |---|---|
28
+ | Không token | **401** |
29
+ | Token sai / hết hạn | **401** |
30
+ | Token đúng nhưng **sai vai** | **403** |
31
+
32
+ - Thiếu bất kỳ ca nào cho một endpoint được bảo vệ ⇒ **MAJOR**
33
+ - Gộp 401 và 403 thành một ca ⇒ **MAJOR** — hai lỗi khác nhau: *chưa biết anh là ai* vs *biết rồi
34
+ nhưng anh không được phép*
35
+
36
+ ### C · Assert phải là "bị chặn", không phải "không lỗi"
37
+
38
+ - `expect(res.status()).not.toBe(200)` ⇒ **MAJOR** — 500 cũng qua được phép assert này
39
+ - Assert đúng mã, và assert body **không rò dữ liệu** của tài nguyên bị cấm ⇒ thiếu ⇒ **MINOR**
40
+
41
+ ### D · Vòng đời token
42
+
43
+ - Không kiểm token hết hạn / refresh khi hợp đồng có ⇒ **MINOR**
44
+
45
+ ---
46
+
47
+ ## Kiểm cơ học + Output
48
+
49
+ Như `endpoint.md` Phase 3 và §Output.
@@ -0,0 +1,89 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-17
4
+ source: upstream/qc-base-new/API-Testing-Standards.md §4 §5 §6 §8 §10 §11 · AGT-010 §3 (Approved)
5
+ ---
6
+
7
+ # Soát script — API endpoint *(Playwright API mode + TypeScript)*
8
+
9
+ **Nạp `../_shared/review-rules.md` trước.** Lane này dùng khi `active_platform = system`.
10
+
11
+ > ⚠️ **API Object ≠ Page Object.** Không có màn hình, không có locator, không có wait. Soát API
12
+ > bằng checklist web là đi tìm những thứ không tồn tại rồi kết luận "không có lỗi".
13
+
14
+ ## Khi nào trigger
15
+ - Soát script kiểm **endpoint** của một service: CRUD, mã trạng thái, cấu trúc response.
16
+
17
+ ## Khi KHÔNG trigger
18
+ - Xác thực / phân quyền → `auth.md` · injection & input validation → `security.md`
19
+ - API gọi phụ trợ **bên trong** một dự án web *(setup/teardown)* → `../web/functional.md`
20
+
21
+ ---
22
+
23
+ ## Phase 1 — Đọc đủ *(R01)*
24
+
25
+ 1. `api-automation/tests/{TICKET-ID}/<feature>-*.spec.ts`
26
+ 2. `api-automation/api/<resource>.api.ts` + `base.api.ts`
27
+ 3. `data/<resource>.data.ts` · `fixtures/api.fixture.ts` · `helpers/schema.helper.ts`
28
+ 4. `.Test.md` + `AUTOMATION_ASSESSMENT.md`
29
+
30
+ **R07 chặn cửa** như mọi lane.
31
+
32
+ ---
33
+
34
+ ## Phase 2 — Năm nhóm soát
35
+
36
+ ### A · API Object *(§4 · AGT-010 R01)*
37
+
38
+ - **Mọi HTTP request phải đi qua API Object.** `request.post(...)` thô trong spec ⇒ **BLOCKER**
39
+ - `extends BaseAPI`; class `<Resource>API`; file `<resource>.api.ts`
40
+ - **1 method = 1 endpoint action**; method gộp nhiều endpoint ⇒ **MAJOR**
41
+ - Kiểu trả về `Promise<APIResponse>` — **không parse response trong API Object** ⇒ parse ⇒ **MAJOR**
42
+ - **Không `expect()` trong API Object** ⇒ có ⇒ **MAJOR**
43
+ - "God API Object" gom mọi resource ⇒ **MAJOR**
44
+
45
+ ### B · Cấu trúc spec *(§5 — AAA)*
46
+
47
+ - Ba khối rõ: **Arrange** (data, token) → **Act** (gọi API Object) → **Assert**
48
+ - Trộn assert vào giữa chuỗi gọi ⇒ **MINOR**
49
+ - Header block có TC-ID + `@trace.verifies` ⇒ thiếu ⇒ **BLOCKER** *(R07)*
50
+ - Data-driven dùng `for...of` hoặc `test.each`, không copy test 5 lần ⇒ copy ⇒ **MINOR**
51
+
52
+ ### C · Assertion *(§6)*
53
+
54
+ - **Assert mã trạng thái là bắt buộc** — thiếu ⇒ **BLOCKER**
55
+ - Assert **cả cấu trúc lẫn giá trị** của body, không chỉ `status === 200` ⇒ chỉ status ⇒ **MAJOR**
56
+ - Kiểm schema cho response có cấu trúc ⇒ thiếu ⇒ **MINOR**
57
+ - Assert header khi hợp đồng có nêu *(content-type, cache)* ⇒ thiếu ⇒ **MINOR**
58
+ - `expect(res.ok()).toBeTruthy()` làm assertion duy nhất ⇒ **MAJOR** — nó đúng cho mọi 2xx/3xx
59
+
60
+ ### D · Dữ liệu *(AGT-010 R03)*
61
+
62
+ - Credential, payload, giá trị mong đợi **hard-code trong spec** ⇒ **MAJOR** — để ở `data/`
63
+ - Bản ghi tạo ra phải xoá trong `afterEach`/`afterAll`, kể cả khi fail ⇒ thiếu ⇒ **MAJOR**
64
+ - Test phụ thuộc bản ghi có sẵn trên môi trường ⇒ **MAJOR**
65
+
66
+ ### E · Async *(AGT-010 R02)* và chất lượng *(§10 · §11)*
67
+
68
+ - **`waitForTimeout` tuyệt đối không dùng** — API là đồng bộ về bản chất, `await` thẳng ⇒ có ⇒ **BLOCKER**
69
+ - Thiếu `await` trước lời gọi API ⇒ **BLOCKER** *(test xanh giả, chạy xong trước khi có response)*
70
+ - TypeScript strict, không `any` ⇒ **MINOR**
71
+ - `test.only` sót lại ⇒ **BLOCKER**
72
+
73
+ ---
74
+
75
+ ## Phase 3 — Kiểm cơ học
76
+
77
+ ```
78
+ npx tsc --noEmit
79
+ npx playwright test --config=api-automation/playwright.config.ts <spec> --list
80
+ ```
81
+
82
+ Số test collect được **phải bằng** số TC `Automatable: Y`. Lệch ⇒ **BLOCKER**.
83
+
84
+ ---
85
+
86
+ ## Output
87
+
88
+ Theo `_shared/review-rules.md` §3, kèm ≥2–3 điểm tốt *(R05)*.
89
+ Lưu ý dãy ID của lane này độc lập: `TC-API-*` ≠ `TC-*` *(§7.3)*.
@@ -0,0 +1,46 @@
1
+ ---
2
+ version: 1.0
3
+ updated: 2026-09-17
4
+ source: upstream/qc-base-new/API-Testing-Standards.md §8 §9.2 (Approved)
5
+ ---
6
+
7
+ # Soát script — API kiểm tra đầu vào & injection
8
+
9
+ **Nạp `../_shared/review-rules.md` rồi `endpoint.md` cùng lane.** Đây là phần thêm.
10
+
11
+ ## Khi nào trigger
12
+ - Soát script kiểm **biên của đầu vào** và các mẫu injection lên endpoint.
13
+
14
+ ---
15
+
16
+ ## Thêm gì so với endpoint
17
+
18
+ ### A · Kỹ thuật thiết kế phải thấy được trong code *(§8)*
19
+
20
+ - **Phân lớp tương đương**: mỗi lớp có ít nhất một ca. Chỉ kiểm ca hợp lệ ⇒ **MAJOR**
21
+ - **Giá trị biên**: với trường có giới hạn, phải có `min-1` · `min` · `max` · `max+1`.
22
+ Thiếu hẳn phân tích biên cho trường có ràng buộc ⇒ **MAJOR**
23
+ - **Phủ HTTP method**: gọi method không được hỗ trợ phải trả **405**; thiếu ⇒ **MINOR**
24
+
25
+ ### B · Payload injection *(§9.2)*
26
+
27
+ - Payload **hard-code rải trong spec** ⇒ **MAJOR** — gom vào `data/`, một bộ dùng cho nhiều endpoint
28
+ - Bộ mẫu thiếu hẳn một họ *(SQL · NoSQL · command · path traversal · XSS lưu trữ)* ⇒ **MINOR**
29
+ kèm nêu rõ họ nào thiếu
30
+
31
+ ### C · Mong đợi phải cụ thể
32
+
33
+ - Mong đợi đúng là **400/422 + thông điệp lỗi có cấu trúc**, hoặc dữ liệu được làm sạch
34
+ - Assert kiểu "không sập" ⇒ **MAJOR** — một endpoint trả 200 kèm dữ liệu đã bị nhiễm vẫn "không sập"
35
+ - Assert thông điệp lỗi **không rò** stack trace / tên bảng / phiên bản ⇒ thiếu ⇒ **MINOR**
36
+
37
+ ### D · Ranh giới của trạm này
38
+
39
+ - Đây **không** phải kiểm thâm nhập. Soát script, không đánh giá mức độ an toàn của hệ thống.
40
+ Biên bản kết luận *"hệ thống an toàn"* ⇒ **MAJOR** — vượt thẩm quyền của lượt soát *(R04 tinh thần)*
41
+
42
+ ---
43
+
44
+ ## Kiểm cơ học + Output
45
+
46
+ Như `endpoint.md` Phase 3 và §Output.