@esimplicitylabs/katalyst-xspec 0.6.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/LICENSE +7 -0
- package/README.md +69 -0
- package/bin/katalyst-xspec.cjs +54 -0
- package/cli/init.cjs +679 -0
- package/cli/stubs.cjs +365 -0
- package/cli/upgrade.cjs +1014 -0
- package/dist/chunk-ACAXOGKZ.js +1611 -0
- package/dist/index.d.ts +881 -0
- package/dist/index.js +1091 -0
- package/dist/steps/index.d.ts +151 -0
- package/dist/steps/index.js +50 -0
- package/package.json +80 -0
- package/scripts/postinstall.cjs +85 -0
- package/skills/katalyst-bdd-architecture/SKILL.md +517 -0
- package/skills/katalyst-bdd-architecture/references/adapters.md +310 -0
- package/skills/katalyst-bdd-architecture/references/custom-steps.md +360 -0
- package/skills/katalyst-bdd-architecture/references/ports.md +256 -0
- package/skills/katalyst-bdd-create-test/SKILL.md +366 -0
- package/skills/katalyst-bdd-create-test/references/api-patterns.md +371 -0
- package/skills/katalyst-bdd-create-test/references/hybrid-patterns.md +420 -0
- package/skills/katalyst-bdd-create-test/references/tui-patterns.md +458 -0
- package/skills/katalyst-bdd-create-test/references/ui-patterns.md +415 -0
- package/skills/katalyst-bdd-quickstart/SKILL.md +292 -0
- package/skills/katalyst-bdd-step-reference/SKILL.md +147 -0
- package/skills/katalyst-bdd-step-reference/references/api-steps.md +247 -0
- package/skills/katalyst-bdd-step-reference/references/shared-steps.md +340 -0
- package/skills/katalyst-bdd-step-reference/references/tui-steps.md +483 -0
- package/skills/katalyst-bdd-step-reference/references/ui-steps.md +521 -0
- package/skills/katalyst-bdd-troubleshooting/SKILL.md +449 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
# API Test Patterns
|
|
2
|
+
|
|
3
|
+
Common patterns for API testing with the Katalyst BDD framework.
|
|
4
|
+
|
|
5
|
+
## Basic CRUD Patterns
|
|
6
|
+
|
|
7
|
+
### List Resources
|
|
8
|
+
|
|
9
|
+
```gherkin
|
|
10
|
+
@api
|
|
11
|
+
Scenario: List all [resources]
|
|
12
|
+
Given I am authenticated as an admin via API
|
|
13
|
+
When I GET "/[endpoint]"
|
|
14
|
+
Then the response status should be 200
|
|
15
|
+
And the response should be a JSON array
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Get Single Resource
|
|
19
|
+
|
|
20
|
+
```gherkin
|
|
21
|
+
@api
|
|
22
|
+
Scenario: Get [resource] by ID
|
|
23
|
+
Given I am authenticated as an admin via API
|
|
24
|
+
When I GET "/[endpoint]/1"
|
|
25
|
+
Then the response status should be 200
|
|
26
|
+
And the response should be a JSON object
|
|
27
|
+
And the value at "id" should equal "1"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Create Resource
|
|
31
|
+
|
|
32
|
+
```gherkin
|
|
33
|
+
@api
|
|
34
|
+
Scenario: Create [resource]
|
|
35
|
+
Given I am authenticated as an admin via API
|
|
36
|
+
Given I generate a UUID and store as "runId"
|
|
37
|
+
When I POST "/[endpoint]" with JSON body:
|
|
38
|
+
"""
|
|
39
|
+
{
|
|
40
|
+
"name": "Test {runId}",
|
|
41
|
+
"email": "test-{runId}@example.com"
|
|
42
|
+
}
|
|
43
|
+
"""
|
|
44
|
+
Then the response status should be 201
|
|
45
|
+
And I store the value at "id" as "resourceId"
|
|
46
|
+
And the value at "name" should equal "Test {runId}"
|
|
47
|
+
Given I register cleanup DELETE "/[endpoint]/{resourceId}"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Update Resource (Full)
|
|
51
|
+
|
|
52
|
+
```gherkin
|
|
53
|
+
@api
|
|
54
|
+
Scenario: Update [resource] with PUT
|
|
55
|
+
Given I am authenticated as an admin via API
|
|
56
|
+
# First create the resource
|
|
57
|
+
When I POST "/[endpoint]" with JSON body:
|
|
58
|
+
"""
|
|
59
|
+
{ "name": "Original", "status": "draft" }
|
|
60
|
+
"""
|
|
61
|
+
Then the response status should be 201
|
|
62
|
+
And I store the value at "id" as "resourceId"
|
|
63
|
+
Given I register cleanup DELETE "/[endpoint]/{resourceId}"
|
|
64
|
+
|
|
65
|
+
# Then update it
|
|
66
|
+
When I PUT "/[endpoint]/{resourceId}" with JSON body:
|
|
67
|
+
"""
|
|
68
|
+
{ "name": "Updated", "status": "published" }
|
|
69
|
+
"""
|
|
70
|
+
Then the response status should be 200
|
|
71
|
+
And the value at "name" should equal "Updated"
|
|
72
|
+
And the value at "status" should equal "published"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Update Resource (Partial)
|
|
76
|
+
|
|
77
|
+
```gherkin
|
|
78
|
+
@api
|
|
79
|
+
Scenario: Partial update with PATCH
|
|
80
|
+
Given I am authenticated as an admin via API
|
|
81
|
+
When I PATCH "/[endpoint]/{resourceId}" with JSON body:
|
|
82
|
+
"""
|
|
83
|
+
{ "status": "active" }
|
|
84
|
+
"""
|
|
85
|
+
Then the response status should be 200
|
|
86
|
+
And the value at "status" should equal "active"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Delete Resource
|
|
90
|
+
|
|
91
|
+
```gherkin
|
|
92
|
+
@api
|
|
93
|
+
Scenario: Delete [resource]
|
|
94
|
+
Given I am authenticated as an admin via API
|
|
95
|
+
# Create resource to delete
|
|
96
|
+
When I POST "/[endpoint]" with JSON body:
|
|
97
|
+
"""
|
|
98
|
+
{ "name": "To Delete" }
|
|
99
|
+
"""
|
|
100
|
+
Then the response status should be 201
|
|
101
|
+
And I store the value at "id" as "resourceId"
|
|
102
|
+
|
|
103
|
+
# Delete it
|
|
104
|
+
When I DELETE "/[endpoint]/{resourceId}"
|
|
105
|
+
Then the response status should be 204
|
|
106
|
+
|
|
107
|
+
# Verify it's gone
|
|
108
|
+
When I GET "/[endpoint]/{resourceId}"
|
|
109
|
+
Then the response status should be 404
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Authentication Patterns
|
|
113
|
+
|
|
114
|
+
### Admin Authentication
|
|
115
|
+
|
|
116
|
+
```gherkin
|
|
117
|
+
Background:
|
|
118
|
+
Given I am authenticated as an admin via API
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### User Authentication
|
|
122
|
+
|
|
123
|
+
```gherkin
|
|
124
|
+
Background:
|
|
125
|
+
Given I am authenticated as a user via API
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Custom Token Authentication
|
|
129
|
+
|
|
130
|
+
```gherkin
|
|
131
|
+
Scenario: Use custom bearer token
|
|
132
|
+
Given I set header "Authorization" to "Bearer custom-token-here"
|
|
133
|
+
When I GET "/protected-endpoint"
|
|
134
|
+
Then the response status should be 200
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Token from Variable
|
|
138
|
+
|
|
139
|
+
```gherkin
|
|
140
|
+
Scenario: Login and use token
|
|
141
|
+
When I POST "/auth/login" with JSON body:
|
|
142
|
+
"""
|
|
143
|
+
{ "email": "user@example.com", "password": "secret" }
|
|
144
|
+
"""
|
|
145
|
+
Then the response status should be 200
|
|
146
|
+
And I store the value at "token" as "authToken"
|
|
147
|
+
|
|
148
|
+
Given I set bearer token from variable "authToken"
|
|
149
|
+
When I GET "/me"
|
|
150
|
+
Then the response status should be 200
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Error Handling Patterns
|
|
154
|
+
|
|
155
|
+
### Not Found
|
|
156
|
+
|
|
157
|
+
```gherkin
|
|
158
|
+
@api
|
|
159
|
+
Scenario: Resource not found
|
|
160
|
+
Given I am authenticated as an admin via API
|
|
161
|
+
When I GET "/[endpoint]/99999"
|
|
162
|
+
Then the response status should be 404
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Validation Error
|
|
166
|
+
|
|
167
|
+
```gherkin
|
|
168
|
+
@api
|
|
169
|
+
Scenario: Invalid data returns 400
|
|
170
|
+
Given I am authenticated as an admin via API
|
|
171
|
+
When I POST "/[endpoint]" with JSON body:
|
|
172
|
+
"""
|
|
173
|
+
{ "email": "not-valid-email" }
|
|
174
|
+
"""
|
|
175
|
+
Then the response status should be 400
|
|
176
|
+
And the value at "error" should contain "email"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Unauthorized
|
|
180
|
+
|
|
181
|
+
```gherkin
|
|
182
|
+
@api
|
|
183
|
+
Scenario: Unauthorized access
|
|
184
|
+
# No authentication
|
|
185
|
+
When I GET "/admin/users"
|
|
186
|
+
Then the response status should be 401
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Forbidden
|
|
190
|
+
|
|
191
|
+
```gherkin
|
|
192
|
+
@api
|
|
193
|
+
Scenario: User cannot access admin endpoint
|
|
194
|
+
Given I am authenticated as a user via API
|
|
195
|
+
When I GET "/admin/settings"
|
|
196
|
+
Then the response status should be 403
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Data Extraction Patterns
|
|
200
|
+
|
|
201
|
+
### Extract Single Value
|
|
202
|
+
|
|
203
|
+
```gherkin
|
|
204
|
+
And I store the value at "id" as "resourceId"
|
|
205
|
+
And I store the value at "data.user.email" as "userEmail"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Extract from Array
|
|
209
|
+
|
|
210
|
+
```gherkin
|
|
211
|
+
And I store the value at "items[0].id" as "firstItemId"
|
|
212
|
+
And I store the value at "results[0].name" as "firstName"
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Extract Nested Value
|
|
216
|
+
|
|
217
|
+
```gherkin
|
|
218
|
+
And I store the value at "response.data.attributes.name" as "attrName"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Assertion Patterns
|
|
222
|
+
|
|
223
|
+
### Exact Value Match
|
|
224
|
+
|
|
225
|
+
```gherkin
|
|
226
|
+
Then the value at "status" should equal "active"
|
|
227
|
+
Then the value at "count" should equal "10"
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Contains
|
|
231
|
+
|
|
232
|
+
```gherkin
|
|
233
|
+
Then the value at "message" should contain "success"
|
|
234
|
+
Then the value at "email" should contain "@example.com"
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Pattern Match
|
|
238
|
+
|
|
239
|
+
```gherkin
|
|
240
|
+
Then the value at "id" should match "^[a-f0-9-]{36}$"
|
|
241
|
+
Then the value at "created_at" should match "^\d{4}-\d{2}-\d{2}"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## Complex Scenarios
|
|
245
|
+
|
|
246
|
+
### Pagination
|
|
247
|
+
|
|
248
|
+
```gherkin
|
|
249
|
+
@api
|
|
250
|
+
Scenario: Paginated list
|
|
251
|
+
Given I am authenticated as an admin via API
|
|
252
|
+
When I GET "/[endpoint]?page=1&limit=10"
|
|
253
|
+
Then the response status should be 200
|
|
254
|
+
And the response should be a JSON object
|
|
255
|
+
And the value at "data" should be a JSON array
|
|
256
|
+
And the value at "meta.page" should equal "1"
|
|
257
|
+
And the value at "meta.limit" should equal "10"
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Search/Filter
|
|
261
|
+
|
|
262
|
+
```gherkin
|
|
263
|
+
@api
|
|
264
|
+
Scenario: Filter by status
|
|
265
|
+
Given I am authenticated as an admin via API
|
|
266
|
+
When I GET "/[endpoint]?status=active"
|
|
267
|
+
Then the response status should be 200
|
|
268
|
+
And the response should be a JSON array
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### Bulk Operations
|
|
272
|
+
|
|
273
|
+
```gherkin
|
|
274
|
+
@api
|
|
275
|
+
Scenario: Bulk create
|
|
276
|
+
Given I am authenticated as an admin via API
|
|
277
|
+
When I POST "/[endpoint]/bulk" with JSON body:
|
|
278
|
+
"""
|
|
279
|
+
{
|
|
280
|
+
"items": [
|
|
281
|
+
{ "name": "Item 1" },
|
|
282
|
+
{ "name": "Item 2" },
|
|
283
|
+
{ "name": "Item 3" }
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
"""
|
|
287
|
+
Then the response status should be 201
|
|
288
|
+
And the value at "created" should equal "3"
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### File Upload (Form Data)
|
|
292
|
+
|
|
293
|
+
```gherkin
|
|
294
|
+
@api
|
|
295
|
+
Scenario: Upload file
|
|
296
|
+
Given I am authenticated as an admin via API
|
|
297
|
+
Given I set header "Content-Type" to "multipart/form-data"
|
|
298
|
+
# Note: Actual file upload requires custom step implementation
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Complete Example: User Management API
|
|
302
|
+
|
|
303
|
+
```gherkin
|
|
304
|
+
@api
|
|
305
|
+
Feature: User Management API
|
|
306
|
+
As an admin
|
|
307
|
+
I want to manage users via API
|
|
308
|
+
So that I can control system access
|
|
309
|
+
|
|
310
|
+
Background:
|
|
311
|
+
Given I am authenticated as an admin via API
|
|
312
|
+
Given I generate a UUID and store as "runId"
|
|
313
|
+
|
|
314
|
+
Scenario: Create new user
|
|
315
|
+
Given I set variable "email" to "user-{runId}@test.com"
|
|
316
|
+
When I POST "/admin/users" with JSON body:
|
|
317
|
+
"""
|
|
318
|
+
{
|
|
319
|
+
"email": "{email}",
|
|
320
|
+
"name": "Test User {runId}",
|
|
321
|
+
"role": "member",
|
|
322
|
+
"department": "Engineering"
|
|
323
|
+
}
|
|
324
|
+
"""
|
|
325
|
+
Then the response status should be 201
|
|
326
|
+
And I store the value at "id" as "userId"
|
|
327
|
+
And the value at "email" should equal "{email}"
|
|
328
|
+
And the value at "role" should equal "member"
|
|
329
|
+
Given I register cleanup DELETE "/admin/users/{userId}"
|
|
330
|
+
|
|
331
|
+
Scenario: Update user role
|
|
332
|
+
# Setup: Create user
|
|
333
|
+
When I POST "/admin/users" with JSON body:
|
|
334
|
+
"""
|
|
335
|
+
{ "email": "role-test-{runId}@test.com", "name": "Role Test" }
|
|
336
|
+
"""
|
|
337
|
+
Then the response status should be 201
|
|
338
|
+
And I store the value at "id" as "userId"
|
|
339
|
+
Given I register cleanup DELETE "/admin/users/{userId}"
|
|
340
|
+
|
|
341
|
+
# Test: Update role
|
|
342
|
+
When I PATCH "/admin/users/{userId}" with JSON body:
|
|
343
|
+
"""
|
|
344
|
+
{ "role": "admin" }
|
|
345
|
+
"""
|
|
346
|
+
Then the response status should be 200
|
|
347
|
+
And the value at "role" should equal "admin"
|
|
348
|
+
|
|
349
|
+
Scenario: Deactivate user
|
|
350
|
+
# Setup: Create user
|
|
351
|
+
When I POST "/admin/users" with JSON body:
|
|
352
|
+
"""
|
|
353
|
+
{ "email": "deactivate-{runId}@test.com", "name": "Deactivate Test" }
|
|
354
|
+
"""
|
|
355
|
+
Then the response status should be 201
|
|
356
|
+
And I store the value at "id" as "userId"
|
|
357
|
+
Given I register cleanup DELETE "/admin/users/{userId}"
|
|
358
|
+
|
|
359
|
+
# Test: Deactivate
|
|
360
|
+
When I PATCH "/admin/users/{userId}" with JSON body:
|
|
361
|
+
"""
|
|
362
|
+
{ "status": "inactive" }
|
|
363
|
+
"""
|
|
364
|
+
Then the response status should be 200
|
|
365
|
+
And the value at "status" should equal "inactive"
|
|
366
|
+
|
|
367
|
+
Scenario: Search users by email domain
|
|
368
|
+
When I GET "/admin/users?email_contains=@test.com"
|
|
369
|
+
Then the response status should be 200
|
|
370
|
+
And the response should be a JSON array
|
|
371
|
+
```
|