@torus-engineering/tas-kit 1.8.0 → 1.9.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.
@@ -0,0 +1,173 @@
1
+ # /tas-apitest-plan $ARGUMENTS
2
+
3
+ Vai trò: SE - Software Engineer
4
+ Generate API Test Specification (Markdown) từ API Spec (OpenAPI 3.0, Markdown, YAML) hoặc phân tích code API.
5
+
6
+ ## Always / Ask / Never
7
+
8
+ | | Hành động |
9
+ |---|---|
10
+ | **Always** | Đọc toàn bộ spec hoặc phân tích code trước khi tạo test spec |
11
+ | **Always** | Tổ chức test cases theo API version — mỗi version một section riêng |
12
+ | **Always** | Append-only: không sửa sections trong version cũ đã tồn tại |
13
+ | **Always** | Coverage matrix: mỗi endpoint cần ≥1 happy path + ≥1 error path |
14
+ | **Always** | Đọc `.claude/rules/csharp/api-testing.md` để nắm convention |
15
+ | **Ask** | Khi spec không rõ expected response schema hoặc business rule |
16
+ | **Never** | Sử dụng version folder/syntax trong test spec file (dùng section headers thay vì) |
17
+ | **Never** | Bỏ qua error path — mỗi endpoint cần cover validation errors |
18
+
19
+ ## Hành động
20
+
21
+ ### Bước 1 — Locate Inputs
22
+
23
+ `$ARGUMENTS` là path đến:
24
+ - API Spec file (OpenAPI 3.0 JSON/YAML, Markdown)
25
+ - Hoặc Story ID — glob tìm `docs/epics/**/Story-{ID}*.md`
26
+ - Hoặc path tới project code API cần phân tích
27
+
28
+ Nếu không có → hỏi user:
29
+ ```
30
+ Nhập input cho /tas-apitest-plan:
31
+ 1. Path đến API Spec file (OpenAPI/Markdown/YAML)
32
+ 2. Story ID (để tìm link spec trong Story)
33
+ 3. Path đến code API cần phân tích tự động
34
+ ```
35
+
36
+ ### Bước 2 — Detect Existing Test Spec
37
+
38
+ Glob tìm `docs/tests/API-Test-Spec-*.md`.
39
+
40
+ - **Tìm thấy**: Đọc file, detect versions đã có (tìm section headers `## v{N}`)
41
+ - **Không tìm thấy**: Tạo mới với version v1
42
+
43
+ ### Bước 3 — Parse Input
44
+
45
+ **Nếu là API Spec file:**
46
+ - Đọc và parse OpenAPI/Markdown/YAML
47
+ - Thu thập cho mỗi endpoint:
48
+ - HTTP method + path, path/query params, request body schema
49
+ - Response schemas theo từng status code
50
+ - Auth requirement, description/summary
51
+ - Tags để nhóm endpoints
52
+
53
+ **Nếu là Story:**
54
+ - Đọc Story để tìm link spec trong `## Technical Plan` hoặc `## Acceptance Criteria`
55
+ - Parse spec như trên
56
+ - Thêm AC mapping vào test spec
57
+
58
+ **Nếu là code path:**
59
+ - Glob tìm controller/handler files (`.cs`, `.ts`, `.py` tùy stack)
60
+ - Phân tích attributes/routes để phát hiện endpoints
61
+ - Extract DTO classes để biết request/response schema
62
+ - Hỏi user confirm nếu detect không rõ
63
+
64
+ ### Bước 4 — Detect API Version
65
+
66
+ Ưu tiên theo thứ tự:
67
+ 1. `info.version` trong OpenAPI
68
+ 2. Prefix trong URL path (v1/, v2/)
69
+ 3. Hỏi user
70
+
71
+ Version format: `v1`, `v2` (không có dot).
72
+
73
+ ### Bước 5 — Determine Output Path
74
+
75
+ Output: `docs/tests/API-Test-Spec-{slug}.md`
76
+
77
+ **Slug generation:**
78
+ - Từ `api_name` trong spec → lowercase, replace spaces với dashes
79
+ - Hoặc hỏi user nhập slug ngắn gọn (ví dụ: `users`, `orders`, `products`)
80
+
81
+ ### Bước 6 — Determine Update Mode
82
+
83
+ Nếu spec file đã tồn tại và version đã có:
84
+ - **Append mode** (default): thêm test cases mới vào cuối section version hiện tại
85
+ - Hỏi user nếu muốn tạo version mới (v2, v3...):
86
+
87
+ ```
88
+ Spec file đã có với version {current}. Bạn muốn:
89
+ 1. Append test cases vào version {current} (default)
90
+ 2. Tạo version mới (v{next}) cho test cases
91
+ ```
92
+
93
+ ### Bước 7 — Generate Test Spec
94
+
95
+ Đọc template `.tas/templates/API-Test-Spec.md` để nắm cấu trúc.
96
+
97
+ **Phân tích endpoints để tạo coverage matrix:**
98
+
99
+ Với mỗi endpoint, generate test cases cho:
100
+ 1. **Happy path** (2xx) — luôn có
101
+ 2. **Unauthorized** (401) — nếu endpoint yêu cầu auth
102
+ 3. **Forbidden** (403) — nếu có RBAC/ownership check
103
+ 4. **Not found** (404) — nếu có path param
104
+ 5. **Validation error** (400/422) — nếu có required fields hoặc business rules
105
+ 6. **Business rules** — từ Story ACs hoặc spec descriptions
106
+
107
+ **Coverage matrix format:**
108
+ ```
109
+ | Endpoint | Happy Path | 401 Unauthorized | 403 Forbidden | 404 Not Found | 400/422 Validation | Business Rule |
110
+ |----------|:---------:|:----------------:|:-------------:|:-------------:|:------------------:|:-------------:|
111
+ | GET /api/users | ✓ | ✓ | | | | |
112
+ | POST /api/users | ✓ | ✓ | | | ✓ | |
113
+ ```
114
+
115
+ **Test case detail format:**
116
+ ```
117
+ #### TC-XXX: {Title} — {Modifier}
118
+ - **Endpoint**: `{METHOD} {path}`
119
+ - **Auth**: Required/Not Required
120
+ - **Preconditions**:
121
+ - {List preconditions}
122
+ - **Request Query/Path/Body**:
123
+ - {Request details}
124
+ - **Expected Response**:
125
+ - Status: {code}
126
+ - Body: {schema}
127
+ - **Assertions**:
128
+ - {List assertions}
129
+ - **AC Reference**: AC-{N} (nếu có)
130
+ - **Test Method Name**: `{Method}_{Resource}_Returns{Status}_When{Condition}`
131
+ ```
132
+
133
+ ### Bước 8 — Write Test Spec File
134
+
135
+ **File chưa tồn tại:** Tạo mới từ template.
136
+
137
+ **File đã tồn tại (append mode):**
138
+ - Đọc file hiện tại
139
+ - Find section `## v{N}` mà đang làm việc
140
+ - Append test cases mới vào cuối section trước `## Version History` hoặc `## Changelog`
141
+ - Preserve toàn bộ content cũ
142
+
143
+ ### Bước 9 — Summary
144
+
145
+ Hiển thị:
146
+ 1. Output file path
147
+ 2. Number of endpoints detected
148
+ 3. Number of test cases generated
149
+ 4. Coverage matrix
150
+ 5. Next steps:
151
+ - Review test spec file
152
+ - Run `/tas-apitest docs/tests/API-Test-Spec-{slug}.md` để generate code
153
+
154
+ ```
155
+ ## API Test Spec Generated
156
+
157
+ **Output**: `docs/tests/API-Test-Spec-{slug}.md`
158
+ **Version**: v{N}
159
+ **Endpoints**: {N}
160
+ **Test Cases**: {N}
161
+
162
+ ### Coverage Matrix
163
+ [Print coverage matrix]
164
+
165
+ ### Next Steps
166
+ 1. Review test spec: `docs/tests/API-Test-Spec-{slug}.md`
167
+ 2. Generate test code: `/tas-apitest docs/tests/API-Test-Spec-{slug}.md`
168
+ 3. Run tests: `dotnet test tests/ApiTests/`
169
+ ```
170
+
171
+ ## Bước cuối — Token Log
172
+
173
+ Invoke skill `token-logger`: ghi AI Usage Log vào test spec file.
@@ -0,0 +1,143 @@
1
+ # /tas-apitest $ARGUMENTS
2
+
3
+ Vai trò: SE - Software Engineer
4
+ Generate .NET xUnit automation test project cho REST API từ API Test Spec file (Markdown).
5
+
6
+ ## Always / Ask / Never
7
+
8
+ | | Hành động |
9
+ |---|---|
10
+ | **Always** | Đọc toàn bộ API Test Spec file trước khi generate bất kỳ test nào |
11
+ | **Always** | Tổ chức tests theo API version — mỗi version một folder riêng |
12
+ | **Always** | Append-only: không sửa files trong version folder cũ đã tồn tại |
13
+ | **Always** | URL và credentials ra `appsettings.json` — không hardcode trong code |
14
+ | **Always** | XML doc comment trên mỗi test method |
15
+ | **Ask** | Khi test spec không rõ expected response schema |
16
+ | **Never** | Sửa hoặc xóa test files của version cũ hơn |
17
+ | **Never** | Hardcode base URL, API key, credentials trong test code |
18
+ | **Never** | Bỏ qua error path — mỗi endpoint cần ≥1 happy path + ≥1 error path |
19
+
20
+ ## Hành động
21
+
22
+ ### Bước 1 — Locate Input
23
+
24
+ `$ARGUMENTS` là path đến API Test Spec file: `docs/tests/API-Test-Spec-{slug}.md`.
25
+
26
+ Nếu không có → hỏi user:
27
+ ```
28
+ Nhập path đến API Test Spec file (vd: docs/tests/API-Test-Spec-users.md)
29
+ ```
30
+
31
+ ### Bước 2 — Parse API Test Spec
32
+
33
+ Đọc `.claude/rules/csharp/api-testing.md` để nắm convention trước khi generate.
34
+
35
+ Từ API Test Spec file, thu thập:
36
+ - API version
37
+ - Endpoints với method, path, params
38
+ - Test cases theo từng endpoint (TC-XXX)
39
+ - Request/response schemas
40
+ - Auth requirements
41
+ - Test data requirements
42
+ - Setup/teardown notes
43
+
44
+ ### Bước 3 — Detect Existing Test Project
45
+
46
+ Glob tìm `**/ApiTests/*.csproj`, `**/Api.Tests/*.csproj`, `**/IntegrationTests/*.csproj`.
47
+
48
+ - **Tìm thấy**: Đọc framework đang dùng (xUnit/NUnit/MSTest), glob `v*/` folders để biết versions đã có.
49
+ - **Không tìm thấy**: Tạo mới tại `tests/ApiTests/` với xUnit + FluentAssertions (per `csharp/testing.md`).
50
+
51
+ ### Bước 4 — Get API Version from Spec
52
+
53
+ Đọc version từ API Test Spec file (tìm frontmatter `api_version` hoặc section headers `## v{N}`).
54
+
55
+ Version folder: lowercase, không có dot — `v1`, `v2` (không phải `v1.0`).
56
+
57
+ ### Bước 5 — Generate Infrastructure (chỉ khi tạo project mới)
58
+
59
+ Đọc `.claude/rules/csharp/api-testing.md` section **Project Structure** và **Config Pattern** để generate:
60
+ - `ApiTests.csproj` với packages chuẩn
61
+ - `appsettings.json` (base) + `appsettings.Test.json` + `appsettings.Staging.json` với values từ spec
62
+ - `Shared/TestBase.cs` — load config, HttpClient, helper methods
63
+ - `Shared/ApiTestSettings.cs` — strongly typed settings
64
+ - `.gitignore` cho `appsettings.*.local.json`
65
+
66
+ ### Bước 6 — Generate Test Classes từ Spec
67
+
68
+ Nhóm endpoints theo resource. Mỗi nhóm → `tests/ApiTests/{version}/{Resource}ApiTests.cs`.
69
+
70
+ Với mỗi test case (TC-XXX) trong spec:
71
+ 1. Đọc test case details
72
+ 2. Map sang test method với naming: `{HttpMethod}_{Resource}_Returns{Status}_When{Condition}`
73
+ 3. Generate XML doc từ test case title
74
+ 4. Generate assertions từ expected response
75
+ 5. Add AC reference comment nếu có
76
+
77
+ Test class header comment:
78
+ ```csharp
79
+ // ============================================================
80
+ // {Resource} API Tests — v{N}
81
+ // Spec: docs/tests/API-Test-Spec-{slug}.md
82
+ // Generated: {YYYY-MM-DD}
83
+ // Story: {ID} (if applicable)
84
+ // APPEND-ONLY: không sửa methods đã tồn tại.
85
+ // ============================================================
86
+ ```
87
+
88
+ ### Bước 7 — Append-Only Guard
89
+
90
+ Trước khi ghi file: kiểm tra file đã tồn tại chưa.
91
+ - **File chưa có** → tạo mới bình thường.
92
+ - **File đã có** trong version folder → check từng test method:
93
+ - Method đã tồn tại (cùng tên) → **SKIP**, không ghi đè
94
+ - Method chưa có → append vào cuối class
95
+
96
+ ### Bước 8 — Generate Test Data Files (nếu spec yêu cầu)
97
+
98
+ Nếu spec có `test-data.{env}.json` references:
99
+ - Tạo `tests/ApiTests/data/test-data.Test.json` với sample data từ spec
100
+ - Hướng dẫn user tạo `test-data.Staging.json` và `test-data.local.json`
101
+
102
+ ### Bước 9 — Post-Generate Review
103
+
104
+ Launch `csharp-reviewer` agent:
105
+ > Review `tests/ApiTests/{version}/`. Đọc `.claude/rules/csharp/testing.md` + `.claude/rules/csharp/api-testing.md`.
106
+ > Tập trung: async/await, HttpClient disposal, assertion completeness, XML doc coverage.
107
+ > Format: Critical / High / Medium / Low với file:line.
108
+
109
+ Gate: Critical/High → fix ngay. Medium/Low → list gợi ý.
110
+
111
+ ### Bước 10 — Summary
112
+
113
+ Hiển thị:
114
+ 1. Test project path
115
+ 2. Number of test classes generated
116
+ 3. Number of test methods generated
117
+ 4. Coverage matrix (so với spec)
118
+ 5. Next steps để chạy tests
119
+
120
+ ```
121
+ ## API Tests Generated
122
+
123
+ **Project**: `tests/ApiTests/`
124
+ **Version**: v{N}
125
+ **Test Classes**: {N}
126
+ **Test Methods**: {N}
127
+
128
+ ### Generated Files
129
+ - tests/ApiTests/{version}/{Resource}ApiTests.cs
130
+ - tests/ApiTests/Shared/TestBase.cs (if new project)
131
+
132
+ ### Coverage (vs Spec)
133
+ [Print coverage table: spec test cases vs generated methods]
134
+
135
+ ### Next Steps
136
+ 1. Configure test environment: edit tests/ApiTests/appsettings.Test.json
137
+ 2. Add test data: tests/ApiTests/data/test-data.Test.json
138
+ 3. Run tests: `dotnet test tests/ApiTests/`
139
+ ```
140
+
141
+ ## Bước cuối — Token Log
142
+
143
+ Invoke skill `token-logger`: ghi AI Usage Log vào API Test Spec file.
@@ -0,0 +1,400 @@
1
+ ---
2
+ api_name:
3
+ api_slug:
4
+ api_version:
5
+ spec_source:
6
+ code_path:
7
+ status:
8
+ created_date:
9
+ updated_date:
10
+ executor:
11
+ story_id:
12
+ framework: xUnit
13
+ ---
14
+
15
+ # API Test Specification: {API Name}
16
+
17
+ **API Version**: v{api_version}
18
+ **Framework**: {framework}
19
+ **Author**: @[executor]
20
+ **Created**: [created_date]
21
+ **Updated**: [updated_date]
22
+ **Status**: [status] (Draft | Review | Approved | Deprecated)
23
+ **Spec Source**: [spec_source]
24
+ **Code Path**: [code_path]
25
+ **Story**: [story_id] (if applicable)
26
+
27
+ ---
28
+
29
+ ## Version History
30
+
31
+ > Mỗi API version có section riêng biệt. APPEND-ONLY: không sửa version cũ.
32
+
33
+ | Version | Status | Created | Description |
34
+ |---------|--------|---------|-------------|
35
+ | v1 | Draft | [created_date] | Initial version |
36
+ | v2 | Draft | [updated_date] | Added new endpoints |
37
+
38
+ ---
39
+
40
+ ## Test Environment Setup
41
+
42
+ ### Configuration (appsettings.json)
43
+
44
+ ```json
45
+ {
46
+ "ApiTest": {
47
+ "BaseUrl": "https://localhost:5001",
48
+ "TimeoutSeconds": 30,
49
+ "Auth": {
50
+ "Type": "Bearer",
51
+ "TokenEndpoint": "/api/auth/token",
52
+ "Username": "",
53
+ "Password": ""
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ### Environment-Specific Overrides
60
+
61
+ | Environment | BaseUrl | Notes |
62
+ |-------------|---------|-------|
63
+ | Local | https://localhost:5001 | Development environment |
64
+ | Test | https://test-api.example.com | Shared test environment |
65
+ | Staging | https://staging-api.example.com | Pre-production |
66
+ | Production | https://api.example.com | Smoke tests only |
67
+
68
+ ### Test Data Requirements
69
+
70
+ | Data Item | Value | Source | Environment-Specific | Notes |
71
+ |-----------|-------|--------|---------------------|-------|
72
+ | Test User Email | test@example.com | test-data.{env}.json | Yes | Different per env |
73
+ | Test User Password | (from .env) | process.env.APITEST__AUTH__PASSWORD | Yes | NEVER hardcode |
74
+ | Auth Token | Generated at runtime | POST /api/auth/token | Yes | Refresh per test class |
75
+ | {Entity} ID | {value} | test-data.{env}.json | Yes | Pre-seeded data |
76
+
77
+ ### Setup/Teardown Notes
78
+
79
+ **Before All Tests:**
80
+ - Authenticate and store token for authenticated requests
81
+ - Seed test data if required
82
+ - Configure HttpClient with base address and timeout
83
+
84
+ **After All Tests:**
85
+ - Dispose HttpClient
86
+ - Clean up test data (unless debugging needed)
87
+
88
+ **Before Each Test:**
89
+ - Reset state if needed (clear headers, reset counters)
90
+
91
+ **After Each Test:**
92
+ - Log test result
93
+ - Capture response on failure for debugging
94
+
95
+ ---
96
+
97
+ ## v{N} — Test Cases
98
+
99
+ ### Endpoints Overview
100
+
101
+ | Method | Path | Description | Auth Required |
102
+ |--------|------|-------------|---------------|
103
+ | GET | /api/users | List users | Yes |
104
+ | POST | /api/users | Create user | Yes |
105
+ | GET | /api/users/{id} | Get user by ID | Yes |
106
+ | PUT | /api/users/{id} | Update user | Yes |
107
+ | DELETE | /api/users/{id} | Delete user | Yes |
108
+
109
+ ### Coverage Matrix
110
+
111
+ | Endpoint | Happy Path | 401 Unauthorized | 403 Forbidden | 404 Not Found | 400/422 Validation | Business Rule |
112
+ |----------|:---------:|:----------------:|:-------------:|:-------------:|:------------------:|:-------------:|
113
+ | GET /api/users | ✓ | ✓ | | | | |
114
+ | POST /api/users | ✓ | ✓ | | | ✓ | |
115
+ | GET /api/users/{id} | ✓ | ✓ | | ✓ | | |
116
+ | PUT /api/users/{id} | ✓ | ✓ | | ✓ | ✓ | |
117
+ | DELETE /api/users/{id} | ✓ | ✓ | ✓ | ✓ | | |
118
+
119
+ ---
120
+
121
+ ### Test Case Details
122
+
123
+ #### GET /api/users — List Users
124
+
125
+ ##### TC-001: Happy Path — Returns Paginated User List
126
+ - **Endpoint**: `GET /api/users?page=1&limit=10`
127
+ - **Auth**: Required (Bearer token)
128
+ - **Preconditions**:
129
+ - Valid authentication token
130
+ - At least 10 users exist in database
131
+ - **Request Query Params**:
132
+ - `page`: 1
133
+ - `limit`: 10
134
+ - **Expected Response**:
135
+ - Status: 200 OK
136
+ - Body:
137
+ ```json
138
+ {
139
+ "data": [
140
+ {
141
+ "id": "guid",
142
+ "email": "user@example.com",
143
+ "name": "John Doe",
144
+ "role": "User",
145
+ "createdAt": "2024-01-01T00:00:00Z"
146
+ }
147
+ ],
148
+ "total": 100,
149
+ "page": 1,
150
+ "limit": 10
151
+ }
152
+ ```
153
+ - **Assertions**:
154
+ - Response status is 200
155
+ - `data` is array with length ≤ 10
156
+ - Each item has required fields: id, email, name, role, createdAt
157
+ - `total` ≥ 0
158
+ - `page` and `limit` match request
159
+ - **AC Reference**: N/A (API spec)
160
+ - **Test Method Name**: `Get_Users_Returns200_WhenAuthenticated`
161
+
162
+ ##### TC-002: Security — Returns 401 When No Token
163
+ - **Endpoint**: `GET /api/users`
164
+ - **Auth**: Not provided
165
+ - **Preconditions**: None
166
+ - **Expected Response**:
167
+ - Status: 401 Unauthorized
168
+ - Body contains error message
169
+ - **Assertions**:
170
+ - Response status is 401
171
+ - **AC Reference**: N/A
172
+ - **Test Method Name**: `Get_Users_Returns401_WhenNotAuthenticated`
173
+
174
+ ##### TC-003: Edge Case — Empty List When No Users Exist
175
+ - **Endpoint**: `GET /api/users`
176
+ - **Auth**: Required
177
+ - **Preconditions**:
178
+ - Database is empty or no users match filter
179
+ - **Expected Response**:
180
+ - Status: 200 OK
181
+ - Body:
182
+ ```json
183
+ {
184
+ "data": [],
185
+ "total": 0,
186
+ "page": 1,
187
+ "limit": 10
188
+ }
189
+ ```
190
+ - **Assertions**:
191
+ - Response status is 200
192
+ - `data` is empty array
193
+ - `total` is 0
194
+ - **AC Reference**: N/A
195
+ - **Test Method Name**: `Get_Users_ReturnsEmptyArray_WhenNoUsersExist`
196
+
197
+ #### POST /api/users — Create User
198
+
199
+ ##### TC-004: Happy Path — Creates New User
200
+ - **Endpoint**: `POST /api/users`
201
+ - **Auth**: Required
202
+ - **Request Body**:
203
+ ```json
204
+ {
205
+ "email": "newuser@example.com",
206
+ "name": "New User",
207
+ "password": "SecurePass123!",
208
+ "role": "User"
209
+ }
210
+ ```
211
+ - **Expected Response**:
212
+ - Status: 201 Created
213
+ - Body contains created user with generated `id`
214
+ - `Location` header contains URL of new resource
215
+ - **Assertions**:
216
+ - Response status is 201
217
+ - `id` is valid GUID
218
+ - `email`, `name`, `role` match request
219
+ - `password` is NOT in response
220
+ - `createdAt` is recent
221
+ - **AC Reference**: N/A
222
+ - **Test Method Name**: `Post_Users_Returns201_WhenValidRequest`
223
+
224
+ ##### TC-005: Validation — Returns 400 When Email Invalid
225
+ - **Endpoint**: `POST /api/users`
226
+ - **Auth**: Required
227
+ - **Request Body**:
228
+ ```json
229
+ {
230
+ "email": "invalid-email",
231
+ "name": "Test User",
232
+ "password": "SecurePass123!",
233
+ "role": "User"
234
+ }
235
+ ```
236
+ - **Expected Response**:
237
+ - Status: 400 Bad Request
238
+ - Body contains validation errors
239
+ - **Assertions**:
240
+ - Response status is 400
241
+ - Error message indicates email format issue
242
+ - **AC Reference**: N/A
243
+ - **Test Method Name**: `Post_Users_Returns400_WhenEmailInvalid`
244
+
245
+ ##### TC-006: Business Rule — Returns 409 When Email Already Exists
246
+ - **Endpoint**: `POST /api/users`
247
+ - **Auth**: Required
248
+ - **Preconditions**: User with email already exists
249
+ - **Request Body**:
250
+ ```json
251
+ {
252
+ "email": "existing@example.com",
253
+ "name": "Test User",
254
+ "password": "SecurePass123!",
255
+ "role": "User"
256
+ }
257
+ ```
258
+ - **Expected Response**:
259
+ - Status: 409 Conflict
260
+ - Body indicates email already registered
261
+ - **Assertions**:
262
+ - Response status is 409
263
+ - Error message mentions duplicate email
264
+ - **AC Reference**: N/A
265
+ - **Test Method Name**: `Post_Users_Returns409_WhenEmailAlreadyExists`
266
+
267
+ #### GET /api/users/{id} — Get User by ID
268
+
269
+ ##### TC-007: Happy Path — Returns User When ID Exists
270
+ - **Endpoint**: `GET /api/users/{id}`
271
+ - **Auth**: Required
272
+ - **Path Params**: `id` = valid GUID
273
+ - **Expected Response**:
274
+ - Status: 200 OK
275
+ - Body contains user details
276
+ - **Assertions**:
277
+ - Response status is 200
278
+ - All required fields present
279
+ - **AC Reference**: N/A
280
+ - **Test Method Name**: `GetById_Users_Returns200_WhenExists`
281
+
282
+ ##### TC-008: Error Path — Returns 404 When ID Not Found
283
+ - **Endpoint**: `GET /api/users/{id}`
284
+ - **Auth**: Required
285
+ - **Path Params**: `id` = valid but non-existent GUID
286
+ - **Expected Response**:
287
+ - Status: 404 Not Found
288
+ - **Assertions**:
289
+ - Response status is 404
290
+ - **AC Reference**: N/A
291
+ - **Test Method Name**: `GetById_Users_Returns404_WhenNotFound`
292
+
293
+ #### PUT /api/users/{id} — Update User
294
+
295
+ ##### TC-009: Happy Path — Updates User
296
+ - **Endpoint**: `PUT /api/users/{id}`
297
+ - **Auth**: Required
298
+ - **Request Body**:
299
+ ```json
300
+ {
301
+ "name": "Updated Name"
302
+ }
303
+ ```
304
+ - **Expected Response**:
305
+ - Status: 200 OK
306
+ - Body contains updated user
307
+ - **Assertions**:
308
+ - Response status is 200
309
+ - `name` matches request
310
+ - **AC Reference**: N/A
311
+ - **Test Method Name**: `Put_Users_Returns200_WhenValidUpdate`
312
+
313
+ ##### TC-010: Validation — Returns 400 When Name Empty
314
+ - **Endpoint**: `PUT /api/users/{id}`
315
+ - **Auth**: Required
316
+ - **Request Body**:
317
+ ```json
318
+ {
319
+ "name": ""
320
+ }
321
+ ```
322
+ - **Expected Response**:
323
+ - Status: 400 Bad Request
324
+ - **Assertions**:
325
+ - Response status is 400
326
+ - **AC Reference**: N/A
327
+ - **Test Method Name**: `Put_Users_Returns400_WhenNameEmpty`
328
+
329
+ #### DELETE /api/users/{id} — Delete User
330
+
331
+ ##### TC-011: Happy Path — Deletes User
332
+ - **Endpoint**: `DELETE /api/users/{id}`
333
+ - **Auth**: Required
334
+ - **Expected Response**:
335
+ - Status: 204 No Content
336
+ - **Assertions**:
337
+ - Response status is 204
338
+ - Subsequent GET returns 404
339
+ - **AC Reference**: N/A
340
+ - **Test Method Name**: `Delete_Users_Returns204_WhenExists`
341
+
342
+ ##### TC-012: Authorization — Returns 403 When Deleting Self
343
+ - **Endpoint**: `DELETE /api/users/{id}` where id = current user's id
344
+ - **Auth**: Required
345
+ - **Expected Response**:
346
+ - Status: 403 Forbidden
347
+ - **Assertions**:
348
+ - Response status is 403
349
+ - Error message indicates cannot delete own account
350
+ - **AC Reference**: N/A
351
+ - **Test Method Name**: `Delete_Users_Returns403_WhenDeletingSelf`
352
+
353
+ ---
354
+
355
+ ## Story-Specific Test Cases (Optional)
356
+
357
+ > Nếu spec được generate từ Story, thêm AC mapping ở đây.
358
+
359
+ | AC ID | AC Description | Test Case IDs |
360
+ |-------|----------------|---------------|
361
+ | AC-1 | {Given...When...Then...} | TC-001, TC-002 |
362
+ | AC-2 | {Given...When...Then...} | TC-004, TC-005 |
363
+
364
+ ---
365
+
366
+ ## Regression Tests (Optional)
367
+
368
+ > Test cases cho bugs đã được tìm thấy và fix.
369
+
370
+ | Bug ID | Description | Test Case ID | Date Added |
371
+ |--------|-------------|--------------|------------|
372
+ | BUG-001 | User profile missing notification_settings field | TC-R001 | 2024-01-15 |
373
+
374
+ ### TC-R001: BUG-001 Regression — notification_settings Present in Response
375
+ - **Endpoint**: `GET /api/users/{id}`
376
+ - **Auth**: Required
377
+ - **Expected Response**:
378
+ - Status: 200 OK
379
+ - Body includes `notification_settings` field
380
+ - **Assertions**:
381
+ - `notification_settings` is present and not undefined
382
+ - **Test Method Name**: `BUG_R001_NotificationSettings_IsPresent`
383
+
384
+ ---
385
+
386
+ ## Changelog
387
+
388
+ | Date | Version | Changes | Author |
389
+ |------|---------|---------|--------|
390
+ | [created_date] | v1 | Initial API test specification | @[executor] |
391
+ | [updated_date] | v2 | Added endpoints for user management | @[executor] |
392
+
393
+ ---
394
+
395
+ ## AI Usage Log
396
+
397
+ | # | Date | Command | Input (est.) | Output (est.) |
398
+ |---|------|---------|-------------|---------------|
399
+ | 1 | [created_date] | /tas-apitest-plan | ~{N}k | ~{N}k |
400
+ | **Total** | | | **~{N}k** | **~{N}k** |
@@ -1,33 +1,36 @@
1
- {
2
- "1.6.0": [
3
- ".claude/commands/tas-dev-story.md",
4
- ".claude/commands/tas-review-code.md",
5
- ".claude/commands/tas-security-check.md"
6
- ],
7
- "1.8.0": [
8
- ".claude/agents/README.md",
9
- ".claude/agents/ado-agent.md",
10
- ".claude/agents/code-architect.md",
11
- ".claude/agents/code-simplifier.md",
12
- ".claude/agents/comment-analyzer.md",
13
- ".claude/agents/conversation-analyzer.md",
14
- ".claude/agents/docs-lookup.md",
15
- ".claude/agents/harness-optimizer.md",
16
- ".claude/agents/loop-operator.md",
17
- ".claude/agents/performance-optimizer.md",
18
- ".claude/agents/pr-test-analyzer.md",
19
- ".claude/agents/pytorch-build-resolver.md",
20
- ".claude/agents/refactor-cleaner.md",
21
- ".claude/agents/seo-specialist.md",
22
- ".claude/agents/silent-failure-hunter.md",
23
- ".claude/agents/type-design-analyzer.md",
24
- ".claude/rules/common/agents.md",
25
- ".claude/rules/common/coding-style.md",
26
- ".claude/rules/common/development-workflow.md",
27
- ".claude/rules/common/git-workflow.md",
28
- ".claude/rules/common/performance.md",
29
- ".claude/skills/agent-harness-construction/SKILL.md",
30
- ".claude/skills/agent-introspection-debugging/SKILL.md",
31
- ".claude/skills/backend-patterns/SKILL.md"
32
- ]
33
- }
1
+ {
2
+ "1.6.0": [
3
+ ".claude/commands/tas-dev-story.md",
4
+ ".claude/commands/tas-review-code.md",
5
+ ".claude/commands/tas-security-check.md"
6
+ ],
7
+ "1.8.0": [
8
+ ".claude/agents/README.md",
9
+ ".claude/agents/ado-agent.md",
10
+ ".claude/agents/code-architect.md",
11
+ ".claude/agents/code-simplifier.md",
12
+ ".claude/agents/comment-analyzer.md",
13
+ ".claude/agents/conversation-analyzer.md",
14
+ ".claude/agents/docs-lookup.md",
15
+ ".claude/agents/harness-optimizer.md",
16
+ ".claude/agents/loop-operator.md",
17
+ ".claude/agents/performance-optimizer.md",
18
+ ".claude/agents/pr-test-analyzer.md",
19
+ ".claude/agents/pytorch-build-resolver.md",
20
+ ".claude/agents/refactor-cleaner.md",
21
+ ".claude/agents/seo-specialist.md",
22
+ ".claude/agents/silent-failure-hunter.md",
23
+ ".claude/agents/type-design-analyzer.md",
24
+ ".claude/rules/common/agents.md",
25
+ ".claude/rules/common/coding-style.md",
26
+ ".claude/rules/common/development-workflow.md",
27
+ ".claude/rules/common/git-workflow.md",
28
+ ".claude/rules/common/performance.md",
29
+ ".claude/skills/agent-harness-construction/SKILL.md",
30
+ ".claude/skills/agent-introspection-debugging/SKILL.md",
31
+ ".claude/skills/backend-patterns/SKILL.md"
32
+ ],
33
+ "1.9.0": [
34
+ ".claude/commands/tas-api-test.md"
35
+ ]
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@torus-engineering/tas-kit",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "Torus Agentic SDLC Kit — Collection of commands, skills, rules, hooks, agents and workflows for modern AI-First SDLC",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,95 +0,0 @@
1
- # /tas-api-test $ARGUMENTS
2
-
3
- Vai trò: SE - Software Engineer
4
- Generate .NET xUnit automation test project cho REST API từ spec (OpenAPI 3.0, Markdown, YAML).
5
-
6
- ## Always / Ask / Never
7
-
8
- | | Hành động |
9
- |---|---|
10
- | **Always** | Đọc toàn bộ spec trước khi generate bất kỳ test nào |
11
- | **Always** | Tổ chức tests theo API version — mỗi version một folder riêng |
12
- | **Always** | Append-only: không sửa files trong version folder cũ đã tồn tại |
13
- | **Always** | URL và credentials ra `appsettings.json` — không hardcode trong code |
14
- | **Always** | XML doc comment trên mỗi test method |
15
- | **Ask** | Khi spec không rõ expected response schema |
16
- | **Never** | Sửa hoặc xóa test files của version cũ hơn |
17
- | **Never** | Hardcode base URL, API key, credentials trong test code |
18
- | **Never** | Bỏ qua error path — mỗi endpoint cần ≥1 happy path + ≥1 error path |
19
-
20
- ## Hành động
21
-
22
- ### Bước 1 — Locate Inputs
23
-
24
- `$ARGUMENTS` là path đến spec file hoặc Story ID. Nếu không có → hỏi user.
25
-
26
- Nếu là Story ID: glob tìm `docs/epics/**/Story-{ID}*.md`, đọc Story để tìm link spec trong `## Technical Plan` hoặc `## Acceptance Criteria`.
27
-
28
- ### Bước 2 — Parse API Spec
29
-
30
- Đọc `.claude/rules/csharp/api-testing.md` để nắm convention trước khi generate.
31
-
32
- Từ spec, thu thập cho mỗi endpoint:
33
- - HTTP method + path, path/query params, request body schema
34
- - Response schemas theo từng status code
35
- - Auth requirement, description/summary
36
-
37
- Nếu có Story: đọc thêm `## Acceptance Criteria` để bổ sung business rule test cases.
38
-
39
- ### Bước 3 — Detect Existing Test Project
40
-
41
- Glob tìm `**/ApiTests/*.csproj`, `**/Api.Tests/*.csproj`, `**/IntegrationTests/*.csproj`.
42
-
43
- - **Tìm thấy**: Đọc framework đang dùng (xUnit/NUnit/MSTest), glob `v*/` folders để biết versions đã có.
44
- - **Không tìm thấy**: Tạo mới tại `tests/ApiTests/` với xUnit + FluentAssertions (per `csharp/testing.md`).
45
-
46
- ### Bước 4 — Detect API Version
47
-
48
- Ưu tiên theo thứ tự: `info.version` trong OpenAPI → prefix trong URL path → hỏi user.
49
- Version folder: lowercase, không có dot — `v1`, `v2` (không phải `v1.0`).
50
-
51
- ### Bước 5 — Generate Infrastructure (chỉ khi tạo project mới)
52
-
53
- Đọc `.claude/rules/csharp/api-testing.md` section **Project Structure** và **Config Pattern** để generate:
54
- - `ApiTests.csproj` với packages chuẩn
55
- - `appsettings.json` (base) + `appsettings.Test.json` + `appsettings.Staging.json`
56
- - `Shared/TestBase.cs` — load config, HttpClient, helper methods
57
- - `Shared/ApiTestSettings.cs` — strongly typed settings
58
- - `.gitignore` cho `appsettings.*.local.json`
59
-
60
- ### Bước 6 — Generate Test Classes
61
-
62
- Nhóm endpoints theo resource/tag. Mỗi nhóm → `tests/ApiTests/{version}/{Resource}ApiTests.cs`.
63
-
64
- Với mỗi endpoint, generate tối thiểu:
65
- 1. Happy path (2xx)
66
- 2. Unauthorized (401) — nếu endpoint yêu cầu auth
67
- 3. Not found (404) — nếu có path param
68
- 4. Validation error (400/422) — nếu có required fields
69
-
70
- Từ Story ACs: thêm test methods tương ứng, comment rõ `// AC: {AC text}`.
71
-
72
- Đầu mỗi file: block comment ghi `Spec`, `Generated date`, `Story ID`, và nhắc **APPEND-ONLY rule**.
73
-
74
- ### Bước 7 — Append-Only Guard
75
-
76
- Trước khi ghi file: kiểm tra file đã tồn tại chưa.
77
- - File chưa có → tạo mới bình thường.
78
- - File đã tồn tại trong version folder → **DỪNG**, thông báo tên file cho user tự edit thủ công.
79
-
80
- ### Bước 8 — Post-Generate Review
81
-
82
- Launch `csharp-reviewer` agent:
83
- > Review `tests/ApiTests/{version}/`. Đọc `.claude/rules/csharp/testing.md` + `.claude/rules/csharp/api-testing.md`.
84
- > Tập trung: async/await, HttpClient disposal, assertion completeness, XML doc coverage.
85
- > Format: Critical / High / Medium / Low với file:line.
86
-
87
- Gate: Critical/High → fix ngay. Medium/Low → list gợi ý.
88
-
89
- ### Bước 9 — Summary
90
-
91
- Hiển thị bảng coverage (endpoint × test type: ✓/—) và next steps để chạy tests.
92
-
93
- ## Bước cuối — Token Log
94
-
95
- Invoke skill `token-logger`: ghi AI Usage Log vào spec file hoặc Story đang làm việc.