@assertrx/dino 1.0.9 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/prompts/generate-bdd-from-url.md +5 -1
  3. package/prompts/generate-k6-test-from-endpoint.md +68 -0
  4. package/prompts/generate-k6-test-from-openapi.md +85 -0
  5. package/prompts/setup-k6.md +130 -0
  6. package/scripts/api-server.mjs +32 -2
  7. package/skills/analyzing-test-results/SKILL.md +150 -0
  8. package/skills/analyzing-test-results/reference/bottleneck-patterns.md +130 -0
  9. package/skills/analyzing-test-results/reference/metrics.md +134 -0
  10. package/skills/analyzing-test-results/reference/visualization.md +152 -0
  11. package/skills/designing-test-scenarios/SKILL.md +247 -0
  12. package/skills/designing-test-scenarios/reference/executors.md +215 -0
  13. package/skills/designing-test-scenarios/reference/test-types.md +215 -0
  14. package/skills/designing-test-scenarios/reference/thresholds.md +208 -0
  15. package/skills/generating-api-load-tests/SKILL.md +199 -0
  16. package/skills/generating-api-load-tests/reference/data-parameterization.md +343 -0
  17. package/skills/generating-api-load-tests/reference/grpc.md +315 -0
  18. package/skills/generating-api-load-tests/reference/http.md +380 -0
  19. package/skills/generating-api-load-tests/reference/websocket.md +369 -0
  20. package/skills/generating-browser-tests/SKILL.md +269 -0
  21. package/skills/generating-browser-tests/reference/browser-api.md +251 -0
  22. package/skills/generating-browser-tests/reference/web-vitals.md +148 -0
  23. package/skills/generating-tests-from-code/SKILL.md +142 -0
  24. package/skills/generating-tests-from-code/reference/auth-analysis.md +220 -0
  25. package/skills/generating-tests-from-code/reference/framework-patterns.md +242 -0
  26. package/skills/generating-tests-from-openapi/SKILL.md +234 -0
  27. package/skills/generating-tests-from-openapi/reference/openapi-auth-mapping.md +247 -0
  28. package/skills/generating-tests-from-openapi/reference/openapi-parsing.md +194 -0
  29. package/skills/operating-k6-in-ci-cd/SKILL.md +98 -0
  30. package/skills/operating-k6-in-ci-cd/reference/ci-cd-pipelines.md +265 -0
  31. package/skills/operating-k6-in-ci-cd/reference/extensions.md +144 -0
  32. package/skills/operating-k6-in-ci-cd/reference/k6-operator.md +214 -0
  33. package/skills/testing-resilience/SKILL.md +230 -0
  34. package/skills/testing-resilience/reference/fault-injection.md +153 -0
  35. package/skills/testing-resilience/reference/resilience-patterns.md +500 -0
