k6-cucumber-steps 1.2.27 → 2.0.1

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 (116) hide show
  1. package/README.md +190 -177
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +72 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/commands/init.command.d.ts +4 -0
  7. package/dist/commands/init.command.d.ts.map +1 -0
  8. package/dist/commands/init.command.js +30 -0
  9. package/dist/commands/init.command.js.map +1 -0
  10. package/dist/generators/feature.parser.d.ts +12 -0
  11. package/dist/generators/feature.parser.d.ts.map +1 -0
  12. package/dist/generators/feature.parser.js +208 -0
  13. package/dist/generators/feature.parser.js.map +1 -0
  14. package/dist/generators/k6-script.generator.d.ts +11 -0
  15. package/dist/generators/k6-script.generator.d.ts.map +1 -0
  16. package/dist/generators/k6-script.generator.js +233 -0
  17. package/dist/generators/k6-script.generator.js.map +1 -0
  18. package/dist/generators/project.generator.d.ts +14 -0
  19. package/dist/generators/project.generator.d.ts.map +1 -0
  20. package/dist/generators/project.generator.js +497 -0
  21. package/dist/generators/project.generator.js.map +1 -0
  22. package/dist/index.d.ts +24 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +53 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/runners/k6.runner.d.ts +19 -0
  27. package/dist/runners/k6.runner.d.ts.map +1 -0
  28. package/dist/runners/k6.runner.js +127 -0
  29. package/dist/runners/k6.runner.js.map +1 -0
  30. package/dist/step-registry.d.ts +14 -0
  31. package/dist/step-registry.d.ts.map +1 -0
  32. package/dist/step-registry.js +36 -0
  33. package/dist/step-registry.js.map +1 -0
  34. package/dist/types/index.d.ts +35 -0
  35. package/dist/types/index.d.ts.map +1 -0
  36. package/dist/types/index.js +3 -0
  37. package/dist/types/index.js.map +1 -0
  38. package/package.json +40 -62
  39. package/LICENSE +0 -21
  40. package/bin/k6-cucumber-steps.js +0 -176
  41. package/docs/data/search.json +0 -1
  42. package/docs/fonts/Inconsolata-Regular.ttf +0 -0
  43. package/docs/fonts/OpenSans-Regular.ttf +0 -0
  44. package/docs/fonts/WorkSans-Bold.ttf +0 -0
  45. package/docs/global.html +0 -36
  46. package/docs/index.html +0 -91
  47. package/docs/k6-cucumber-steps/1.2.8/data/search.json +0 -1
  48. package/docs/k6-cucumber-steps/1.2.8/fonts/Inconsolata-Regular.ttf +0 -0
  49. package/docs/k6-cucumber-steps/1.2.8/fonts/OpenSans-Regular.ttf +0 -0
  50. package/docs/k6-cucumber-steps/1.2.8/fonts/WorkSans-Bold.ttf +0 -0
  51. package/docs/k6-cucumber-steps/1.2.8/global.html +0 -3
  52. package/docs/k6-cucumber-steps/1.2.8/helpers_generateHeaders.js.html +0 -38
  53. package/docs/k6-cucumber-steps/1.2.8/helpers_resolveBody.js.html +0 -65
  54. package/docs/k6-cucumber-steps/1.2.8/index.html +0 -91
  55. package/docs/k6-cucumber-steps/1.2.8/module-generateHeaders.html +0 -3
  56. package/docs/k6-cucumber-steps/1.2.8/module-resolveBody.html +0 -3
  57. package/docs/k6-cucumber-steps/1.2.8/scripts/core.js +0 -726
  58. package/docs/k6-cucumber-steps/1.2.8/scripts/core.min.js +0 -23
  59. package/docs/k6-cucumber-steps/1.2.8/scripts/resize.js +0 -90
  60. package/docs/k6-cucumber-steps/1.2.8/scripts/search.js +0 -265
  61. package/docs/k6-cucumber-steps/1.2.8/scripts/search.min.js +0 -6
  62. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/Apache-License-2.0.txt +0 -202
  63. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/fuse.js +0 -9
  64. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/hljs-line-num-original.js +0 -369
  65. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/hljs-line-num.js +0 -1
  66. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/hljs-original.js +0 -5171
  67. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/hljs.js +0 -1
  68. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/popper.js +0 -5
  69. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/tippy.js +0 -1
  70. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/tocbot.js +0 -672
  71. package/docs/k6-cucumber-steps/1.2.8/scripts/third-party/tocbot.min.js +0 -1
  72. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme-base.css +0 -1159
  73. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme-dark.css +0 -412
  74. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme-light.css +0 -482
  75. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme-scrollbar.css +0 -30
  76. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -1
  77. package/docs/k6-cucumber-steps/1.2.8/styles/clean-jsdoc-theme.min.css +0 -1
  78. package/docs/k6-cucumber-steps/1.2.8/utils_k6Runner.js.html +0 -95
  79. package/docs/load_test_steps.js.html +0 -664
  80. package/docs/scripts/core.js +0 -726
  81. package/docs/scripts/core.min.js +0 -23
  82. package/docs/scripts/resize.js +0 -90
  83. package/docs/scripts/search.js +0 -265
  84. package/docs/scripts/search.min.js +0 -6
  85. package/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
  86. package/docs/scripts/third-party/fuse.js +0 -9
  87. package/docs/scripts/third-party/hljs-line-num-original.js +0 -369
  88. package/docs/scripts/third-party/hljs-line-num.js +0 -1
  89. package/docs/scripts/third-party/hljs-original.js +0 -5171
  90. package/docs/scripts/third-party/hljs.js +0 -1
  91. package/docs/scripts/third-party/popper.js +0 -5
  92. package/docs/scripts/third-party/tippy.js +0 -1
  93. package/docs/scripts/third-party/tocbot.js +0 -672
  94. package/docs/scripts/third-party/tocbot.min.js +0 -1
  95. package/docs/styles/clean-jsdoc-theme-base.css +0 -1159
  96. package/docs/styles/clean-jsdoc-theme-dark.css +0 -412
  97. package/docs/styles/clean-jsdoc-theme-light.css +0 -482
  98. package/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -30
  99. package/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -1
  100. package/docs/styles/clean-jsdoc-theme.min.css +0 -1
  101. package/index.js +0 -1
  102. package/lib/helpers/buildK6Script.d.ts +0 -1
  103. package/lib/helpers/buildK6Script.js +0 -103
  104. package/lib/helpers/generateHeaders.d.ts +0 -5
  105. package/lib/helpers/generateHeaders.js +0 -48
  106. package/lib/helpers/resolveBody.d.ts +0 -2
  107. package/lib/helpers/resolveBody.js +0 -78
  108. package/lib/helpers/resolvePayloadPath.js +0 -25
  109. package/lib/helpers/runK6ScriptFromWorld.js +0 -26
  110. package/lib/utils/k6Runner.d.ts +0 -6
  111. package/lib/utils/k6Runner.js +0 -89
  112. package/scripts/cucumber.js +0 -18
  113. package/scripts/linkReports.js +0 -107
  114. package/step_definitions/load_test_steps.d.ts +0 -89
  115. package/step_definitions/load_test_steps.js +0 -689
  116. package/step_definitions/world.js +0 -41
