@torus-engineering/tas-kit 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/tas-apitest-plan.md +173 -0
- package/.claude/commands/tas-apitest.md +143 -0
- package/.claude/commands/tas-security.md +7 -1
- package/.tas/README.md +334 -1588
- package/.tas/hooks/README.md +138 -0
- package/.tas/hooks/pre-commit +26 -0
- package/.tas/hooks/security-scan.js +599 -0
- package/.tas/tas-example.yaml +126 -109
- package/.tas/templates/API-Test-Spec.md +400 -0
- package/CLAUDE-Example.md +61 -58
- package/README.md +334 -82
- package/bin/cli.js +24 -7
- package/lib/deleted-files.json +36 -33
- package/lib/install.js +161 -47
- package/package.json +1 -1
- package/.claude/commands/tas-api-test.md +0 -95
package/.tas/tas-example.yaml
CHANGED
|
@@ -1,109 +1,126 @@
|
|
|
1
|
-
# .tas/tas-example.yaml - Reference template cho tas.yaml ở root
|
|
2
|
-
# Copy file này ra root (tas.yaml) và điền thông tin dự án.
|
|
3
|
-
# File này CHỈ chứa flow và logic của TAS.
|
|
4
|
-
# Tech stack, coding conventions, build commands thuộc về CLAUDE.md.
|
|
5
|
-
|
|
6
|
-
project:
|
|
7
|
-
name: "My Project"
|
|
8
|
-
code: "PROJ" # Prefix for file naming: PROJ-Epic-001, PROJ-Feature-001, etc.
|
|
9
|
-
type: greenfield # greenfield | brownfield
|
|
10
|
-
description: "Mô tả ngắn về dự án"
|
|
11
|
-
|
|
12
|
-
# Azure DevOps integration
|
|
13
|
-
ado:
|
|
14
|
-
enabled: true # false nếu project không dùng ADO
|
|
15
|
-
organization: "https://dev.azure.com/torus-bellesoft"
|
|
16
|
-
project_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
17
|
-
|
|
18
|
-
team:
|
|
19
|
-
- name: "Nguyen Van A"
|
|
20
|
-
role: pe
|
|
21
|
-
ado_id: "nguyenvana@torus.vn"
|
|
22
|
-
- name: "Tran Van B"
|
|
23
|
-
role: se
|
|
24
|
-
ado_id: "tranvanb@torus.vn"
|
|
25
|
-
- name: "Le Van C"
|
|
26
|
-
role: dse
|
|
27
|
-
ado_id: "levanc@torus.vn"
|
|
28
|
-
|
|
29
|
-
# Flow configuration
|
|
30
|
-
workflow:
|
|
31
|
-
# Phase 0: Discovery & Design (Human-led, AI-powered)
|
|
32
|
-
discovery:
|
|
33
|
-
enabled: true
|
|
34
|
-
lead: pe
|
|
35
|
-
artifacts:
|
|
36
|
-
- prd
|
|
37
|
-
- design_spec
|
|
38
|
-
- sad
|
|
39
|
-
- adr
|
|
40
|
-
- epic
|
|
41
|
-
- feature
|
|
42
|
-
- story
|
|
43
|
-
gate: ready_for_development
|
|
44
|
-
|
|
45
|
-
# Phase 1: Develop (Orchestrated Agentic)
|
|
46
|
-
develop:
|
|
47
|
-
enabled: true
|
|
48
|
-
lead: se
|
|
49
|
-
environment: test
|
|
50
|
-
use_tdd: true
|
|
51
|
-
auto_review: true
|
|
52
|
-
|
|
53
|
-
# Phase 2: Verify (Agentic + PE Review)
|
|
54
|
-
verify:
|
|
55
|
-
enabled: true
|
|
56
|
-
lead: pe
|
|
57
|
-
environment: staging
|
|
58
|
-
auto_integration_test: true
|
|
59
|
-
gate: pe_approved
|
|
60
|
-
|
|
61
|
-
# Phase 3: Deploy with Feature Flag (Agentic)
|
|
62
|
-
deploy:
|
|
63
|
-
enabled: true
|
|
64
|
-
lead: dse
|
|
65
|
-
environment: production
|
|
66
|
-
feature_flag: true
|
|
67
|
-
gate: pe_approved_production
|
|
68
|
-
|
|
69
|
-
# Phase 4: Operate (Autonomous)
|
|
70
|
-
operate:
|
|
71
|
-
enabled: false
|
|
72
|
-
lead: dse
|
|
73
|
-
environment: production
|
|
74
|
-
security_check: true
|
|
75
|
-
performance_monitor: true
|
|
76
|
-
|
|
77
|
-
# Brownfield-specific config
|
|
78
|
-
brownfield:
|
|
79
|
-
existing_docs_path: "docs/"
|
|
80
|
-
codebase_scan_on_init: true
|
|
81
|
-
|
|
82
|
-
#
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
#
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
1
|
+
# .tas/tas-example.yaml - Reference template cho tas.yaml ở root
|
|
2
|
+
# Copy file này ra root (tas.yaml) và điền thông tin dự án.
|
|
3
|
+
# File này CHỈ chứa flow và logic của TAS.
|
|
4
|
+
# Tech stack, coding conventions, build commands thuộc về CLAUDE.md.
|
|
5
|
+
|
|
6
|
+
project:
|
|
7
|
+
name: "My Project"
|
|
8
|
+
code: "PROJ" # Prefix for file naming: PROJ-Epic-001, PROJ-Feature-001, etc.
|
|
9
|
+
type: greenfield # greenfield | brownfield
|
|
10
|
+
description: "Mô tả ngắn về dự án"
|
|
11
|
+
|
|
12
|
+
# Azure DevOps integration
|
|
13
|
+
ado:
|
|
14
|
+
enabled: true # false nếu project không dùng ADO
|
|
15
|
+
organization: "https://dev.azure.com/torus-bellesoft"
|
|
16
|
+
project_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
|
17
|
+
|
|
18
|
+
team:
|
|
19
|
+
- name: "Nguyen Van A"
|
|
20
|
+
role: pe
|
|
21
|
+
ado_id: "nguyenvana@torus.vn"
|
|
22
|
+
- name: "Tran Van B"
|
|
23
|
+
role: se
|
|
24
|
+
ado_id: "tranvanb@torus.vn"
|
|
25
|
+
- name: "Le Van C"
|
|
26
|
+
role: dse
|
|
27
|
+
ado_id: "levanc@torus.vn"
|
|
28
|
+
|
|
29
|
+
# Flow configuration
|
|
30
|
+
workflow:
|
|
31
|
+
# Phase 0: Discovery & Design (Human-led, AI-powered)
|
|
32
|
+
discovery:
|
|
33
|
+
enabled: true
|
|
34
|
+
lead: pe
|
|
35
|
+
artifacts:
|
|
36
|
+
- prd
|
|
37
|
+
- design_spec
|
|
38
|
+
- sad
|
|
39
|
+
- adr
|
|
40
|
+
- epic
|
|
41
|
+
- feature
|
|
42
|
+
- story
|
|
43
|
+
gate: ready_for_development
|
|
44
|
+
|
|
45
|
+
# Phase 1: Develop (Orchestrated Agentic)
|
|
46
|
+
develop:
|
|
47
|
+
enabled: true
|
|
48
|
+
lead: se
|
|
49
|
+
environment: test
|
|
50
|
+
use_tdd: true
|
|
51
|
+
auto_review: true
|
|
52
|
+
|
|
53
|
+
# Phase 2: Verify (Agentic + PE Review)
|
|
54
|
+
verify:
|
|
55
|
+
enabled: true
|
|
56
|
+
lead: pe
|
|
57
|
+
environment: staging
|
|
58
|
+
auto_integration_test: true
|
|
59
|
+
gate: pe_approved
|
|
60
|
+
|
|
61
|
+
# Phase 3: Deploy with Feature Flag (Agentic)
|
|
62
|
+
deploy:
|
|
63
|
+
enabled: true
|
|
64
|
+
lead: dse
|
|
65
|
+
environment: production
|
|
66
|
+
feature_flag: true
|
|
67
|
+
gate: pe_approved_production
|
|
68
|
+
|
|
69
|
+
# Phase 4: Operate (Autonomous)
|
|
70
|
+
operate:
|
|
71
|
+
enabled: false
|
|
72
|
+
lead: dse
|
|
73
|
+
environment: production
|
|
74
|
+
security_check: true
|
|
75
|
+
performance_monitor: true
|
|
76
|
+
|
|
77
|
+
# Brownfield-specific config
|
|
78
|
+
brownfield:
|
|
79
|
+
existing_docs_path: "docs/"
|
|
80
|
+
codebase_scan_on_init: true
|
|
81
|
+
|
|
82
|
+
# Pre-commit security hook (installed via tas-kit install --security-hook=husky|native)
|
|
83
|
+
# See .tas/hooks/README.md for details
|
|
84
|
+
#
|
|
85
|
+
# 3-tier scan:
|
|
86
|
+
# Tier 1 (always): built-in regex scan for ~45 secret patterns — blocks
|
|
87
|
+
# Tier 2 (if on PATH): gitleaks / trufflehog — only runs if installed — blocks
|
|
88
|
+
# Tier 3 (opt-in, LOCAL ONLY): AI deep scan → writes docs/security-report.md;
|
|
89
|
+
# does NOT block. Use a personal Claude Code
|
|
90
|
+
# subscription (no API charges). Not for CI.
|
|
91
|
+
security:
|
|
92
|
+
pre_commit_hook: true # master switch; false to disable without uninstalling
|
|
93
|
+
external_scanner: auto # auto | gitleaks | trufflehog | none — tier 2
|
|
94
|
+
tool: claude # claude | codex | gemini | none — tier 3 AI (report-only)
|
|
95
|
+
deep_scan_on_every_commit: false # true = opt into tier 3 AI review each local commit
|
|
96
|
+
block_on: [critical, high] # severities that block commit (tier 1 & 2 only)
|
|
97
|
+
allow_bypass: true # print hint about SKIP_SECURITY_SCAN / --no-verify
|
|
98
|
+
|
|
99
|
+
# Template overrides (optional)
|
|
100
|
+
templates:
|
|
101
|
+
sad: ".tas/templates/SAD.md"
|
|
102
|
+
adr: ".tas/templates/ADR.md"
|
|
103
|
+
prd: ".tas/templates/PRD.md"
|
|
104
|
+
epic: ".tas/templates/Epic.md"
|
|
105
|
+
feature: ".tas/templates/Feature.md"
|
|
106
|
+
story: ".tas/templates/Story.md"
|
|
107
|
+
bug: ".tas/templates/Bug.md"
|
|
108
|
+
|
|
109
|
+
# Model mapping
|
|
110
|
+
models:
|
|
111
|
+
default: sonnet
|
|
112
|
+
commands:
|
|
113
|
+
tas-prd: sonnet
|
|
114
|
+
tas-design: sonnet
|
|
115
|
+
tas-sad: opus
|
|
116
|
+
tas-adr: opus
|
|
117
|
+
tas-epic: sonnet
|
|
118
|
+
tas-feature: sonnet
|
|
119
|
+
tas-story: sonnet
|
|
120
|
+
tas-dev: sonnet
|
|
121
|
+
tas-review-code: opus
|
|
122
|
+
tas-brainstorm: opus
|
|
123
|
+
tas-bug: sonnet
|
|
124
|
+
tas-verify: haiku
|
|
125
|
+
tas-status: haiku
|
|
126
|
+
tas-security-check: opus
|
|
@@ -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** |
|