@@ -0,0 +1,247 @@
1
+ # OpenAPI Security Scheme to k6 Mapping
2
+
3
+ ## Security Scheme Types
4
+
5
+ ### HTTP Bearer
6
+
7
+ ```yaml
8
+ components:
9
+ securitySchemes:
10
+ bearerAuth:
11
+ type: http
12
+ scheme: bearer
13
+ bearerFormat: JWT # Optional, informational
14
+ ```
15
+
16
+ **k6 mapping:**
17
+ ```javascript
18
+ export function setup() {
19
+ // Obtain token (login endpoint must be identified separately)
20
+ const res = http.post(`${BASE_URL}/auth/login`,
21
+ JSON.stringify({ username: __ENV.USERNAME, password: __ENV.PASSWORD }),
22
+ { headers: { 'Content-Type': 'application/json' } }
23
+ );
24
+ return { token: res.json('access_token') };
25
+ }
26
+
27
+ export default function (data) {
28
+ http.get(`${BASE_URL}/resource`, {
29
+ headers: { 'Authorization': `Bearer ${data.token}` },
30
+ });
31
+ }
32
+ ```
33
+
34
+ ### HTTP Basic
35
+
36
+ ```yaml
37
+ components:
38
+ securitySchemes:
39
+ basicAuth:
40
+ type: http
41
+ scheme: basic
42
+ ```
43
+
44
+ **k6 mapping:**
45
+ ```javascript
46
+ import encoding from 'k6/encoding';
47
+
48
+ const credentials = encoding.b64encode(
49
+ `${__ENV.USERNAME}:${__ENV.PASSWORD}`
50
+ );
51
+
52
+ export default function () {
53
+ http.get(`${BASE_URL}/resource`, {
54
+ headers: { 'Authorization': `Basic ${credentials}` },
55
+ });
56
+ }
57
+ ```
58
+
59
+ ### API Key (Header)
60
+
61
+ ```yaml
62
+ components:
63
+ securitySchemes:
64
+ apiKeyAuth:
65
+ type: apiKey
66
+ in: header
67
+ name: X-API-Key
68
+ ```
69
+
70
+ **k6 mapping:**
71
+ ```javascript
72
+ const API_KEY = __ENV.API_KEY;
73
+
74
+ export default function () {
75
+ http.get(`${BASE_URL}/resource`, {
76
+ headers: { 'X-API-Key': API_KEY },
77
+ });
78
+ }
79
+ ```
80
+
81
+ ### API Key (Query)
82
+
83
+ ```yaml
84
+ components:
85
+ securitySchemes:
86
+ apiKeyQuery:
87
+ type: apiKey
88
+ in: query
89
+ name: api_key
90
+ ```
91
+
92
+ **k6 mapping:**
93
+ ```javascript
94
+ const API_KEY = __ENV.API_KEY;
95
+
96
+ export default function () {
97
+ http.get(`${BASE_URL}/resource?api_key=${API_KEY}`);
98
+ }
99
+ ```
100
+
101
+ ### API Key (Cookie)
102
+
103
+ ```yaml
104
+ components:
105
+ securitySchemes:
106
+ apiKeyCookie:
107
+ type: apiKey
108
+ in: cookie
109
+ name: session_id
110
+ ```
111
+
112
+ **k6 mapping:**
113
+ ```javascript
114
+ export default function () {
115
+ http.get(`${BASE_URL}/resource`, {
116
+ cookies: { session_id: __ENV.SESSION_ID },
117
+ });
118
+ }
119
+ ```
120
+
121
+ ### OAuth2 — Client Credentials
122
+
123
+ ```yaml
124
+ components:
125
+ securitySchemes:
126
+ oauth2:
127
+ type: oauth2
128
+ flows:
129
+ clientCredentials:
130
+ tokenUrl: https://auth.example.com/oauth/token
131
+ scopes:
132
+ read: Read access
133
+ write: Write access
134
+ ```
135
+
136
+ **k6 mapping:**
137
+ ```javascript
138
+ import encoding from 'k6/encoding';
139
+
140
+ const TOKEN_URL = 'https://auth.example.com/oauth/token';
141
+ const CLIENT_ID = __ENV.CLIENT_ID;
142
+ const CLIENT_SECRET = __ENV.CLIENT_SECRET;
143
+
144
+ export function setup() {
145
+ const res = http.post(TOKEN_URL,
146
+ 'grant_type=client_credentials&scope=read write',
147
+ {
148
+ headers: {
149
+ 'Content-Type': 'application/x-www-form-urlencoded',
150
+ 'Authorization': `Basic ${encoding.b64encode(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
151
+ },
152
+ }
153
+ );
154
+ check(res, { 'token obtained': (r) => r.status === 200 });
155
+ return { token: res.json('access_token') };
156
+ }
157
+
158
+ export default function (data) {
159
+ http.get(`${BASE_URL}/resource`, {
160
+ headers: { 'Authorization': `Bearer ${data.token}` },
161
+ });
162
+ }
163
+ ```
164
+
165
+ ### OAuth2 — Password (Resource Owner)
166
+
167
+ ```yaml
168
+ components:
169
+ securitySchemes:
170
+ oauth2:
171
+ type: oauth2
172
+ flows:
173
+ password:
174
+ tokenUrl: https://auth.example.com/oauth/token
175
+ scopes:
176
+ read: Read access
177
+ ```
178
+
179
+ **k6 mapping:**
180
+ ```javascript
181
+ export function setup() {
182
+ const res = http.post(TOKEN_URL,
183
+ `grant_type=password&username=${__ENV.USERNAME}&password=${__ENV.PASSWORD}&scope=read`,
184
+ { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
185
+ );
186
+ return { token: res.json('access_token') };
187
+ }
188
+ ```
189
+
190
+ ### OAuth2 — Authorization Code
191
+
192
+ Not directly applicable for automated load testing since it requires browser-based user interaction. Alternatives:
193
+ 1. Use a pre-obtained token via environment variable
194
+ 2. Use the password flow if the auth server supports it
195
+ 3. Use client credentials flow for service-to-service testing
196
+
197
+ ```javascript
198
+ // Pre-obtained token approach
199
+ const TOKEN = __ENV.OAUTH_TOKEN;
200
+
201
+ export default function () {
202
+ http.get(`${BASE_URL}/resource`, {
203
+ headers: { 'Authorization': `Bearer ${TOKEN}` },
204
+ });
205
+ }
206
+ ```
207
+
208
+ ### OpenID Connect
209
+
210
+ ```yaml
211
+ components:
212
+ securitySchemes:
213
+ openId:
214
+ type: openIdConnect
215
+ openIdConnectUrl: https://auth.example.com/.well-known/openid-configuration
216
+ ```
217
+
218
+ **k6 mapping:** Similar to OAuth2. Fetch the OpenID configuration to discover the token endpoint, then use the appropriate OAuth2 flow.
219
+
220
+ ## Per-Endpoint Security
221
+
222
+ ```yaml
223
+ security:
224
+ - bearerAuth: [] # Global default
225
+
226
+ paths:
227
+ /public/health:
228
+ get:
229
+ security: [] # No auth required (overrides global)
230
+
231
+ /users:
232
+ get:
233
+ security:
234
+ - bearerAuth: []
235
+ - apiKeyAuth: [] # Either bearer OR API key
236
+
237
+ /admin/settings:
238
+ put:
239
+ security:
240
+ - bearerAuth: [admin] # Bearer with admin scope
241
+ ```
242
+
243
+ **k6 mapping strategy:**
244
+ 1. Public endpoints → No auth headers
245
+ 2. Multiple schemes (OR) → Use the simplest one for testing
246
+ 3. Scoped access → Ensure test credentials have required scopes
247
+ 4. Generate separate scenarios for different auth levels if needed
@@ -0,0 +1,194 @@
1
+ # OpenAPI Spec Parsing Reference
2
+
3
+ ## Spec Structure Overview
4
+
5
+ ```yaml
6
+ openapi: '3.1.0'
7
+ info: { title, version, description }
8
+ servers: [{ url, description }]
9
+ security: [{ schemeName: [] }] # Global security
10
+ paths:
11
+ /resource:
12
+ get/post/put/patch/delete:
13
+ operationId: string
14
+ tags: [string]
15
+ summary: string
16
+ parameters: [Parameter]
17
+ requestBody: RequestBody
18
+ responses: { statusCode: Response }
19
+ security: [{ schemeName: [scope] }] # Per-operation override
20
+ components:
21
+ schemas: { SchemaName: Schema }
22
+ securitySchemes: { SchemeName: SecurityScheme }
23
+ parameters: { ParameterName: Parameter }
24
+ requestBodies: { BodyName: RequestBody }
25
+ ```
26
+
27
+ ## Extracting Paths and Operations
28
+
29
+ For each entry in `paths`:
30
+
31
+ 1. **Path** → URL path (e.g., `/users/{id}`)
32
+ 2. **HTTP method** → `get`, `post`, `put`, `patch`, `delete`
33
+ 3. **Operation** → The operation object under the method
34
+
35
+ ### Path Parameters
36
+
37
+ ```yaml
38
+ parameters:
39
+ - name: id
40
+ in: path # path | query | header | cookie
41
+ required: true
42
+ schema:
43
+ type: integer
44
+ ```
45
+
46
+ Map to k6:
47
+ - `in: path` → Replace in URL: `/users/${id}`
48
+ - `in: query` → Append: `?page=1&limit=10`
49
+ - `in: header` → Add to headers: `{ 'X-Custom': 'value' }`
50
+
51
+ ### Request Body
52
+
53
+ ```yaml
54
+ requestBody:
55
+ required: true
56
+ content:
57
+ application/json:
58
+ schema:
59
+ $ref: '#/components/schemas/CreateUser'
60
+ multipart/form-data:
61
+ schema:
62
+ type: object
63
+ properties:
64
+ file:
65
+ type: string
66
+ format: binary
67
+ ```
68
+
69
+ Map to k6:
70
+ - `application/json` → `JSON.stringify(body)` with `Content-Type` header
71
+ - `multipart/form-data` → Use `http.file()` for binary fields
72
+ - `application/x-www-form-urlencoded` → URL-encoded string body
73
+
74
+ ## Resolving $ref References
75
+
76
+ ```yaml
77
+ # Reference
78
+ $ref: '#/components/schemas/User'
79
+
80
+ # Resolves to the object at components.schemas.User
81
+ ```
82
+
83
+ Follow `$ref` chains:
84
+ 1. Parse the JSON pointer path
85
+ 2. Navigate to the target object
86
+ 3. Replace the `$ref` with the resolved object
87
+ 4. Handle circular references (stop at 2 levels deep)
88
+
89
+ ## Schema to Example Value Generation
90
+
91
+ ### Primitive Types
92
+
93
+ | Schema | Generated Example |
94
+ |--------|------------------|
95
+ | `type: string` | `"test-string"` |
96
+ | `type: string, format: email` | `"test@example.com"` |
97
+ | `type: string, format: date` | `"2024-01-15"` |
98
+ | `type: string, format: date-time` | `"2024-01-15T10:30:00Z"` |
99
+ | `type: string, format: uuid` | `"550e8400-e29b-41d4-a716-446655440000"` |
100
+ | `type: string, format: uri` | `"https://example.com"` |
101
+ | `type: string, format: password` | `"password123"` |
102
+ | `type: string, enum: [A, B, C]` | `"A"` (first value) |
103
+ | `type: string, minLength: 5` | `"test-string"` (at least minLength) |
104
+ | `type: integer` | `1` |
105
+ | `type: integer, minimum: 10` | `10` |
106
+ | `type: number` | `1.0` |
107
+ | `type: boolean` | `true` |
108
+
109
+ ### Complex Types
110
+
111
+ ```yaml
112
+ # Object
113
+ type: object
114
+ required: [name, email]
115
+ properties:
116
+ name: { type: string }
117
+ email: { type: string, format: email }
118
+ age: { type: integer }
119
+ # → { "name": "test-string", "email": "test@example.com", "age": 1 }
120
+
121
+ # Array
122
+ type: array
123
+ items: { type: string }
124
+ # → ["test-string"]
125
+
126
+ # Array of objects
127
+ type: array
128
+ items:
129
+ $ref: '#/components/schemas/User'
130
+ # → [{ ...user example }]
131
+ ```
132
+
133
+ ### Using Existing Examples
134
+
135
+ Prefer spec-provided examples over generated ones:
136
+
137
+ ```yaml
138
+ schema:
139
+ type: object
140
+ properties:
141
+ name: { type: string }
142
+ example:
143
+ name: "John Doe"
144
+ # Use the example value: { "name": "John Doe" }
145
+ ```
146
+
147
+ Check in order:
148
+ 1. `example` field on the schema
149
+ 2. `examples` field on the media type
150
+ 3. `default` field on the schema
151
+ 4. Generate from type/format
152
+
153
+ ## Response Status Codes
154
+
155
+ Map response codes to k6 checks:
156
+
157
+ ```yaml
158
+ responses:
159
+ '200': { description: Success }
160
+ '201': { description: Created }
161
+ '204': { description: No Content }
162
+ '400': { description: Bad Request }
163
+ '401': { description: Unauthorized }
164
+ '404': { description: Not Found }
165
+ ```
166
+
167
+ For primary success responses, generate checks:
168
+ - `2xx` responses → `check(res, { 'status 200': (r) => r.status === 200 })`
169
+ - Use `http.expectedStatuses()` if testing error scenarios
170
+
171
+ ## Grouping by Tags
172
+
173
+ ```yaml
174
+ paths:
175
+ /users:
176
+ get:
177
+ tags: [Users]
178
+ /products:
179
+ get:
180
+ tags: [Products]
181
+ ```
182
+
183
+ Map tags to k6 `group()`:
184
+
185
+ ```javascript
186
+ group('Users', () => {
187
+ // All operations tagged 'Users'
188
+ });
189
+ group('Products', () => {
190
+ // All operations tagged 'Products'
191
+ });
192
+ ```
193
+
194
+ Operations without tags → group as `'Default'` or by path prefix.
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: operating-k6-in-ci-cd
3
+ description: Use when setting up k6 in CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins), configuring distributed testing with k6-operator on Kubernetes, or managing k6 extensions (xk6). Use when the user wants to automate performance tests in a pipeline or run distributed load tests.
4
+ ---
5
+
6
+ # Operating k6 in CI/CD
7
+
8
+ Configure k6 for CI/CD pipelines, distributed testing on Kubernetes, and extension management.
9
+
10
+ ## Choose Your Path
11
+
12
+ - **CI/CD Pipeline Setup** → See [reference/ci-cd-pipelines.md](reference/ci-cd-pipelines.md)
13
+ - GitHub Actions, GitLab CI, Jenkins
14
+ - Docker-based execution
15
+ - Threshold-based pass/fail in pipelines
16
+
17
+ - **Distributed Testing (Kubernetes)** → See [reference/k6-operator.md](reference/k6-operator.md)
18
+ - k6-operator installation
19
+ - TestRun CRD configuration
20
+ - Scaling load across pods
21
+
22
+ - **Extensions (xk6)** → See [reference/extensions.md](reference/extensions.md)
23
+ - Building custom k6 binaries
24
+ - Official and community extensions
25
+ - Automatic extension resolution
26
+
27
+ ## Quick Start: GitHub Actions
28
+
29
+ ```yaml
30
+ name: k6 Load Test
31
+ on: [push]
32
+ jobs:
33
+ k6:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: grafana/setup-k6-action@v1
38
+ - uses: grafana/run-k6-action@v1
39
+ with:
40
+ path: tests/load-test.js
41
+ ```
42
+
43
+ ## Quick Start: Docker
44
+
45
+ ```bash
46
+ docker run --rm -i grafana/k6 run - < script.js
47
+
48
+ # With local script file
49
+ docker run --rm -v $(pwd):/scripts grafana/k6 run /scripts/test.js
50
+
51
+ # With environment variables
52
+ docker run --rm -v $(pwd):/scripts \
53
+ -e BASE_URL=https://staging.example.com \
54
+ grafana/k6 run /scripts/test.js
55
+ ```
56
+
57
+ ## Key Concepts
58
+
59
+ ### Threshold-Based Pass/Fail
60
+
61
+ k6 exits with code 99 if thresholds fail. CI/CD pipelines use this to pass/fail the build:
62
+
63
+ ```javascript
64
+ export const options = {
65
+ thresholds: {
66
+ http_req_duration: ['p(95)<500'], // Fails pipeline if p95 > 500ms
67
+ http_req_failed: ['rate<0.01'], // Fails pipeline if error rate > 1%
68
+ },
69
+ };
70
+ ```
71
+
72
+ ### Environment-Specific Configuration
73
+
74
+ ```javascript
75
+ const BASE_URL = __ENV.BASE_URL || 'https://api.example.com';
76
+ const TARGET_VUS = parseInt(__ENV.TARGET_VUS) || 10;
77
+
78
+ export const options = {
79
+ vus: TARGET_VUS,
80
+ duration: __ENV.DURATION || '5m',
81
+ };
82
+ ```
83
+
84
+ ### Grafana Cloud k6 Integration
85
+
86
+ ```bash
87
+ # Run locally, send results to cloud
88
+ K6_CLOUD_TOKEN=$TOKEN k6 cloud run --local-execution script.js
89
+
90
+ # Run entirely in cloud
91
+ K6_CLOUD_TOKEN=$TOKEN k6 cloud run script.js
92
+ ```
93
+
94
+ ## Related Skills
95
+
96
+ - For generating test scripts: `/k6:generating-api-load-tests`
97
+ - For analyzing results: `/k6:analyzing-test-results`
98
+ - For resilience testing on Kubernetes: `/k6:testing-resilience`