k6-cucumber-steps 1.1.4 → 1.1.6

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/README.md CHANGED
@@ -5,12 +5,14 @@
5
5
  </td></tr></table>
6
6
 
7
7
  [![npm version](https://img.shields.io/npm/v/k6-cucumber-steps.svg)](https://www.npmjs.com/package/k6-cucumber-steps)
8
- [![npm downloads](https://img.shields.io/npm/dt/k6-cucumber-steps.svg)](https://www.npmjs.com/package/k6-cucumber-steps)
9
- [![license](https://img.shields.io/npm/l/k6-cucumber-steps)](https://github.com/qaPaschalE/k6-cucumber-steps/blob/main/LICENSE)
10
- [![Cucumber](https://img.shields.io/badge/built%20with-Cucumber-3178c6.svg)](https://cucumber.io/)
8
+ [![Built with k6](https://img.shields.io/badge/built%20with-k6-7D64FF?logo=k6&logoColor=white&style=flat-square)](https://k6.io/)
9
+ [![license](https://img.shields.io/npm/l/k6-cucumber-steps?logo=github)](https://github.com/qaPaschalE/k6-cucumber-steps/blob/main/LICENSE)
10
+ [![Built for Cucumber](https://img.shields.io/badge/built%20for-Cucumber-23d96c?logo=cucumber&logoColor=white&style=flat-square)](https://cucumber.io/)
11
11
  [![Node.js](https://img.shields.io/badge/node-%3E=18-green.svg)](https://nodejs.org/)
12
- [![Sponsor](https://img.shields.io/github/sponsors/qaPaschalE?style=social)](https://github.com/sponsors/qaPaschalE)
13
- [![Build Status](https://github.com/qaPaschalE/k6-cucumber-steps/actions/workflows/k6-load-test.yml/badge.svg)](https://github.com/aPaschalE/k6-cucumber-steps/actions/workflows/k6-load-test.yml)
12
+ [![Build Status](https://github.com/qaPaschalE/k6-cucumber-steps/actions/workflows/k6-load-test.yml/badge.svg)](https://github.com/qaPaschalE/k6-cucumber-steps/actions/workflows/k6-load-test.yml)
13
+ [![Issues](https://img.shields.io/github/issues/qaPaschalE/k6-cucumber-steps?style=flat-square)](https://github.com/qaPaschalE/k6-cucumber-steps/issues)
14
+ [![Stars](https://img.shields.io/github/stars/qaPaschalE/k6-cucumber-steps?style=flat-square)](https://github.com/qaPaschalE/k6-cucumber-steps/stargazers)
15
+ [![npm downloads](https://img.shields.io/npm/dt/k6-cucumber-steps?logo=download&logoColor=white&style=flat-square)](https://www.npmjs.com/package/k6-cucumber-steps)
14
16
 
15
17
  Run [k6](https://k6.io/) performance/load tests using [Cucumber](https://cucumber.io/) BDD syntax with ease.
16
18
 
@@ -18,20 +20,19 @@ Run [k6](https://k6.io/) performance/load tests using [Cucumber](https://cucumbe
18
20
 
19
21
  ## ✨ Features
20
22
 
21
- - ✅ Cucumber + Gherkin for writing k6 tests
22
- to generate JSON and HTML reports.
23
+ - ✅ Cucumber + Gherkin for writing k6 tests to generate JSON and HTML reports.
23
24
  - ✅ Flexible configuration through Cucumber data tables.
24
- - ✅ Support for JSON body parsing and escaping
25
+ - ✅ Support for JSON body parsing and escaping.
25
26
  - ✅ Dynamic request body generation using environment variables, Faker templates, and JSON file includes.
26
27
  - ✅ `.env` + `K6.env`-style variable resolution (`{{API_KEY}}`)
27
- - ✅ Support for headers, query params, stages
28
+ - ✅ Support for headers, query params, stages.
28
29
  - ✅ Supports multiple authentication types: API key, Bearer token, Basic Auth, and No Auth.
29
-
30
- - ✅ Clean-up of temporary k6 files after execution
31
- - ✅ Built-in support for **distributed load testing** with stages
30
+ - ✅ Clean-up of temporary k6 files after execution.
31
+ - ✅ Built-in support for **distributed load testing** with stages.
32
32
  - ✅ TypeScript-first 🧡
33
33
  - ✅ **Optional report overwriting**: Use the `overwrite` option to control whether reports are overwritten or appended.
34
- - ✅ **Generate detailed reports**: Use the `--reporter` flag
34
+ - ✅ **Generate detailed reports**: Use the `--reporter` flag.
35
+ - ✅ **Clean reports directory before run**: Use the `--cleanReports`/`--clean` CLI flag, `CLEAN_REPORTS=true` in `.env`, or `cleanReports: true` in your `cucumber.js` config.
35
36
 
36
37
  ---
37
38
 
@@ -55,13 +56,16 @@ The `run` command accepts the following options:
55
56
 
56
57
  - `-f, --feature <path>`: Path to the feature file to execute.
57
58
  - `-t, --tags <string>`: Cucumber tags to filter scenarios (e.g., `@smoke and not @regression`).
59
+ - `-c, --config <file>`: Custom config file (default: `cucumber.js`).
58
60
  - `-r, --reporter`: Generate HTML and JSON reports in the `reports` directory. This is a boolean flag, so just include `-r, --reporter` to enable it.
59
61
  - `-o, --overwrite`: Overwrite existing reports instead of appending them.
62
+ - `--cleanReports`, `--clean`: **Clean the `reports` directory before running.**
63
+ You can also set this via the `cleanReports` property in your `cucumber.js` config or with the `CLEAN_REPORTS=true` environment variable.
60
64
 
61
65
  ### Example Usage with Options
62
66
 
63
67
  ```bash
64
- npx k6-cucumber-steps run --feature ./features/my_feature.feature --tags "@load and not @wip" --reporter
68
+ npx k6-cucumber-steps run --feature ./features/my_feature.feature --tags "@load and not @wip" --reporter --cleanReports
65
69
  ```
66
70
 
67
71
  ---
@@ -73,9 +77,9 @@ Here's a step-by-step guide to using `k6-cucumber-steps` in your project:
73
77
  **Prerequisites:**
74
78
 
75
79
  1. **Node.js and npm (or yarn):** Ensure you have Node.js and npm (or yarn) installed.
76
- 2. **k6:** Install k6 on your system following the instructions at [k6.io/docs/getting-started/installation/](https://www.google.com/search?q=https://k6.io/docs/getting-started/installation/).
77
- 3. **@cucumber/cucumber:(optional)** This package is required for using Cucumber.
78
- 4. **cucumber-html-reporter:(optional)** This package is needed if you intend to generate detailed HTML reports
80
+ 2. **k6:** Install k6 on your system following the instructions at [k6.io/docs/getting-started/installation/](https://k6.io/docs/getting-started/installation/).
81
+ 3. **@cucumber/cucumber (optional):** This package is required for using Cucumber.
82
+ 4. **cucumber-html-reporter (optional):** This package is needed if you intend to generate detailed HTML reports.
79
83
 
80
84
  **Setup:**
81
85
 
@@ -116,7 +120,7 @@ Here's a step-by-step guide to using `k6-cucumber-steps` in your project:
116
120
  require: [
117
121
  // You can add paths to your local step definitions here if needed
118
122
  ],
119
- reporter:true // To provide HTML and JSON report
123
+ reporter: true, // To provide HTML and JSON report
120
124
  format: [
121
125
  "summary",
122
126
  "json:reports/load-report.json", // For JSON report
@@ -125,25 +129,27 @@ Here's a step-by-step guide to using `k6-cucumber-steps` in your project:
125
129
  paths: ["./features/*.feature"],
126
130
  tags: process.env.TAGS,
127
131
  worldParameters: {
128
- payloadPath: "apps/qa/performance/payloads"
129
- }
132
+ payloadPath: "apps/qa/performance/payloads",
133
+ },
130
134
  overwrite: false, // Default to not overwrite the report file
135
+ cleanReports: true, // <--- Clean the reports directory before running
131
136
  };
132
137
  ```
133
138
 
134
- **Running Tests:**
139
+ **Controlling Report Directory Clean-up**
135
140
 
136
- From the root of your project, use the CLI command for default config:
141
+ You can control whether the `reports` directory is cleaned before each run using any of these methods:
137
142
 
138
- ```bash
139
- npx k6-cucumber-steps run
140
- ```
143
+ - **Command-line:**
144
+ Add `--cleanReports` or `--clean` to your CLI command.
141
145
 
142
- You can also specify a configFile:
146
+ - **Environment variable:**
147
+ Add `CLEAN_REPORTS=true` to your `.env` file.
143
148
 
144
- ```bash
145
- npx k6-cucumber-steps run --configFile cucumber.prod.js
146
- ```
149
+ - **Config file:**
150
+ Set `cleanReports: true` in your `cucumber.js` config.
151
+
152
+ Priority order: **CLI > Environment variable > Config file**
147
153
 
148
154
  ---
149
155
 
@@ -152,8 +158,8 @@ npx k6-cucumber-steps run --configFile cucumber.prod.js
152
158
  1. **Environment Variables**: Create a `.env` file in your project root based on the provided `.env.example`:
153
159
 
154
160
  ```env
155
- BASE_URL=[https://api.example.com](https://api.example.com)
156
- API_BASE_URL=[https://api.example.com](https://api.example.com)
161
+ BASE_URL=https://api.example.com
162
+ API_BASE_URL=https://api.example.com
157
163
  API_KEY=your_api_key
158
164
  BEARER_TOKEN=your_bearer_token
159
165
  BASIC_USER=your_basic_user
@@ -180,7 +186,7 @@ Feature: API Performance Testing
180
186
  And I set the following endpoints used:
181
187
  """
182
188
  /api/profile
183
- [https://reqres.in/api/users?page=2](https://reqres.in/api/users?page=2)
189
+ https://reqres.in/api/users?page=2
184
190
  """
185
191
  And I set the authentication type to "none"
186
192
  Then I see the API should handle the GET request successfully
@@ -234,7 +240,6 @@ When I set the request headers:
234
240
  When I set the following endpoints used:
235
241
  When I set the following {word} body is used for {string}
236
242
  When I store the value at {string} as alias {string}
237
-
238
243
  ```
239
244
 
240
245
  ### Assertion Steps
@@ -272,12 +277,4 @@ If you find this package useful, consider [sponsoring me on GitHub](https://gith
272
277
 
273
278
  MIT License - [@qaPaschalE](https://github.com/qaPaschalE)
274
279
 
275
- ```
276
-
277
-
278
- ## License
279
-
280
280
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
281
-
282
-
283
- ```
@@ -1,231 +1,128 @@
1
1
  #!/usr/bin/env node
2
- //bin/k6-cucumber-steps.js
3
2
  const path = require("path");
4
3
  const fs = require("fs");
5
4
  const { spawn } = require("child_process");
6
- const yargs = require("yargs/yargs");
7
- const { hideBin } = require("yargs/helpers");
5
+ const { Command } = require("commander");
8
6
  require("dotenv").config();
9
7
 
8
+ const { linkReports } = require("../scripts/linkReports");
9
+
10
10
  console.log(`
11
11
  -----------------------------------------
12
12
  🚀 Starting k6-cucumber-steps execution...
13
13
  -----------------------------------------
14
14
  `);
15
15
 
16
- // Parse CLI arguments
17
- const argv = yargs(hideBin(process.argv))
18
- .usage("Usage: $0 run [options]")
19
- .option("feature", {
20
- alias: "f",
21
- describe: "Path to the feature file",
22
- type: "string",
23
- })
24
- .option("tags", {
25
- alias: "t",
26
- describe: "Cucumber tags to filter scenarios (e.g., @smoke)",
27
- type: "string",
28
- })
29
- .option("reporter", {
30
- alias: "r",
31
- describe: "Enable HTML and JSON reports",
32
- type: "boolean",
33
- default: false,
34
- })
35
- .option("overwrite", {
36
- alias: "o",
37
- describe: "Overwrite existing reports",
38
- type: "boolean",
39
- default: false,
40
- })
41
- .option("configFile", {
42
- alias: "c",
43
- describe: "Custom cucumber config file",
44
- type: "string",
45
- })
46
- .help().argv;
47
-
48
- // Base Cucumber arguments
16
+ const program = new Command();
17
+
18
+ program
19
+ .command("run")
20
+ .option("-f, --feature <path>", "Feature file path")
21
+ .option("-t, --tags <string>", "Cucumber tags")
22
+ .option("-c, --config <file>", "Custom config file") // changed from --configFile to --config
23
+ .option("-r, --reporter", "Enable report generation", false)
24
+ .option("-o, --overwrite", "Overwrite report files", false)
25
+ .option("--cleanReports", "Clean the reports folder before running")
26
+ .option("--clean", "Alias for --cleanReports");
27
+
28
+ program.parse(process.argv);
29
+
30
+ const argv = program.opts();
31
+
49
32
  const cucumberArgs = ["cucumber-js"];
50
33
 
51
- // Load custom configuration file if provided
52
- const configFileName =
53
- argv.configFile || process.env.CUCUMBER_CONFIG_FILE || "cucumber.js";
54
- const configFilePath = path.resolve(process.cwd(), configFileName);
34
+ // Update all references to argv.configFile to argv.config:
35
+ const configFileInput =
36
+ argv.config || process.env.CUCUMBER_CONFIG_FILE || "cucumber.js";
37
+ const configFilePath = path.isAbsolute(configFileInput)
38
+ ? configFileInput
39
+ : path.resolve(process.cwd(), configFileInput);
55
40
 
56
41
  let configOptions = {};
42
+
57
43
  if (fs.existsSync(configFilePath)) {
58
- cucumberArgs.push("--config", configFileName);
44
+ cucumberArgs.push("--config", configFileInput);
59
45
  try {
60
46
  const loadedConfig = require(configFilePath);
61
47
  configOptions = loadedConfig.default || loadedConfig;
62
48
  } catch (err) {
63
49
  console.warn("⚠️ Could not load config file:", err.message);
64
50
  }
51
+ } else {
52
+ console.warn(`⚠️ Config file not found at ${configFilePath}`);
65
53
  }
66
54
 
67
- // Tags
68
- const tags = argv.tags || process.env.TAGS || configOptions.tags;
69
- if (tags) {
70
- cucumberArgs.push("--tags", tags);
55
+ // Resolve cleanReports: CLI > ENV > config file
56
+ const cleanReports =
57
+ typeof argv.cleanReports === "boolean"
58
+ ? argv.cleanReports
59
+ : typeof argv.clean === "boolean"
60
+ ? argv.clean
61
+ : process.env.CLEAN_REPORTS
62
+ ? process.env.CLEAN_REPORTS === "true"
63
+ : configOptions.cleanReports;
64
+
65
+ // Clean reports directory if needed
66
+ const reportsDir = path.resolve("reports");
67
+ if (cleanReports) {
68
+ if (fs.existsSync(reportsDir)) {
69
+ fs.rmSync(reportsDir, { recursive: true, force: true });
70
+ console.log("🧹 Cleaned reports directory.");
71
+ }
72
+ }
73
+ if (!fs.existsSync(reportsDir)) {
74
+ fs.mkdirSync(reportsDir, { recursive: true });
71
75
  }
72
76
 
73
- // Feature file(s)
77
+ // Build featureFiles array before using it
74
78
  let featureFiles = [];
75
79
  if (argv.feature) {
76
80
  featureFiles.push(path.resolve(argv.feature));
77
- } else if (configOptions.paths && configOptions.paths.length > 0) {
78
- featureFiles.push(...configOptions.paths.map((p) => path.resolve(p)));
79
- }
80
- if (featureFiles.length > 0) {
81
- cucumberArgs.push(...featureFiles);
81
+ } else if (Array.isArray(configOptions.paths)) {
82
+ featureFiles = configOptions.paths.map((f) => path.resolve(f));
82
83
  }
83
84
 
84
- // Require step definitions
85
- const defaultStepsPath = path.resolve(
86
- process.cwd(),
87
- "node_modules",
88
- "k6-cucumber-steps",
89
- "step_definitions"
90
- );
91
- cucumberArgs.push("--require", defaultStepsPath);
92
-
93
- // Include additional custom step definitions from config
94
- if (configOptions.require && Array.isArray(configOptions.require)) {
95
- for (const reqPath of configOptions.require) {
96
- cucumberArgs.push("--require", path.resolve(reqPath));
97
- }
98
- }
99
-
100
- // Reports directory setup
101
- const reportsDir = path.join(process.cwd(), "reports");
102
-
103
- // Clean and prepare reports directory
104
- const cleanReportsDir = () => {
105
- if (fs.existsSync(reportsDir)) {
106
- try {
107
- fs.rmSync(reportsDir, { recursive: true, force: true });
108
- console.log("🧹 Cleaned existing reports directory.");
109
- } catch (err) {
110
- console.error("❌ Failed to clean reports directory:", err.message);
111
- process.exit(1);
112
- }
113
- }
114
-
115
- try {
116
- fs.mkdirSync(reportsDir, { recursive: true });
117
- console.log("📁 Created fresh reports directory.");
118
- } catch (err) {
119
- console.error("❌ Failed to create reports directory:", err.message);
120
- process.exit(1);
121
- }
122
- };
123
-
124
- cleanReportsDir();
125
-
126
- // Determine base report name
127
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
128
-
129
85
  let baseReportName = "load-report";
130
86
  if (featureFiles.length === 1) {
131
- const nameFromFeature = path.basename(featureFiles[0], ".feature");
132
- baseReportName = nameFromFeature || baseReportName;
87
+ baseReportName = path.basename(featureFiles[0], ".feature");
133
88
  } else if (featureFiles.length > 1) {
134
89
  baseReportName = "multi-feature";
135
90
  }
91
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
92
+ let reportHtmlPath = path.join(reportsDir, `cucumber-report.html`);
136
93
 
137
- const shouldGenerateReports = argv.reporter || configOptions.reporter || false;
138
- const shouldOverwrite =
139
- argv.overwrite ||
140
- process.env.K6_CUCUMBER_OVERWRITE === "true" ||
141
- configOptions.overwrite === true;
142
-
143
- let reportJsonPath = path.join(reportsDir, `${baseReportName}.json`);
144
- let reportHtmlPath = path.join(reportsDir, `${baseReportName}.html`);
145
-
146
- if (!shouldOverwrite) {
147
- reportJsonPath = path.join(reportsDir, `${baseReportName}-${timestamp}.json`);
148
- reportHtmlPath = path.join(reportsDir, `${baseReportName}-${timestamp}.html`);
149
- }
150
-
151
- // Respect config format path if defined
152
- if (Array.isArray(configOptions.format)) {
153
- const jsonFmt = configOptions.format.find((f) => f.startsWith("json:"));
154
- if (jsonFmt) {
155
- reportJsonPath = jsonFmt.split("json:")[1];
156
- console.log(`📝 Using report path from config: ${reportJsonPath}`);
157
- }
158
- }
159
-
160
- const formatInConfig =
161
- Array.isArray(configOptions.format) && configOptions.format.length > 0;
162
-
163
- if (shouldGenerateReports && !formatInConfig) {
94
+ if (argv.reporter && !Array.isArray(configOptions.format)) {
164
95
  cucumberArgs.push("--format", "summary");
165
- cucumberArgs.push("--format", `json:${reportJsonPath}`);
166
96
  cucumberArgs.push("--format", `html:${reportHtmlPath}`);
167
97
  }
168
98
 
169
99
  console.log("\n▶️ Final arguments passed to cucumber-js:");
170
100
  console.log(["npx", ...cucumberArgs].join(" ") + "\n");
171
101
 
172
- // Execute Cucumber process
173
102
  const cucumberProcess = spawn("npx", cucumberArgs, {
174
103
  stdio: "inherit",
175
104
  env: {
176
105
  ...process.env,
177
- K6_CUCUMBER_OVERWRITE: shouldOverwrite ? "true" : "false",
178
- TAGS: tags,
179
- FEATURE_PATH: featureFiles.join(","),
180
- REPORT_JSON_PATH: reportJsonPath,
181
106
  REPORT_HTML_PATH: reportHtmlPath,
107
+ K6_CUCUMBER_OVERWRITE: argv.overwrite ? "true" : "false",
182
108
  },
183
109
  });
184
110
 
185
- function detectMostRecentK6Report() {
186
- const files = fs
187
- .readdirSync(reportsDir)
188
- .filter((file) => /^k6-report.*\.html$/.test(file))
189
- .map((file) => ({
190
- name: file,
191
- time: fs.statSync(path.join(reportsDir, file)).mtime.getTime(),
192
- }))
193
- .sort((a, b) => b.time - a.time);
194
-
195
- return files.length > 0 ? path.join(reportsDir, files[0].name) : null;
196
- }
197
-
198
111
  cucumberProcess.on("close", async (code) => {
199
112
  if (code === 0) {
200
113
  console.log("-----------------------------------------");
201
114
  console.log("✅ k6-cucumber-steps execution completed successfully.");
202
-
203
- // Generate Cucumber HTML report
204
- try {
205
- await generateHtmlReports();
206
- console.log(
207
- `🚀 Cucumber HTML report generated successfully at: ${reportHtmlPath}`
208
- );
209
- } catch (err) {
210
- console.error("⚠️ Failed to generate Cucumber HTML report:", err.message);
211
- }
212
-
213
- // Link reports
214
115
  try {
215
116
  await linkReports();
216
- console.log(
217
- "🔗 Combined and minified HTML report available at: reports/combined-report.html"
218
- );
117
+ console.log("🔗 Reports linked successfully with embedded Cucumber tab.");
219
118
  } catch (err) {
220
119
  console.error("⚠️ Failed to link reports:", err.message);
221
120
  }
222
-
223
121
  console.log("-----------------------------------------");
224
122
  } else {
225
123
  console.error("-----------------------------------------");
226
124
  console.error("❌ k6-cucumber-steps execution failed.");
227
125
  console.error("-----------------------------------------");
228
126
  }
229
-
230
127
  process.exit(code);
231
128
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k6-cucumber-steps",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -33,6 +33,15 @@
33
33
  "bin": {
34
34
  "k6-cucumber-steps": "./bin/k6-cucumber-steps.js"
35
35
  },
36
+ "files": [
37
+ "bin/",
38
+ "lib/",
39
+ "step_definitions/",
40
+ "scripts/",
41
+ "package.json",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
36
45
  "keywords": [
37
46
  "k6",
38
47
  "cucumber",
@@ -59,12 +68,11 @@
59
68
  "@babel/preset-env": "^7.27.2",
60
69
  "@faker-js/faker": "^9.8.0",
61
70
  "@types/k6": "^1.0.2",
62
- "axios": "^1.10.0",
63
71
  "dotenv": "^16.5.0",
64
- "html-minifier-terser": "^7.2.0",
65
- "yargs": "^18.0.0"
72
+ "html-minifier-terser": "^7.2.0"
66
73
  },
67
74
  "dependencies": {
68
- "@babel/register": "^7.27.1"
75
+ "@babel/register": "^7.27.1",
76
+ "commander": "^14.0.0"
69
77
  }
70
78
  }
@@ -1,69 +1,62 @@
1
1
  const fs = require("fs");
2
2
  const path = require("path");
3
+ const { minify } = require("html-minifier-terser");
3
4
 
4
5
  const reportsDir = path.resolve("reports");
5
6
 
6
- /**
7
- * Finds the first file that looks like a Cucumber HTML report.
8
- */
9
- function findCucumberReportFile() {
10
- const files = fs.readdirSync(reportsDir);
11
- return files.find((f) => f.includes("cucumber") && f.endsWith(".html"));
12
- }
13
-
14
- /**
15
- * Adds a Cucumber report tab as an iframe.
16
- */
17
- function addLinksToReport(targetFile, cucumberFileName) {
18
- const content = fs.readFileSync(targetFile, "utf-8");
19
-
20
- const cucumberTab = `
21
- <input type="radio" name="tabs" id="tabcucumber">
22
- <label for="tabcucumber"><i class="fas fa-file-alt"></i> &nbsp; Cucumber Report</label>
23
- <div class="tab">
24
- ${
25
- cucumberFileName
26
- ? `<iframe src="${cucumberFileName}" style="width:100%; min-height:600px; border:none;"></iframe>`
27
- : `<p style="color:red; padding:1rem;">⚠️ Cucumber HTML report not found in <code>reports/</code> directory.</p>`
28
- }
29
- </div>
30
- `;
31
-
32
- const modifiedContent = content
33
- .replace(
34
- /<input type="radio" name="tabs" id="tabone"/,
35
- `${cucumberTab}\n<input type="radio" name="tabs" id="tabone"`
36
- )
37
- .replace(/<div style="[^>]*margin-top:20px;[^>]*">[\s\S]*?<\/div>/g, "");
38
-
39
- fs.writeFileSync(targetFile, modifiedContent, "utf-8");
40
- }
41
-
42
- /**
43
- * Adds a Cucumber tab to every K6 HTML report found in /reports.
44
- */
45
- function linkReports() {
7
+ async function linkReports() {
46
8
  if (!fs.existsSync(reportsDir)) {
47
9
  console.warn("⚠️ No reports directory found.");
48
10
  return;
49
11
  }
50
12
 
51
- const cucumberFile = findCucumberReportFile();
52
-
53
13
  const htmlFiles = fs
54
14
  .readdirSync(reportsDir)
55
- .filter((f) => /^k6-report.*\.html$/.test(f));
56
-
57
- if (htmlFiles.length === 0) {
58
- console.warn("⚠️ No K6 reports found to inject.");
15
+ .filter((f) => f.endsWith(".html"));
16
+ const k6ReportFile = htmlFiles.find(
17
+ (f) => f.startsWith("k6-report") && f.endsWith(".html")
18
+ );
19
+ const cucumberReportFile = htmlFiles.find((f) =>
20
+ f.includes("cucumber-report")
21
+ );
22
+
23
+ if (!k6ReportFile || !cucumberReportFile) {
24
+ console.warn("⚠️ K6 or Cucumber HTML report not found.");
59
25
  return;
60
26
  }
61
27
 
62
- htmlFiles.forEach((file) => {
63
- const fullPath = path.join(reportsDir, file);
64
- addLinksToReport(fullPath, cucumberFile);
65
- console.log(`🔗 Injected Cucumber tab into: ${file}`);
28
+ const k6Path = path.join(reportsDir, k6ReportFile);
29
+ const cucumberPath = path.basename(cucumberReportFile);
30
+ let content = fs.readFileSync(k6Path, "utf8");
31
+
32
+ const cucumberTab = `
33
+ <input type="radio" name="tabs" id="tabcucumber">
34
+ <label for="tabcucumber"><i class="fas fa-file-alt"></i> &nbsp; Cucumber Report</label>
35
+ <div class="tab">
36
+ <iframe src="${cucumberPath}" style="width:100%; height:600px; border:none;"></iframe>
37
+ </div>
38
+ `;
39
+
40
+ content = content.replace(
41
+ /<input type="radio" name="tabs" id="tabone"/,
42
+ `${cucumberTab}\n<input type="radio" name="tabs" id="tabone"`
43
+ );
44
+
45
+ content = content.replace(
46
+ /<div style="padding:10px;margin-top:20px;text-align:center">[\s\S]*?<\/div>/,
47
+ ""
48
+ );
49
+
50
+ const minified = await minify(content, {
51
+ collapseWhitespace: true,
52
+ removeComments: true,
53
+ minifyCSS: true,
66
54
  });
55
+
56
+ const combinedPath = path.join(reportsDir, "combined-report.html");
57
+ fs.writeFileSync(combinedPath, minified, "utf8");
58
+
59
+ console.log(`📄 Combined report generated at: ${combinedPath}`);
67
60
  }
68
61
 
69
62
  module.exports = { linkReports };
@@ -9,7 +9,6 @@ const buildK6Script = require("../lib/helpers/buildK6Script.js");
9
9
  const generateHeaders = require("../lib/helpers/generateHeaders.js");
10
10
  const { generateK6Script, runK6Script } = require("../lib/utils/k6Runner.js");
11
11
  require("dotenv").config();
12
- const axios = require("axios");
13
12
 
14
13
  // Validate thresholds (e.g., "rate<0.01")
15
14
  const validateThreshold = (threshold) => {
@@ -278,17 +277,22 @@ When(
278
277
  });
279
278
 
280
279
  try {
281
- const response = await axios.post(
282
- `${process.env.BASE_URL}${endpoint}`,
283
- resolved,
284
- {
285
- headers: {
286
- "Content-Type": "application/json",
287
- },
288
- }
289
- );
280
+ const response = await fetch(`${process.env.BASE_URL}${endpoint}`, {
281
+ method: "POST",
282
+ headers: {
283
+ "Content-Type": "application/json",
284
+ },
285
+ body: JSON.stringify(resolved),
286
+ });
287
+
288
+ const data = await response.json();
289
+
290
+ if (!response.ok) {
291
+ console.error("❌ Login request failed:", data);
292
+ throw new Error(`Login request failed with status ${response.status}`);
293
+ }
290
294
 
291
- this.lastResponse = response.data; // ✅ Makes aliasing work
295
+ this.lastResponse = data; // ✅ Makes aliasing work
292
296
  console.log("🔐 Login successful, response saved to alias context.");
293
297
  } catch (err) {
294
298
  console.error("❌ Login request failed:", err.message);