@@ -0,0 +1,497 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ProjectGenerator = void 0;
7
+ // src/generators/project.generator.ts
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ class ProjectGenerator {
11
+ generateProjectStructure(config, outputPath) {
12
+ // Create main directories
13
+ this.createDirectory(path_1.default.join(outputPath, "features"));
14
+ this.createDirectory(path_1.default.join(outputPath, "steps"));
15
+ this.createDirectory(path_1.default.join(outputPath, "generated"));
16
+ this.createDirectory(path_1.default.join(outputPath, "data"));
17
+ this.createDirectory(path_1.default.join(outputPath, "reports"));
18
+ fs_1.default.mkdirSync(path_1.default.join(outputPath, "data"), { recursive: true });
19
+ // Generate package.json
20
+ this.generatePackageJson(outputPath, config);
21
+ // Generate README
22
+ this.generateReadme(outputPath, config);
23
+ // Generate sample feature file
24
+ this.generateSampleFeature(outputPath);
25
+ this.generateBrowserSampleFeature(outputPath);
26
+ this.generateAuthSampleFeature(outputPath);
27
+ // Generate sample step definitions
28
+ this.generateSampleSteps(outputPath, config);
29
+ // Generate gitignore
30
+ this.generateGitignore(outputPath);
31
+ // Generate tsconfig if TypeScript
32
+ if (config.language === "ts") {
33
+ this.generateTsConfig(outputPath);
34
+ }
35
+ }
36
+ createDirectory(dirPath) {
37
+ if (!fs_1.default.existsSync(dirPath)) {
38
+ fs_1.default.mkdirSync(dirPath, { recursive: true });
39
+ }
40
+ }
41
+ generatePackageJson(outputPath, config) {
42
+ const packageJson = {
43
+ name: "k6-cucumber-test-project",
44
+ version: "1.0.0",
45
+ description: "Generated k6 test project with Cucumber integration",
46
+ main: config.language === "ts" ? "src/test.ts" : "test.js",
47
+ scripts: {
48
+ test: `k6 run generated/${config.language === "ts" ? "test.generated.ts" : "test.generated.js"}`,
49
+ dev: `k6 run --out json=results.json generated/${config.language === "ts" ? "test.generated.ts" : "test.generated.js"}`,
50
+ },
51
+ devDependencies: {
52
+ "@types/k6": "^0.48.0",
53
+ },
54
+ dependencies: {
55
+ // Add any runtime dependencies here
56
+ },
57
+ author: config.author,
58
+ license: "MIT",
59
+ };
60
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "package.json"), JSON.stringify(packageJson, null, 2));
61
+ }
62
+ generateReadme(outputPath, config) {
63
+ const readmeContent = `# K6 Cucumber Test Project
64
+
65
+ Generated with k6-cucumber-steps by ${config.author}
66
+
67
+ ## Setup
68
+
69
+ \`\`\`bash
70
+ npm install
71
+ \`\`\`
72
+
73
+ ## Running Tests
74
+
75
+ ### Generate k6 script from features:
76
+ \`\`\`bash
77
+ npx k6-cucumber-steps generate -l ${config.language === "ts" ? "ts" : "js"}
78
+ \`\`\`
79
+
80
+ ### Run tests:
81
+ \`\`\`bash
82
+ npm test
83
+ \`\`\`
84
+
85
+ ## Project Structure
86
+ - \`features/\` - Gherkin feature files
87
+ - \`steps/\` - Step definition implementations
88
+ - \`generated/\` - Generated k6 scripts
89
+ `;
90
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "README.md"), readmeContent);
91
+ }
92
+ generateAuthSampleFeature(outputPath) {
93
+ const content = `@vus:2
94
+ Feature: Authentication Examples
95
+ # This demonstrates dynamic auth with DataTables using k6's public test suite
96
+
97
+ Background:
98
+ Given the base URL is "http://coop.apps.symfonycasts.com"
99
+
100
+ Scenario: Authenticate via Standard Login
101
+ # Using k6's public login endpoint
102
+ Given the base URL is "https://demoqa.com"
103
+ When I authenticate with the following url and request body as "standard_user":
104
+ | endpoint | userName | password |
105
+ | /Account/v1/Authorized | k6tester | 1Password@ |
106
+ And I store "data" in "data/standard_user.json"
107
+
108
+ Scenario: Authenticate via Client Credentials (OAuth2 Simulation)
109
+ # Added "as form" at the end to trigger urlencoding
110
+ When I authenticate with the following url and request body as "service_account" as "form":
111
+ | endpoint | client_id | client_secret | grant_type |
112
+ | /token | k6-cucumber-steps | 40d595cb79978e9c2cccc61e4fa972fd | client_credentials |
113
+ And I store "access_token" in "data/service_account.json"
114
+
115
+ # Scenario: Authenticate with API Key and Environment
116
+ # When I authenticate with the following url and request body as "dev_user":
117
+ # | endpoint | apiKey | environment | version |
118
+ # | /token | key-4455 | staging | v2 |
119
+ # And I store "auth.key" in "data/dev_user.json"
120
+ `;
121
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "features", "authSample.feature"), content);
122
+ }
123
+ generateSampleFeature(outputPath) {
124
+ const sampleFeature = `@smoke @vus:10 @duration:1m
125
+ Feature: Comprehensive API Testing
126
+
127
+ Background:
128
+ Given the base URL is "https://jsonplaceholder.typicode.com"
129
+ And I set the default headers:
130
+ | Content-Type | Accept |
131
+ | application/json | application/json |
132
+
133
+ @group:user-api @threshold:http_req_duration=p(95)<500
134
+ Scenario: Get specific user details
135
+ When I make a GET request to "/users/1"
136
+ Then the response status should be 200
137
+ And the response should contain "name"
138
+
139
+ @group:load-test @stages:0s-0,20s-10,30s-10,10s-0
140
+ Scenario Outline: Validate multiple user endpoints
141
+ When I make a GET request to "/users/<userId>"
142
+ Then the response status should be <expectedStatus>
143
+
144
+ Examples:
145
+ | userId | expectedStatus |
146
+ | 1 | 200 |
147
+ | 5 | 200 |
148
+ | 999 | 404 |
149
+
150
+ @group:post-api
151
+ Scenario: Create a post with bulk data
152
+ Given I have the following post data:
153
+ """
154
+ {
155
+ "title": "Performance Test",
156
+ "body": "Testing DataTables and DocStrings",
157
+ "userId": 1
158
+ }
159
+ """
160
+ When I make a POST request to "/posts"
161
+ Then the response status should be 201
162
+ `;
163
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "features", "sample.feature"), sampleFeature);
164
+ }
165
+ generateBrowserSampleFeature(outputPath) {
166
+ const content = `@browser
167
+ Feature: Browser Performance Example
168
+ # Scenarios with @browser tag run in a real Chromium instance
169
+
170
+ Scenario: Verify UI Elements
171
+ Given the base URL is "https://test.k6.io"
172
+ When I navigate to the "/" page
173
+ Then I see the text on the page "Collection of simple web-pages"
174
+ `;
175
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "features", "browserSample.feature"), content);
176
+ }
177
+ // src/generators/project.generator.ts
178
+ generateSampleSteps(outputPath, config) {
179
+ const isTS = config.language === "ts";
180
+ const stepExtension = isTS ? ".ts" : ".js";
181
+ // Type helpers
182
+ const headerType = isTS ? ": Record<string, string>" : "";
183
+ const anyType = isTS ? ": any[]" : "";
184
+ const stringType = isTS ? ": string" : "";
185
+ const mixedType = isTS ? ": string | number" : "";
186
+ const sampleSteps = `import http from "k6/http";
187
+ import { check, sleep, group } from "k6";
188
+
189
+ let baseUrl = "";
190
+ let defaultHeaders${headerType} = {
191
+ 'Content-Type': 'application/json'
192
+ };
193
+
194
+ /**
195
+ * Given the base URL is "..."
196
+ */
197
+ export function theBaseUrlIs(url${stringType}) {
198
+ baseUrl = url;
199
+ }
200
+
201
+ /**
202
+ * When I authenticate with the following url and request body as {string} (as {string})
203
+ * This handles both:
204
+ * 1. ...as "user":
205
+ * 2. ...as "user" as "form":
206
+ */
207
+ export function iAuthenticateWithTheFollowingUrlAndRequestBodyAs(
208
+ context${stringType},
209
+ formatOrTable${anyType},
210
+ maybeTable${anyType}
211
+ ) {
212
+ let format = 'json';
213
+ let dataTable;
214
+
215
+ // Argument shifting logic
216
+ if (maybeTable === undefined) {
217
+ format = 'json';
218
+ dataTable = formatOrTable;
219
+ } else {
220
+ format = formatOrTable;
221
+ dataTable = maybeTable;
222
+ }
223
+
224
+ if (!dataTable || !dataTable[0]) return;
225
+
226
+ const row = dataTable[0];
227
+ const { endpoint, ...payload } = row;
228
+ const url = \`\${baseUrl}\${endpoint}\`;
229
+
230
+ let body;
231
+ let params = { headers: {} };
232
+
233
+ /** * FORM FORMAT LOGIC
234
+ * k6 behavior: If the body is an object and Content-Type is x-www-form-urlencoded,
235
+ * k6 serializes the object into a query string (key=value&key2=value2).
236
+ */
237
+ if (format === 'form') {
238
+ params.headers['Content-Type'] = 'application/x-www-form-urlencoded';
239
+ /** * IMPORTANT: For k6 to auto-encode, the body MUST be a plain object.
240
+ * We ensure payload is clean of any non-serializable properties.
241
+ */
242
+ body = Object.assign({}, payload);
243
+ } else {
244
+ params.headers['Content-Type'] = 'application/json';
245
+ body = JSON.stringify(payload);
246
+ }
247
+
248
+ const response = http.post(url, body, params);
249
+
250
+
251
+ const success = check(response, {
252
+ [\`Auth successful (\${format})\`]: (r) => r.status === 200 || r.status === 201
253
+ });
254
+
255
+ if (success) {
256
+ try {
257
+ const parsed = response.json();
258
+ globalThis.lastResponse = parsed;
259
+ console.log(\`✅ \${context} Response Captured. Keys: \${Object.keys(parsed).join(', ')}\`);
260
+ } catch (e) {
261
+ console.error(\`❌ Failed to parse JSON response for \${context}: \${response.body}\`);
262
+ globalThis.lastResponse = null;
263
+ }
264
+
265
+ } else {
266
+ console.error(\`❌ Auth failed for \${context}. Status: \${response.status}\`);
267
+ globalThis.lastResponse = null;
268
+ }
269
+ }
270
+ /**
271
+ * When I authenticate with the following url and request body as {string} (as {string})
272
+ * This handles both:
273
+ * 1. ...as "user":
274
+ * 2. ...as "user" as "form":
275
+ */
276
+ export function iAuthenticateWithTheFollowingUrlAndRequestBodyAsAs(
277
+ context${stringType},
278
+ formatOrTable${anyType},
279
+ maybeTable${anyType}
280
+ ) {
281
+ let format = 'json';
282
+ let dataTable;
283
+
284
+ // Argument shifting logic
285
+ if (maybeTable === undefined) {
286
+ format = 'json';
287
+ dataTable = formatOrTable;
288
+ } else {
289
+ format = formatOrTable;
290
+ dataTable = maybeTable;
291
+ }
292
+
293
+ if (!dataTable || !dataTable[0]) return;
294
+
295
+ const row = dataTable[0];
296
+ const { endpoint, ...payload } = row;
297
+ const url = \`\${baseUrl}\${endpoint}\`;
298
+
299
+ let body;
300
+ let params = { headers: {} };
301
+
302
+ /** * FORM FORMAT LOGIC
303
+ * k6 behavior: If the body is an object and Content-Type is x-www-form-urlencoded,
304
+ * k6 serializes the object into a query string (key=value&key2=value2).
305
+ */
306
+ if (format === 'form') {
307
+ params.headers['Content-Type'] = 'application/x-www-form-urlencoded';
308
+ /** * IMPORTANT: For k6 to auto-encode, the body MUST be a plain object.
309
+ * We ensure payload is clean of any non-serializable properties.
310
+ */
311
+ body = Object.assign({}, payload);
312
+ } else {
313
+ params.headers['Content-Type'] = 'application/json';
314
+ body = JSON.stringify(payload);
315
+ }
316
+
317
+ const response = http.post(url, body, params);
318
+
319
+
320
+ const success = check(response, {
321
+ [\`Auth successful (\${format})\`]: (r) => r.status === 200 || r.status === 201
322
+ });
323
+
324
+ if (success) {
325
+ try {
326
+ const parsed = response.json();
327
+ globalThis.lastResponse = parsed;
328
+ console.log(\`✅ \${context} Response Captured. Keys: \${Object.keys(parsed).join(', ')}\`);
329
+ } catch (e) {
330
+ console.error(\`❌ Failed to parse JSON response for \${context}: \${response.body}\`);
331
+ globalThis.lastResponse = null;
332
+ }
333
+
334
+ } else {
335
+ console.error(\`❌ Auth failed for \${context}. Status: \${response.status}\`);
336
+ globalThis.lastResponse = null;
337
+ }
338
+ }
339
+ /**
340
+ * And I store "data.token" in "data/standard_user.json"
341
+ */
342
+ export function iStoreIn(jsonPath${stringType}, fileName${stringType}) {
343
+ const responseData = globalThis.lastResponse;
344
+
345
+ if (!responseData) return;
346
+ const value = jsonPath.split('.').reduce((acc, key) => acc && acc[key], responseData);
347
+
348
+
349
+ // Debug: See what the server actually sent back
350
+ console.log(\`DEBUG: Response for \${fileName}: \`, JSON.stringify(responseData));
351
+
352
+
353
+
354
+ // Check for undefined/null specifically so 0 or "" aren't ignored
355
+ if (value !== undefined && value !== null) {
356
+ globalThis.savedTokens = globalThis.savedTokens || {};
357
+
358
+ // Store in the requested file path
359
+ globalThis.savedTokens[fileName] = value;
360
+
361
+ // ALSO store as a clean alias (e.g., 'service_account' instead of 'data/service_account.json')
362
+ const alias = fileName.split('/').pop().replace('.json', '');
363
+ globalThis.savedTokens[alias] = value;
364
+
365
+ console.log(\`✅ Value staged for file write: \${fileName}\`); } else {
366
+ console.error(\`❌ Could not find path "\${jsonPath}" in the response. JSON keys found: \${Object.keys(responseData).join(', ')}\`);
367
+ }
368
+ }
369
+ /**
370
+ * Background Auth: Applies the previously stored token to headers
371
+ */
372
+ export function iAmAuthenticatedAsA(userType${stringType}) {
373
+ const memoryKey = \`data/\${userType}.json\`;
374
+ const token = globalThis.savedTokens && globalThis.savedTokens[memoryKey];
375
+
376
+ if (token) {
377
+ defaultHeaders['Authorization'] = \`Bearer \${token}\`;
378
+ console.log(\`Using memory-stored token for \${userType}\`);
379
+ } else {
380
+ // Fallback: try to read the INITIAL file created during project init
381
+ try {
382
+ const userData = JSON.parse(open(\`../data/\${userType}.json\`));
383
+ if (userData.token) {
384
+ defaultHeaders['Authorization'] = \`Bearer \${userData.token}\`;
385
+ }
386
+ } catch (e) {
387
+ console.warn(\`No token found for \${userType} in memory or file.\`);
388
+ }
389
+ }
390
+ }
391
+
392
+ /**
393
+ * And I set the default headers:
394
+ */
395
+ export function iSetTheDefaultHeaders(data${anyType}) {
396
+ if (data && data.length > 0) {
397
+ Object.assign(defaultHeaders, data[0]);
398
+ }
399
+ }
400
+
401
+ /**
402
+ * When I make a GET request to "..."
403
+ */
404
+ export function iMakeAGetRequestTo(endpoint${stringType}) {
405
+ const url = \`\${baseUrl}\${endpoint}\`;
406
+ const response = http.get(url, { headers: defaultHeaders });
407
+
408
+ check(response, {
409
+ 'status is 200 or 404': (r) => r.status === 200 || r.status === 404,
410
+ 'has valid headers': (r) => r.request.headers['Authorization'] !== undefined
411
+ });
412
+ }
413
+
414
+ /**
415
+ * Then the response status should be ...
416
+ */
417
+ export function theResponseStatusShouldBe(expectedStatus${mixedType}) {
418
+ const status = typeof expectedStatus === 'string' ? parseInt(expectedStatus) : expectedStatus;
419
+ }
420
+
421
+ export function theResponseShouldContain(field${stringType}) {
422
+ console.log(\`Verified: Response contains \${field}\`);
423
+ }
424
+
425
+ /**
426
+ * Given I have the following post data:
427
+ */
428
+ export function iHaveTheFollowingPostData(content${stringType}) {
429
+ return JSON.parse(content);
430
+ }
431
+
432
+ /**
433
+ * When I make a POST request to "..."
434
+ */
435
+ export function iMakeAPostRequestTo(endpoint${stringType}) {
436
+ const url = \`\${baseUrl}\${endpoint}\`;
437
+ const payload = JSON.stringify({ title: 'k6 test' });
438
+ const response = http.post(url, payload, { headers: defaultHeaders });
439
+
440
+ check(response, {
441
+ 'POST status is 201': (r) => r.status === 201
442
+ });
443
+ }
444
+ /** --- Browser Steps (@browser) --- **/
445
+
446
+ export async function iNavigateToThePage(page, url${stringType}) {
447
+ // If URL is relative, prepend baseUrl
448
+ const fullUrl = url.startsWith('http') ? url : \`\${baseUrl}\${url}\`;
449
+ await page.goto(fullUrl);
450
+ }
451
+
452
+ export async function iClickTheButton(page, selector${stringType}) {
453
+ await page.locator(selector).click();
454
+ }
455
+
456
+ export async function iSeeTheTextOnThePage(page, text${stringType}) {
457
+ const content = await page.content();
458
+ check(page, {
459
+ [\`Text "\${text}" is visible\`]: () => content.includes(text)
460
+ });
461
+ }
462
+ `;
463
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "steps", `sample.steps${stepExtension}`), sampleSteps);
464
+ }
465
+ generateGitignore(outputPath) {
466
+ const gitignoreContent = `node_modules/
467
+
468
+ *.html
469
+ dist/
470
+ build/
471
+ reports/
472
+ data/*.json
473
+ .nyc_output/
474
+ coverage/
475
+ .env
476
+ `;
477
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, ".gitignore"), gitignoreContent);
478
+ }
479
+ generateTsConfig(outputPath) {
480
+ const tsconfig = {
481
+ compilerOptions: {
482
+ target: "ES2020",
483
+ module: "commonjs",
484
+ strict: true,
485
+ esModuleInterop: true,
486
+ skipLibCheck: true,
487
+ forceConsistentCasingInFileNames: true,
488
+ types: ["k6"],
489
+ },
490
+ include: ["src/**/*", "steps/**/*"],
491
+ exclude: ["node_modules"],
492
+ };
493
+ fs_1.default.writeFileSync(path_1.default.join(outputPath, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
494
+ }
495
+ }
496
+ exports.ProjectGenerator = ProjectGenerator;
497
+ //# sourceMappingURL=project.generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.generator.js","sourceRoot":"","sources":["../../src/generators/project.generator.ts"],"names":[],"mappings":";;;;;;AAAA,sCAAsC;AACtC,4CAAoB;AACpB,gDAAwB;AAGxB,MAAa,gBAAgB;IAC3B,wBAAwB,CAAC,MAAqB,EAAE,UAAkB;QAChE,0BAA0B;QAC1B,IAAI,CAAC,eAAe,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC;QACxD,IAAI,CAAC,eAAe,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,eAAe,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC,eAAe,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,eAAe,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;QACvD,YAAE,CAAC,SAAS,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,wBAAwB;QACxB,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAE7C,kBAAkB;QAClB,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAExC,+BAA+B;QAC/B,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,4BAA4B,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,yBAAyB,CAAC,UAAU,CAAC,CAAC;QAE3C,mCAAmC;QACnC,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QAC7C,qBAAqB;QACrB,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAEnC,kCAAkC;QAClC,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC;IACH,CAAC;IAEO,eAAe,CAAC,OAAe;QACrC,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,YAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAEO,mBAAmB,CAAC,UAAkB,EAAE,MAAqB;QACnE,MAAM,WAAW,GAAG;YAClB,IAAI,EAAE,0BAA0B;YAChC,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,qDAAqD;YAClE,IAAI,EAAE,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;YAC1D,OAAO,EAAE;gBACP,IAAI,EAAE,oBAAoB,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,EAAE;gBAChG,GAAG,EAAE,4CAA4C,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,EAAE;aACxH;YACD,eAAe,EAAE;gBACf,WAAW,EAAE,SAAS;aACvB;YACD,YAAY,EAAE;YACZ,oCAAoC;aACrC;YACD,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,OAAO,EAAE,KAAK;SACf,CAAC;QAEF,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,EACrC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CACrC,CAAC;IACJ,CAAC;IAEO,cAAc,CAAC,UAAkB,EAAE,MAAqB;QAC9D,MAAM,aAAa,GAAG;;sCAEY,MAAM,CAAC,MAAM;;;;;;;;;;;;oCAYf,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;;;;;;;;;CAYzE,CAAC;QAEE,YAAE,CAAC,aAAa,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,aAAa,CAAC,CAAC;IACtE,CAAC;IACO,yBAAyB,CAAC,UAAkB;QAClD,MAAM,OAAO,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BnB,CAAC;QACE,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,EACvD,OAAO,CACR,CAAC;IACJ,CAAC;IACO,qBAAqB,CAAC,UAAkB;QAC9C,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCzB,CAAC;QAEE,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,CAAC,EACnD,aAAa,CACd,CAAC;IACJ,CAAC;IACO,4BAA4B,CAAC,UAAkB;QACrD,MAAM,OAAO,GAAG;;;;;;;;CAQnB,CAAC;QACE,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,uBAAuB,CAAC,EAC1D,OAAO,CACR,CAAC;IACJ,CAAC;IACD,sCAAsC;IAC9B,mBAAmB,CAAC,UAAkB,EAAE,MAAqB;QACnE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,KAAK,IAAI,CAAC;QACtC,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;QAE3C,eAAe;QACf,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;QACtC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC;QAElD,MAAM,WAAW,GAAG;;;;oBAIJ,UAAU;;;;;;;kCAOI,UAAU;;;;;;;;;;;WAWjC,UAAU;iBACJ,OAAO;cACV,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAmEV,UAAU;iBACJ,OAAO;cACV,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mCA+Dc,UAAU,aAAa,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CA8BtB,UAAU;;;;;;;;;;;;;;;;;;;;;;;4CAuBZ,OAAO;;;;;;;;;6CASN,UAAU;;;;;;;;;;;;;0DAaG,SAAS;;;;gDAInB,UAAU;;;;;;;mDAOP,UAAU;;;;;;;8CAOf,UAAU;;;;;;;;;;;oDAWJ,UAAU;;;;;;sDAMR,UAAU;;;;uDAIT,UAAU;;;;;;CAMhE,CAAC;QAEE,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,eAAe,aAAa,EAAE,CAAC,EAC9D,WAAW,CACZ,CAAC;IACJ,CAAC;IACO,iBAAiB,CAAC,UAAkB;QAC1C,MAAM,gBAAgB,GAAG;;;;;;;;;;CAU5B,CAAC;QAEE,YAAE,CAAC,aAAa,CAAC,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC1E,CAAC;IAEO,gBAAgB,CAAC,UAAkB;QACzC,MAAM,QAAQ,GAAG;YACf,eAAe,EAAE;gBACf,MAAM,EAAE,QAAQ;gBAChB,MAAM,EAAE,UAAU;gBAClB,MAAM,EAAE,IAAI;gBACZ,eAAe,EAAE,IAAI;gBACrB,YAAY,EAAE,IAAI;gBAClB,gCAAgC,EAAE,IAAI;gBACtC,KAAK,EAAE,CAAC,IAAI,CAAC;aACd;YACD,OAAO,EAAE,CAAC,UAAU,EAAE,YAAY,CAAC;YACnC,OAAO,EAAE,CAAC,cAAc,CAAC;SAC1B,CAAC;QAEF,YAAE,CAAC,aAAa,CACd,cAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,EACtC,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAClC,CAAC;IACJ,CAAC;CACF;AAvgBD,4CAugBC"}
@@ -0,0 +1,24 @@
1
+ import { InitCommand } from "./commands/init.command";
2
+ import { FeatureParser } from "./generators/feature.parser";
3
+ import { K6ScriptGenerator } from "./generators/k6-script.generator";
4
+ import { ProjectGenerator } from "./generators/project.generator";
5
+ import { K6Runner } from "./runners/k6.runner";
6
+ import { Given, When, Then, And, But } from "./step-registry";
7
+ export { InitCommand, FeatureParser, K6ScriptGenerator, ProjectGenerator, K6Runner, Given, When, Then, And, But, };
8
+ export * from "./types";
9
+ export declare const VERSION: any;
10
+ declare const _default: {
11
+ InitCommand: typeof InitCommand;
12
+ FeatureParser: typeof FeatureParser;
13
+ K6ScriptGenerator: typeof K6ScriptGenerator;
14
+ ProjectGenerator: typeof ProjectGenerator;
15
+ K6Runner: typeof K6Runner;
16
+ Given: typeof Given;
17
+ When: typeof When;
18
+ Then: typeof Then;
19
+ And: typeof And;
20
+ But: typeof But;
21
+ VERSION: any;
22
+ };
23
+ export default _default;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAE9D,OAAO,EACL,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,GAAG,EACH,GAAG,GACJ,CAAC;AAGF,cAAc,SAAS,CAAC;AAGxB,eAAO,MAAM,OAAO,KAAqC,CAAC;;;;;;;;;;;;;;AAG1D,wBAYE"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.VERSION = exports.But = exports.And = exports.Then = exports.When = exports.Given = exports.K6Runner = exports.ProjectGenerator = exports.K6ScriptGenerator = exports.FeatureParser = exports.InitCommand = void 0;
18
+ // src/index.ts
19
+ const init_command_1 = require("./commands/init.command");
20
+ Object.defineProperty(exports, "InitCommand", { enumerable: true, get: function () { return init_command_1.InitCommand; } });
21
+ const feature_parser_1 = require("./generators/feature.parser");
22
+ Object.defineProperty(exports, "FeatureParser", { enumerable: true, get: function () { return feature_parser_1.FeatureParser; } });
23
+ const k6_script_generator_1 = require("./generators/k6-script.generator");
24
+ Object.defineProperty(exports, "K6ScriptGenerator", { enumerable: true, get: function () { return k6_script_generator_1.K6ScriptGenerator; } });
25
+ const project_generator_1 = require("./generators/project.generator");
26
+ Object.defineProperty(exports, "ProjectGenerator", { enumerable: true, get: function () { return project_generator_1.ProjectGenerator; } });
27
+ const k6_runner_1 = require("./runners/k6.runner");
28
+ Object.defineProperty(exports, "K6Runner", { enumerable: true, get: function () { return k6_runner_1.K6Runner; } });
29
+ const step_registry_1 = require("./step-registry");
30
+ Object.defineProperty(exports, "Given", { enumerable: true, get: function () { return step_registry_1.Given; } });
31
+ Object.defineProperty(exports, "When", { enumerable: true, get: function () { return step_registry_1.When; } });
32
+ Object.defineProperty(exports, "Then", { enumerable: true, get: function () { return step_registry_1.Then; } });
33
+ Object.defineProperty(exports, "And", { enumerable: true, get: function () { return step_registry_1.And; } });
34
+ Object.defineProperty(exports, "But", { enumerable: true, get: function () { return step_registry_1.But; } });
35
+ // Export types
36
+ __exportStar(require("./types"), exports);
37
+ // Main package version
38
+ exports.VERSION = require("../package.json").version;
39
+ // Default export for convenience
40
+ exports.default = {
41
+ InitCommand: init_command_1.InitCommand,
42
+ FeatureParser: feature_parser_1.FeatureParser,
43
+ K6ScriptGenerator: k6_script_generator_1.K6ScriptGenerator,
44
+ ProjectGenerator: project_generator_1.ProjectGenerator,
45
+ K6Runner: k6_runner_1.K6Runner,
46
+ Given: step_registry_1.Given,
47
+ When: step_registry_1.When,
48
+ Then: step_registry_1.Then,
49
+ And: step_registry_1.And,
50
+ But: step_registry_1.But,
51
+ VERSION: exports.VERSION,
52
+ };
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,eAAe;AACf,0DAAsD;AAQpD,4FARO,0BAAW,OAQP;AAPb,gEAA4D;AAQ1D,8FARO,8BAAa,OAQP;AAPf,0EAAqE;AAQnE,kGARO,uCAAiB,OAQP;AAPnB,sEAAkE;AAQhE,iGARO,oCAAgB,OAQP;AAPlB,mDAA+C;AAQ7C,yFARO,oBAAQ,OAQP;AAPV,mDAA8D;AAQ5D,sFARO,qBAAK,OAQP;AACL,qFATc,oBAAI,OASd;AACJ,qFAVoB,oBAAI,OAUpB;AACJ,oFAX0B,mBAAG,OAW1B;AACH,oFAZ+B,mBAAG,OAY/B;AAGL,eAAe;AACf,0CAAwB;AAExB,uBAAuB;AACV,QAAA,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,CAAC;AAE1D,iCAAiC;AACjC,kBAAe;IACb,WAAW,EAAX,0BAAW;IACX,aAAa,EAAb,8BAAa;IACb,iBAAiB,EAAjB,uCAAiB;IACjB,gBAAgB,EAAhB,oCAAgB;IAChB,QAAQ,EAAR,oBAAQ;IACR,KAAK,EAAL,qBAAK;IACL,IAAI,EAAJ,oBAAI;IACJ,IAAI,EAAJ,oBAAI;IACJ,GAAG,EAAH,mBAAG;IACH,GAAG,EAAH,mBAAG;IACH,OAAO,EAAP,eAAO;CACR,CAAC"}
@@ -0,0 +1,19 @@
1
+ export declare class K6Runner {
2
+ runFromFeatures(featuresPath: string, outputScriptPath?: string, options?: {
3
+ tags?: string;
4
+ group?: string;
5
+ language?: "js" | "ts";
6
+ additionalK6Options?: string[];
7
+ }): Promise<void>;
8
+ runK6Test(scriptPath: string, additionalOptions?: string[]): Promise<void>;
9
+ runGeneratedScript(scriptPath: string, options?: string[]): Promise<void>;
10
+ private filterFeaturesByTags;
11
+ private filterFeaturesByGroup;
12
+ runWithFilters(featuresPath: string, filters: {
13
+ tags?: string;
14
+ group?: string;
15
+ vus?: number;
16
+ duration?: string;
17
+ }): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=k6.runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k6.runner.d.ts","sourceRoot":"","sources":["../../src/runners/k6.runner.ts"],"names":[],"mappings":"AAWA,qBAAa,QAAQ;IACb,eAAe,CACnB,YAAY,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,MAAM,EACzB,OAAO,GAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;QACvB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;KAC3B,GACL,OAAO,CAAC,IAAI,CAAC;IAuDV,SAAS,CACb,UAAU,EAAE,MAAM,EAClB,iBAAiB,CAAC,EAAE,MAAM,EAAE,GAC3B,OAAO,CAAC,IAAI,CAAC;IAsCV,kBAAkB,CACtB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC;IAQhB,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,qBAAqB;IAgBvB,cAAc,CAClB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GACA,OAAO,CAAC,IAAI,CAAC;CAiBjB"}