@testsmith/api-spector 0.6.0 → 0.6.2
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/docs/ai/api-spector-scripting-reference.md +149 -0
- package/docs/ai/collection-file-format.md +110 -0
- package/docs/ai/functional-testing-guide.md +145 -0
- package/docs/ai/security-testing-guide.md +253 -0
- package/out/main/agents.js +2 -1
- package/out/main/chunks/{snapshots-Y33M1SEy.js → broker-client-WEymdqAK.js} +119 -10
- package/out/main/chunks/{cli-common-BKYgsbGB.js → cli-common-vASoDfQH.js} +3 -2
- package/out/main/chunks/data-files-Br2h3Dt2.js +85 -0
- package/out/main/chunks/escape-BwPM4Tf6.js +9 -0
- package/out/main/chunks/{handle-BFaeFA0A.js → handle-CL-nWtYA.js} +11 -2
- package/out/main/chunks/{import-D9LH0isB.js → import-DdXhO56X.js} +2 -2
- package/out/main/chunks/{request-collection-BQIo1765.js → request-collection-Hqh3I3rs.js} +75 -15
- package/out/main/chunks/{request-exec-5_3279w1.js → request-exec-DAFA6Fap.js} +19 -1
- package/out/main/chunks/{soap-handler-CWn3o6Py.js → soap-handler-BAPCALkN.js} +2 -2
- package/out/main/compare.js +2 -1
- package/out/main/contract.js +50 -147
- package/out/main/coverage.js +2 -1
- package/out/main/generate-tests.js +2 -1
- package/out/main/index.js +131 -36
- package/out/main/lib.js +2 -2
- package/out/main/mock.js +2 -1
- package/out/main/record.js +2 -1
- package/out/main/runner.js +95 -13
- package/out/main/wsdl.js +5 -4
- package/out/preload/index.js +21 -3
- package/out/renderer/assets/{GraphQLEditor-DITvPhtG.js → GraphQLEditor-DtppmZJO.js} +3 -1
- package/out/renderer/assets/{SoapEditor-Bf-oE-rS.js → SoapEditor-BwSm12wH.js} +4 -2
- package/out/renderer/assets/ajv-2MAg6kGF.js +6153 -0
- package/out/renderer/assets/codemirror-F6m3Hm1M.js +26552 -0
- package/out/renderer/assets/index-B3mtLdU3.css +2 -0
- package/out/renderer/assets/{index-MMIHKSKx.js → index-D6-zmXen.js} +17493 -49301
- package/out/renderer/index.html +4 -2
- package/package.json +4 -2
- package/src/cli/agent-templates/aider/conventions.md +10 -0
- package/src/cli/agent-templates/claude/skills/api-spector-api-audit.md +135 -0
- package/src/cli/agent-templates/claude/skills/api-spector-functional-tests.md +73 -0
- package/src/cli/agent-templates/claude/skills/api-spector-generate-mocks.md +182 -0
- package/src/cli/agent-templates/claude/skills/api-spector-security-tests.md +73 -0
- package/src/cli/agent-templates/copilot/copilot-instructions.md +38 -0
- package/src/cli/agent-templates/cursor/rules/api-spector.mdc +21 -0
- package/src/cli/agent-templates/windsurf/windsurfrules +19 -0
- package/out/renderer/assets/index-CkHujZU3.css +0 -2
package/out/renderer/index.html
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
<meta charset="UTF-8" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>API Spector</title>
|
|
8
|
-
<script type="module" crossorigin src="./assets/index-
|
|
9
|
-
<link rel="
|
|
8
|
+
<script type="module" crossorigin src="./assets/index-D6-zmXen.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="./assets/codemirror-F6m3Hm1M.js">
|
|
10
|
+
<link rel="modulepreload" crossorigin href="./assets/ajv-2MAg6kGF.js">
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/index-B3mtLdU3.css">
|
|
10
12
|
</head>
|
|
11
13
|
|
|
12
14
|
<body>
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testsmith/api-spector",
|
|
3
3
|
"productName": "API Spector",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.2",
|
|
5
5
|
"description": "Local-first API testing tool to inspect, test and mock APIs",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
"bin/",
|
|
27
27
|
"resources/splash.html",
|
|
28
28
|
"build/icon.png",
|
|
29
|
-
"build/icon.ico"
|
|
29
|
+
"build/icon.ico",
|
|
30
|
+
"src/cli/agent-templates/",
|
|
31
|
+
"docs/ai/"
|
|
30
32
|
],
|
|
31
33
|
"scripts": {
|
|
32
34
|
"dev": "electron-vite dev",
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# API Spector Conventions
|
|
2
|
+
|
|
3
|
+
This project uses API Spector for API testing. Reference docs are in `.aider/docs/`:
|
|
4
|
+
|
|
5
|
+
- `api-spector-scripting-reference.md` — `sp.*` API (assertions, variables, TOTP, JSONPath)
|
|
6
|
+
- `collection-file-format.md` — `.spector` and `.env.json` structure
|
|
7
|
+
- `functional-testing-guide.md` — functional test design patterns
|
|
8
|
+
- `security-testing-guide.md` — OWASP API Top 10 test patterns
|
|
9
|
+
|
|
10
|
+
Use `sp.test()` for assertions, `sp.response.json()` for body parsing, `sp.environment.set()` for cross-request variables.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Audit API for Inconsistencies
|
|
3
|
+
description: Analyze an OpenAPI spec for design inconsistencies, naming violations, missing fields, and best-practice deviations
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Audit API for Inconsistencies
|
|
7
|
+
|
|
8
|
+
Analyze an OpenAPI spec and produce a detailed audit report of design inconsistencies, naming violations, missing documentation, and deviations from REST best practices. This is a read-only analysis — no tests or collections are generated.
|
|
9
|
+
|
|
10
|
+
## Execution steps — follow in order
|
|
11
|
+
|
|
12
|
+
1. Ask the user for an OpenAPI spec URL or file path
|
|
13
|
+
2. Fetch/read the spec
|
|
14
|
+
3. Run every check listed below
|
|
15
|
+
4. **Call the Write tool to create `api-audit-report.md` in the project directory.** Do NOT just print results in chat — write the full report to disk as a file.
|
|
16
|
+
5. After writing, tell the user: "Audit report written to api-audit-report.md" and show a brief summary (total errors/warnings/info count) in chat.
|
|
17
|
+
6. Rate each finding as: **error** (breaks clients), **warning** (inconsistent/confusing), or **info** (suggestion)
|
|
18
|
+
|
|
19
|
+
## Checks to perform
|
|
20
|
+
|
|
21
|
+
### 1. Naming consistency
|
|
22
|
+
|
|
23
|
+
- **Path casing**: are paths consistently kebab-case (`/user-profiles`), snake_case (`/user_profiles`), or camelCase (`/userProfiles`)? Flag any that deviate from the majority.
|
|
24
|
+
- **Path pluralization**: are collection endpoints plural (`/users`) and singleton endpoints singular (`/user/{id}`)? Flag inconsistent pluralization like `/user` for a list and `/products` for another list.
|
|
25
|
+
- **Parameter naming**: are path/query params consistently camelCase, snake_case, or kebab-case? Flag mixed conventions (e.g. `userId` in one endpoint, `brand_id` in another).
|
|
26
|
+
- **Schema property naming**: same casing check across all request/response schemas. Flag if some schemas use `firstName` and others use `first_name`.
|
|
27
|
+
- **Operation IDs**: are they present? Are they consistently formatted (camelCase, snake_case)?
|
|
28
|
+
|
|
29
|
+
### 2. HTTP method usage
|
|
30
|
+
|
|
31
|
+
- **GET with request body**: GET endpoints should not have a request body. Flag any that do.
|
|
32
|
+
- **POST for retrieval**: POST endpoints that only return data (no creation) — might be better as GET with query params.
|
|
33
|
+
- **DELETE returning body**: flag DELETE endpoints that return 200 with a body (should typically be 204 No Content).
|
|
34
|
+
- **PATCH vs PUT confusion**: flag PUT endpoints that accept partial updates (should be PATCH) or PATCH endpoints that require all fields (should be PUT).
|
|
35
|
+
|
|
36
|
+
### 3. Response consistency
|
|
37
|
+
|
|
38
|
+
- **Status codes**: do similar operations return the same codes? E.g. all successful creates return 201, all deletes return 204. Flag inconsistencies (one POST returns 200, another returns 201).
|
|
39
|
+
- **Error schema**: do all error responses use the same shape? Flag if some return `{ "message": "..." }` and others return `{ "error": "..." }` or `{ "errors": [...] }`.
|
|
40
|
+
- **Pagination**: do all list endpoints use the same pagination structure? Flag if some use `page/per_page`, others use `offset/limit`, and others have no pagination.
|
|
41
|
+
- **Envelope consistency**: do some endpoints wrap data in `{ "data": [...] }` while others return bare arrays? Flag the inconsistency.
|
|
42
|
+
|
|
43
|
+
### 4. Missing documentation
|
|
44
|
+
|
|
45
|
+
- **Endpoints without descriptions**: list them.
|
|
46
|
+
- **Parameters without descriptions**: list the count per endpoint.
|
|
47
|
+
- **Schemas without property descriptions**: flag schemas where >50% of properties lack descriptions.
|
|
48
|
+
- **Missing examples**: flag request/response schemas without examples (makes the spec harder to use).
|
|
49
|
+
- **Missing operationId**: flag endpoints without operationId (breaks code generators).
|
|
50
|
+
|
|
51
|
+
### 5. Schema issues
|
|
52
|
+
|
|
53
|
+
- **Identical schemas with different names**: detect schemas that have the same properties/types but different names (copy-paste duplication).
|
|
54
|
+
- **Overly permissive types**: flag `type: string` without `format`, `minLength`, `maxLength`, or `pattern` for fields that should be constrained (email, phone, URL, date).
|
|
55
|
+
- **Missing required fields**: flag schemas that define properties like `id`, `email`, `name` but don't list them in `required`.
|
|
56
|
+
- **Inconsistent ID types**: flag if some schemas use `type: integer` for IDs and others use `type: string`.
|
|
57
|
+
- **Nullable vs optional confusion**: flag fields that are nullable but not marked as such, or optional fields that should be required.
|
|
58
|
+
|
|
59
|
+
### 6. Security
|
|
60
|
+
|
|
61
|
+
- **Endpoints without security**: flag endpoints that don't reference any security scheme (and aren't public-by-design like login/register).
|
|
62
|
+
- **Inconsistent auth**: flag if some endpoints use Bearer tokens and others use API keys without clear reason.
|
|
63
|
+
- **Sensitive data in query params**: flag endpoints that pass tokens, passwords, or keys as query parameters (should be headers or body).
|
|
64
|
+
- **Missing security schemes**: flag if the spec references security schemes that aren't defined.
|
|
65
|
+
|
|
66
|
+
### 7. Versioning & deprecation
|
|
67
|
+
|
|
68
|
+
- **Mixed versioning**: flag if some paths use `/v1/...` and others use `/v2/...` or no version.
|
|
69
|
+
- **Deprecated endpoints without replacement**: flag endpoints marked deprecated that don't document what to use instead.
|
|
70
|
+
- **Deprecated endpoints without timeline**: flag deprecated endpoints that don't specify when they'll be removed.
|
|
71
|
+
|
|
72
|
+
### 8. REST best practices
|
|
73
|
+
|
|
74
|
+
- **Nested resources too deep**: flag paths with more than 3 levels of nesting (e.g. `/users/{id}/orders/{orderId}/items/{itemId}/details`).
|
|
75
|
+
- **Verbs in paths**: flag paths that contain action verbs (e.g. `/getUser`, `/createOrder`, `/deleteProduct`) — the HTTP method should convey the action.
|
|
76
|
+
- **Inconsistent trailing slashes**: flag if some paths end with `/` and others don't.
|
|
77
|
+
- **Missing CORS headers in spec**: flag if no security headers or CORS configuration is documented.
|
|
78
|
+
|
|
79
|
+
## Output format
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
# API Audit Report: <API Name>
|
|
83
|
+
|
|
84
|
+
**Spec**: <URL or file>
|
|
85
|
+
**Version**: <spec version>
|
|
86
|
+
**Endpoints analyzed**: <count>
|
|
87
|
+
**Schemas analyzed**: <count>
|
|
88
|
+
|
|
89
|
+
## Summary
|
|
90
|
+
|
|
91
|
+
| Category | Errors | Warnings | Info |
|
|
92
|
+
|---|---|---|---|
|
|
93
|
+
| Naming consistency | 0 | 3 | 1 |
|
|
94
|
+
| HTTP method usage | 1 | 0 | 0 |
|
|
95
|
+
| Response consistency | 0 | 2 | 0 |
|
|
96
|
+
| ... | ... | ... | ... |
|
|
97
|
+
| **Total** | **1** | **5** | **1** |
|
|
98
|
+
|
|
99
|
+
## Findings
|
|
100
|
+
|
|
101
|
+
### Naming Consistency
|
|
102
|
+
|
|
103
|
+
#### ⚠️ WARNING: Mixed parameter naming convention
|
|
104
|
+
- `GET /users/{userId}` uses camelCase
|
|
105
|
+
- `GET /brands/{brand_id}` uses snake_case
|
|
106
|
+
- `GET /categories/{categoryId}` uses camelCase
|
|
107
|
+
**Recommendation**: Standardize on one convention (snake_case is most common in REST APIs).
|
|
108
|
+
|
|
109
|
+
#### ℹ️ INFO: Consider adding operationId to all endpoints
|
|
110
|
+
- 12 out of 45 endpoints lack operationId
|
|
111
|
+
**Recommendation**: Add operationId for better code generation support.
|
|
112
|
+
|
|
113
|
+
### HTTP Method Usage
|
|
114
|
+
|
|
115
|
+
#### 🔴 ERROR: GET endpoint has request body
|
|
116
|
+
- `GET /reports/custom` defines a request body
|
|
117
|
+
**Recommendation**: Use query parameters or POST for complex filters.
|
|
118
|
+
|
|
119
|
+
...
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Important rules
|
|
123
|
+
|
|
124
|
+
- This is **analysis only** — don't generate tests, collections, or code
|
|
125
|
+
- Be specific: list the exact endpoints/schemas that have issues, don't just say "some endpoints"
|
|
126
|
+
- Provide concrete recommendations for each finding
|
|
127
|
+
- Don't flag things that are valid design choices (e.g. using UUIDs vs integers for IDs is a choice, not an inconsistency — unless both are used)
|
|
128
|
+
- Group related findings (e.g. all naming issues together)
|
|
129
|
+
- Count the total findings per severity in the summary table
|
|
130
|
+
|
|
131
|
+
## Token efficiency
|
|
132
|
+
|
|
133
|
+
- Don't reproduce the full spec in the output
|
|
134
|
+
- Cite endpoints by method + path only
|
|
135
|
+
- If 20+ endpoints have the same issue, show 3 examples and say "and N more"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Generate Functional Tests from OpenAPI
|
|
3
|
+
description: Fetch an OpenAPI spec and generate an API Spector collection with functional test scripts
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate Functional Tests from OpenAPI
|
|
7
|
+
|
|
8
|
+
## Execution steps — follow in order
|
|
9
|
+
|
|
10
|
+
### 1. Get the spec
|
|
11
|
+
|
|
12
|
+
Ask the user for an OpenAPI spec URL or file path. Fetch/read it.
|
|
13
|
+
|
|
14
|
+
### 2. Create the workspace + collection + environment
|
|
15
|
+
|
|
16
|
+
#### If workspace.json already exists
|
|
17
|
+
|
|
18
|
+
Read it. Add the new collection/environment to existing arrays.
|
|
19
|
+
|
|
20
|
+
#### If no workspace exists
|
|
21
|
+
|
|
22
|
+
Create:
|
|
23
|
+
```
|
|
24
|
+
{project}/
|
|
25
|
+
├── workspace.json
|
|
26
|
+
├── collections/{name}.spector
|
|
27
|
+
└── environments/{name}.env.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Environment must include `baseUrl` from the spec + credential placeholders.
|
|
31
|
+
|
|
32
|
+
### 3. Tell the user
|
|
33
|
+
|
|
34
|
+
After creating everything, tell the user:
|
|
35
|
+
- "Workspace created with collection and environment"
|
|
36
|
+
- "Open the workspace in API Spector, fill in environment variables, and run"
|
|
37
|
+
|
|
38
|
+
## URL and path parameters — CRITICAL
|
|
39
|
+
|
|
40
|
+
NEVER use `:param` or `{param}`. Always use `{{variable}}`:
|
|
41
|
+
- WRONG: `{{baseUrl}}/brands/:id`
|
|
42
|
+
- RIGHT: `{{baseUrl}}/brands/{{brand_id}}`
|
|
43
|
+
|
|
44
|
+
Every `{{var}}` in a URL must be set by a prior request via `sp.environment.set("var", ...)`.
|
|
45
|
+
|
|
46
|
+
## Variable naming — CRITICAL
|
|
47
|
+
|
|
48
|
+
Use simple snake_case. The name in `sp.environment.set("x", ...)` MUST exactly match every `{{x}}` reference.
|
|
49
|
+
|
|
50
|
+
Before outputting, build a dependency chain and verify every `{{var}}` has a matching setter that runs first.
|
|
51
|
+
|
|
52
|
+
## Collection structure
|
|
53
|
+
|
|
54
|
+
- One folder per API tag
|
|
55
|
+
- `beforeAll` login hook that extracts `{{access_token}}`
|
|
56
|
+
- ONE request per test scenario
|
|
57
|
+
- `postRequestScript` with `sp.test()` assertions
|
|
58
|
+
- Path params as `paramType: "path"` in params array AND `{{var}}` in URL
|
|
59
|
+
- Use `{{baseUrl}}` prefix
|
|
60
|
+
- Order: list/create before get/update/delete (so IDs are extracted first)
|
|
61
|
+
|
|
62
|
+
## References
|
|
63
|
+
|
|
64
|
+
- `.claude/docs/api-spector-scripting-reference.md` — `sp.*` API
|
|
65
|
+
- `.claude/docs/functional-testing-guide.md` — test patterns
|
|
66
|
+
- `.claude/docs/collection-file-format.md` — JSON format
|
|
67
|
+
|
|
68
|
+
## Token efficiency
|
|
69
|
+
|
|
70
|
+
- Extract only paths, methods, required fields from spec
|
|
71
|
+
- Ask which tags to cover, generate one at a time
|
|
72
|
+
- Skip boilerplate headers (Accept/Content-Type are defaults)
|
|
73
|
+
- Use compact JSON
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Generate Mock Server from OpenAPI
|
|
3
|
+
description: Create an API Spector mock server with dynamic responses from an OpenAPI spec
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate Mock Server from OpenAPI
|
|
7
|
+
|
|
8
|
+
## What to do
|
|
9
|
+
|
|
10
|
+
1. Ask the user for an OpenAPI spec URL or file path
|
|
11
|
+
2. Ask which endpoints/tags to mock (or all)
|
|
12
|
+
3. Ask what port to use (default: 3900)
|
|
13
|
+
4. Generate a `.mock.json` file with routes for each endpoint
|
|
14
|
+
|
|
15
|
+
## Mock server file format
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"version": "1.0",
|
|
20
|
+
"id": "uuid",
|
|
21
|
+
"name": "My API Mock",
|
|
22
|
+
"port": 3900,
|
|
23
|
+
"routes": [
|
|
24
|
+
{
|
|
25
|
+
"id": "uuid",
|
|
26
|
+
"method": "GET",
|
|
27
|
+
"path": "/users/:id",
|
|
28
|
+
"statusCode": 200,
|
|
29
|
+
"headers": { "Content-Type": "application/json" },
|
|
30
|
+
"body": "{ ... }",
|
|
31
|
+
"description": "Get user by ID",
|
|
32
|
+
"script": "// optional JS to make response dynamic"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Route fields
|
|
39
|
+
- `method`: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, or ANY
|
|
40
|
+
- `path`: Express-style with `:param` for path params (e.g. `/users/:id`)
|
|
41
|
+
- `statusCode`: default HTTP status
|
|
42
|
+
- `headers`: response headers (Content-Type defaults to application/json)
|
|
43
|
+
- `body`: static JSON string response body
|
|
44
|
+
- `script`: JavaScript that runs before sending. Has access to `request`, `response`, `faker`, `dayjs`
|
|
45
|
+
- `delay`: optional ms delay before responding
|
|
46
|
+
|
|
47
|
+
### Path params
|
|
48
|
+
|
|
49
|
+
Use Express-style `:param` syntax, NOT OpenAPI `{param}`:
|
|
50
|
+
- OpenAPI: `/users/{userId}` → Mock: `/users/:userId`
|
|
51
|
+
|
|
52
|
+
### Script context
|
|
53
|
+
|
|
54
|
+
```javascript
|
|
55
|
+
// Available in route scripts:
|
|
56
|
+
request.method // "GET"
|
|
57
|
+
request.path // "/users/42"
|
|
58
|
+
request.params // { id: "42" }
|
|
59
|
+
request.query // { page: "1" }
|
|
60
|
+
request.body // parsed JSON body (or null)
|
|
61
|
+
request.headers // { authorization: "Bearer ...", ... }
|
|
62
|
+
|
|
63
|
+
response.statusCode // mutable — change to e.g. 404
|
|
64
|
+
response.body // mutable — replace the response body
|
|
65
|
+
response.headers // mutable — add/change headers
|
|
66
|
+
|
|
67
|
+
faker // @faker-js/faker — generate dynamic data
|
|
68
|
+
dayjs // dayjs — date/time helpers
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Making responses dynamic
|
|
72
|
+
|
|
73
|
+
Use `script` on routes to generate realistic data with faker:
|
|
74
|
+
|
|
75
|
+
### List endpoint with faker data
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"method": "GET",
|
|
79
|
+
"path": "/users",
|
|
80
|
+
"statusCode": 200,
|
|
81
|
+
"body": "[]",
|
|
82
|
+
"script": "const users = Array.from({length: 10}, (_, i) => ({ id: i + 1, name: faker.person.fullName(), email: faker.internet.email(), role: faker.helpers.arrayElement(['admin', 'user']), created_at: faker.date.recent().toISOString() })); response.body = JSON.stringify(users);"
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Single resource using path param
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"method": "GET",
|
|
90
|
+
"path": "/users/:id",
|
|
91
|
+
"statusCode": 200,
|
|
92
|
+
"body": "{}",
|
|
93
|
+
"script": "response.body = JSON.stringify({ id: request.params.id, name: faker.person.fullName(), email: faker.internet.email(), created_at: faker.date.recent().toISOString() });"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### POST that echoes back with generated ID
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"method": "POST",
|
|
101
|
+
"path": "/users",
|
|
102
|
+
"statusCode": 201,
|
|
103
|
+
"body": "{}",
|
|
104
|
+
"script": "const body = request.body || {}; response.body = JSON.stringify({ id: faker.string.uuid(), ...body, created_at: dayjs().toISOString() });"
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Conditional responses (not found, validation)
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"method": "GET",
|
|
112
|
+
"path": "/users/:id",
|
|
113
|
+
"statusCode": 200,
|
|
114
|
+
"body": "{}",
|
|
115
|
+
"script": "if (request.params.id === '0' || request.params.id === 'notfound') { response.statusCode = 404; response.body = JSON.stringify({ message: 'User not found' }); } else { response.body = JSON.stringify({ id: request.params.id, name: faker.person.fullName() }); }"
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Auth validation mock
|
|
120
|
+
```json
|
|
121
|
+
{
|
|
122
|
+
"method": "GET",
|
|
123
|
+
"path": "/users/me",
|
|
124
|
+
"statusCode": 200,
|
|
125
|
+
"body": "{}",
|
|
126
|
+
"script": "if (!request.headers.authorization) { response.statusCode = 401; response.body = JSON.stringify({ message: 'Unauthorized' }); } else { response.body = JSON.stringify({ id: 1, name: faker.person.fullName(), email: faker.internet.email() }); }"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## What to generate per endpoint type
|
|
131
|
+
|
|
132
|
+
| OpenAPI pattern | Mock behavior |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `GET /resources` (list) | faker array of 5-10 items with realistic field values |
|
|
135
|
+
| `GET /resources/:id` | faker single item using `request.params.id` |
|
|
136
|
+
| `POST /resources` | 201 + echo body with generated `id` and `created_at` |
|
|
137
|
+
| `PUT /resources/:id` | 200 + echo body merged with `request.params.id` |
|
|
138
|
+
| `PATCH /resources/:id` | 200 + echo body merged with `request.params.id` |
|
|
139
|
+
| `DELETE /resources/:id` | 204 + empty body |
|
|
140
|
+
| Auth endpoint (`POST /login`) | Return `{ access_token: faker.string.uuid() }` |
|
|
141
|
+
|
|
142
|
+
## When to use static vs dynamic
|
|
143
|
+
|
|
144
|
+
- **IDs, timestamps, emails, names**: always dynamic (faker)
|
|
145
|
+
- **Enum fields** (status, role, type): use `faker.helpers.arrayElement([...])`
|
|
146
|
+
- **Booleans**: use `faker.datatype.boolean()`
|
|
147
|
+
- **Prices/amounts**: use `faker.number.float({ min: 1, max: 999, fractionDigits: 2 })`
|
|
148
|
+
- **Fixed structure fields** (pagination meta, error shapes): static in `body`
|
|
149
|
+
- **Path-param-dependent data**: use `request.params.x` in scripts
|
|
150
|
+
|
|
151
|
+
## Token efficiency
|
|
152
|
+
|
|
153
|
+
- Extract only paths, methods, and response schemas from the spec — skip descriptions
|
|
154
|
+
- Ask which tags to mock before generating all
|
|
155
|
+
- Generate compact JSON
|
|
156
|
+
- One script per route, no comments in scripts (they're in `description` field)
|
|
157
|
+
|
|
158
|
+
## File output — create or update workspace
|
|
159
|
+
|
|
160
|
+
### If no workspace.json exists, create the full workspace:
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
<project>/
|
|
164
|
+
├── workspace.json
|
|
165
|
+
└── mocks/
|
|
166
|
+
└── <api-name>.mock.json
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`workspace.json`:
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"version": "1.0",
|
|
173
|
+
"collections": [],
|
|
174
|
+
"environments": [],
|
|
175
|
+
"mocks": ["mocks/<api-name>.mock.json"],
|
|
176
|
+
"activeEnvironmentId": null
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### If workspace.json already exists:
|
|
181
|
+
|
|
182
|
+
Add the mock file path to the existing `mocks` array (create the array if it doesn't exist). Don't overwrite collections or environments.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Generate Security Tests from OpenAPI (OWASP API Top 10)
|
|
3
|
+
description: Generate OWASP API Top 10 security test cases with attack payloads for API Spector
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Generate Security Tests from OpenAPI (OWASP API Top 10)
|
|
7
|
+
|
|
8
|
+
## Execution steps — follow in order
|
|
9
|
+
|
|
10
|
+
### 1. Get the spec
|
|
11
|
+
|
|
12
|
+
Ask the user for an OpenAPI spec URL or file path. Fetch/read it.
|
|
13
|
+
|
|
14
|
+
### 2. Analyze auth
|
|
15
|
+
|
|
16
|
+
Check the spec for `securityDefinitions`, `security`, `securitySchemes`, or login endpoints.
|
|
17
|
+
|
|
18
|
+
- **No auth found** → skip BOLA, Broken Auth, Function-Level Auth. Only generate: Injection, Security Config, Resource Consumption, SSRF. Do NOT ask for credentials.
|
|
19
|
+
- **Auth found** → ask for credential variable names (`{{user_a_token}}`, `{{user_b_token}}`, `{{admin_token}}`, `{{user_b_id}}`).
|
|
20
|
+
|
|
21
|
+
### 3. Create the workspace + collection + environment
|
|
22
|
+
|
|
23
|
+
#### If workspace.json already exists
|
|
24
|
+
|
|
25
|
+
Read it. Add the new security collection/environment to existing arrays.
|
|
26
|
+
|
|
27
|
+
#### If no workspace exists
|
|
28
|
+
|
|
29
|
+
Create:
|
|
30
|
+
```
|
|
31
|
+
{project}/
|
|
32
|
+
├── workspace.json
|
|
33
|
+
├── collections/{name}-security.spector
|
|
34
|
+
└── environments/{name}.env.json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Environment must include `baseUrl` from the spec + credential placeholders (if auth exists).
|
|
38
|
+
|
|
39
|
+
### 4. Tell the user
|
|
40
|
+
|
|
41
|
+
After creating everything, tell the user:
|
|
42
|
+
- "Workspace created with security collection and environment"
|
|
43
|
+
- "Open the workspace in API Spector, fill in environment variables, and run"
|
|
44
|
+
|
|
45
|
+
## Applicability rules
|
|
46
|
+
|
|
47
|
+
| Condition | BOLA | Auth | Mass Assign | Func Auth | Injection | SSRF | Config | Resources |
|
|
48
|
+
|---|---|---|---|---|---|---|---|---|
|
|
49
|
+
| Has auth + user IDs in paths | YES | YES | YES | YES | YES | maybe | YES | YES |
|
|
50
|
+
| Has auth, no user IDs | no | YES | YES | maybe | YES | maybe | YES | YES |
|
|
51
|
+
| No auth at all | no | no | maybe | no | YES | maybe | YES | YES |
|
|
52
|
+
|
|
53
|
+
## URL syntax — CRITICAL
|
|
54
|
+
|
|
55
|
+
NEVER use `:param` or `{param}`. Always use `{{variable}}`:
|
|
56
|
+
- WRONG: `{{baseUrl}}/users/:id`
|
|
57
|
+
- RIGHT: `{{baseUrl}}/users/{{user_b_id}}`
|
|
58
|
+
|
|
59
|
+
## Variable naming — CRITICAL
|
|
60
|
+
|
|
61
|
+
Use consistent snake_case. `sp.environment.set("x", ...)` must match `{{x}}` everywhere.
|
|
62
|
+
|
|
63
|
+
## References
|
|
64
|
+
|
|
65
|
+
- `.claude/docs/api-spector-scripting-reference.md` — `sp.*` API
|
|
66
|
+
- `.claude/docs/security-testing-guide.md` — OWASP patterns
|
|
67
|
+
- `.claude/docs/collection-file-format.md` — JSON format
|
|
68
|
+
|
|
69
|
+
## Token efficiency
|
|
70
|
+
|
|
71
|
+
- Ask which OWASP categories to focus on before generating all
|
|
72
|
+
- Skip categories that don't apply
|
|
73
|
+
- Generate in batches if 20+ endpoints
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# GitHub Copilot Instructions — API Spector
|
|
2
|
+
|
|
3
|
+
This project uses **API Spector**, a local-first API testing tool. When working with test scripts, collections, or test generation, refer to the documentation in `.github/docs/`.
|
|
4
|
+
|
|
5
|
+
## Key references
|
|
6
|
+
|
|
7
|
+
- **Scripting API**: See `.github/docs/api-spector-scripting-reference.md` for the full `sp.*` API (assertions, response access, variables, TOTP, JSONPath)
|
|
8
|
+
- **Collection format**: See `.github/docs/collection-file-format.md` for `.spector` file structure
|
|
9
|
+
- **Functional testing**: See `.github/docs/functional-testing-guide.md` for test design patterns
|
|
10
|
+
- **Security testing**: See `.github/docs/security-testing-guide.md` for OWASP API Top 10 patterns
|
|
11
|
+
|
|
12
|
+
## Quick reference
|
|
13
|
+
|
|
14
|
+
Scripts use the `sp` global:
|
|
15
|
+
|
|
16
|
+
```javascript
|
|
17
|
+
// Test assertion
|
|
18
|
+
sp.test('name', function() {
|
|
19
|
+
const json = sp.response.json();
|
|
20
|
+
sp.expect(json.field).to.equal("value");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Variable extraction
|
|
24
|
+
sp.environment.set("token", String(sp.response.json().access_token));
|
|
25
|
+
|
|
26
|
+
// Status check
|
|
27
|
+
sp.expect(sp.response.code).to.equal(200);
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Variables use `{{name}}` interpolation in URLs, headers, body, and scripts.
|
|
31
|
+
|
|
32
|
+
## When asked to generate tests
|
|
33
|
+
|
|
34
|
+
1. Read the relevant `.github/docs/` guide
|
|
35
|
+
2. Use `sp.test()` blocks with descriptive names
|
|
36
|
+
3. Parse JSON once: `const json = sp.response.json();`
|
|
37
|
+
4. Cover: happy path, missing fields, wrong types, auth, edge cases
|
|
38
|
+
5. Use `sp.environment.set()` for cross-request data flow
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: API Spector API testing tool — scripting API, collection format, and test generation
|
|
3
|
+
globs: ["**/*.spector", "**/*.env.json", "**/workspace.json"]
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# API Spector
|
|
7
|
+
|
|
8
|
+
This project uses API Spector for API testing. When editing collection files (`.spector`), environment files (`.env.json`), or generating test scripts, follow these references:
|
|
9
|
+
|
|
10
|
+
- `.cursor/docs/api-spector-scripting-reference.md` — Full `sp.*` scripting API
|
|
11
|
+
- `.cursor/docs/collection-file-format.md` — `.spector` and `.env.json` file structure
|
|
12
|
+
- `.cursor/docs/functional-testing-guide.md` — Functional test design patterns
|
|
13
|
+
- `.cursor/docs/security-testing-guide.md` — OWASP API Top 10 security tests
|
|
14
|
+
|
|
15
|
+
## Script conventions
|
|
16
|
+
|
|
17
|
+
- Wrap assertions in `sp.test('descriptive name', function() { ... })`
|
|
18
|
+
- Parse JSON once per script: `const json = sp.response.json();`
|
|
19
|
+
- Use `sp.environment.set("key", value)` to pass data between requests
|
|
20
|
+
- Use `{{variable}}` interpolation in URLs, headers, body, and scripts
|
|
21
|
+
- Hooks: `beforeAll` runs once per folder, `before` runs per request
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# API Spector — Windsurf Rules
|
|
2
|
+
|
|
3
|
+
This project uses API Spector for API testing.
|
|
4
|
+
|
|
5
|
+
## References
|
|
6
|
+
|
|
7
|
+
When working with test scripts or collection files, read:
|
|
8
|
+
- `.windsurf/docs/api-spector-scripting-reference.md` — Full `sp.*` scripting API
|
|
9
|
+
- `.windsurf/docs/collection-file-format.md` — Collection and environment file format
|
|
10
|
+
- `.windsurf/docs/functional-testing-guide.md` — Functional test patterns
|
|
11
|
+
- `.windsurf/docs/security-testing-guide.md` — OWASP API Top 10 test patterns
|
|
12
|
+
|
|
13
|
+
## Script conventions
|
|
14
|
+
|
|
15
|
+
- Use `sp.test('name', function() { ... })` for assertions
|
|
16
|
+
- Use `sp.expect(value)` with `.to.equal()`, `.to.include()`, `.to.be.a()`, etc.
|
|
17
|
+
- Parse body: `const json = sp.response.json();`
|
|
18
|
+
- Set variables: `sp.environment.set("key", "value")`
|
|
19
|
+
- Use `{{variable}}` in URLs, headers, body, and scripts
|