k6-cucumber-steps 1.0.41 โ†’ 1.1.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.
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
-
2
+ //bin/k6-cucumber-steps.js
3
3
  const path = require("path");
4
4
  const fs = require("fs");
5
5
  const { spawn } = require("child_process");
6
6
  const yargs = require("yargs");
7
7
  require("dotenv").config();
8
+ const { generateHtmlReports } = require("../scripts/generateHtmlReports");
9
+ const { linkReports } = require("../scripts/linkReports");
8
10
 
9
11
  console.log(`
10
12
  -----------------------------------------
@@ -95,9 +97,32 @@ if (configOptions.require && Array.isArray(configOptions.require)) {
95
97
 
96
98
  // Determine base report name
97
99
  const reportsDir = path.join(process.cwd(), "reports");
100
+ // Clean and prepare reports directory
101
+ const cleanReportsDir = () => {
102
+ if (fs.existsSync(reportsDir)) {
103
+ try {
104
+ fs.rmSync(reportsDir, { recursive: true, force: true });
105
+ console.log("๐Ÿงน Cleaned existing reports directory.");
106
+ } catch (err) {
107
+ console.error("โŒ Failed to clean reports directory:", err.message);
108
+ process.exit(1);
109
+ }
110
+ }
111
+
112
+ try {
113
+ fs.mkdirSync(reportsDir, { recursive: true });
114
+ console.log("๐Ÿ“ Created fresh reports directory.");
115
+ } catch (err) {
116
+ console.error("โŒ Failed to create reports directory:", err.message);
117
+ process.exit(1);
118
+ }
119
+ };
120
+
121
+ cleanReportsDir();
122
+
98
123
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
99
124
 
100
- let baseReportName = "load-results";
125
+ let baseReportName = "load-report";
101
126
  if (featureFiles.length === 1) {
102
127
  const nameFromFeature = path.basename(featureFiles[0], ".feature");
103
128
  baseReportName = nameFromFeature || baseReportName;
@@ -145,12 +170,30 @@ const cucumberProcess = spawn("npx", cucumberArgs, {
145
170
  });
146
171
 
147
172
  cucumberProcess.on("close", (code) => {
148
- console.log(`\n-----------------------------------------`);
149
173
  if (code === 0) {
174
+ console.log("-----------------------------------------");
150
175
  console.log("โœ… k6-cucumber-steps execution completed successfully.");
176
+
177
+ generateHtmlReports(); // Cucumber HTML
178
+ console.log(
179
+ "๐Ÿš€ Cucumber HTML report reports/cucumber-report.html generated successfully ๐Ÿ‘"
180
+ );
181
+
182
+ const k6ReportPath = detectMostRecentK6Report(); // Add this helper function
183
+ if (k6ReportPath) {
184
+ console.log(
185
+ `๐Ÿ“„ K6 HTML report ${k6ReportPath} generated successfully ๐Ÿ‘`
186
+ );
187
+ }
188
+
189
+ linkReports(); // Link both reports
190
+
191
+ console.log("-----------------------------------------");
151
192
  } else {
193
+ console.error("-----------------------------------------");
152
194
  console.error("โŒ k6-cucumber-steps execution failed.");
195
+ console.error("-----------------------------------------");
153
196
  }
154
- console.log(`-----------------------------------------\n`);
197
+
155
198
  process.exit(code);
156
199
  });
package/cucumber.js CHANGED
@@ -1,12 +1,12 @@
1
1
  module.exports = {
2
2
  default: {
3
- require: ["./step_definitions/**/*.js"],
3
+ // require: ["./step_definitions/**/*.js"],
4
4
  format: [
5
5
  "summary",
6
- "json:./src/examples/reports/load-report.json",
7
- "html:./src/examples/reports/report.html",
6
+ "json:./reports/load-report.json",
7
+ "html:./reports/cucumber-report.html",
8
8
  ],
9
- paths: ["./src/examples/features/*.feature"],
9
+ paths: ["./features/bsp.feature"],
10
10
  tags: "@load",
11
11
  worldParameters: {
12
12
  payloadPath: "src/examples/payloads",
@@ -1,14 +1,12 @@
1
1
  module.exports = function buildK6Script(config) {
2
2
  const { method, endpoints, endpoint, body, headers, options } = config;
3
3
 
4
- // Ensure at least one of `endpoints` or `endpoint` is defined
5
4
  if (!endpoints?.length && !endpoint) {
6
5
  throw new Error(
7
6
  'Either "endpoints" or "endpoint" must be defined in the configuration.'
8
7
  );
9
8
  }
10
9
 
11
- // Prefer API_BASE_URL, fallback to BASE_URL
12
10
  const BASE_URL = process.env.API_BASE_URL || process.env.BASE_URL;
13
11
  if (!BASE_URL) {
14
12
  throw new Error(
@@ -16,18 +14,18 @@ module.exports = function buildK6Script(config) {
16
14
  );
17
15
  }
18
16
 
19
- // Resolve relative endpoints by prepending BASE_URL
20
17
  const resolveEndpoint = (url) => {
21
18
  return url.startsWith("/") ? `${BASE_URL}${url}` : url;
22
19
  };
23
20
 
24
- // Convert to inline JS object (not stringified) so K6 can call JSON.stringify() itself
25
21
  const stringifiedHeaders = JSON.stringify(headers, null, 2);
26
22
  const stringifiedBody = JSON.stringify(body, null, 2);
27
23
 
28
24
  return `
29
25
  import http from 'k6/http';
30
26
  import { check } from 'k6';
27
+ import { htmlReport } from "https://raw.githubusercontent.com/benc-uk/k6-reporter/main/dist/bundle.js";
28
+ import { textSummary } from "https://jslib.k6.io/k6-summary/0.0.1/index.js";
31
29
 
32
30
  export const options = ${JSON.stringify(options, null, 2)};
33
31
 
@@ -40,32 +38,42 @@ export default function () {
40
38
  ? endpoints
41
39
  .map(
42
40
  (url, i) => `
43
- const resolvedUrl${i} = "${resolveEndpoint(url)}";
44
- const res${i} = http.request("${method}", resolvedUrl${i}, ${
41
+ const resolvedUrl${i} = "${resolveEndpoint(url)}";
42
+ const res${i} = http.request("${method}", resolvedUrl${i}, ${
45
43
  method === "GET" || method === "DELETE"
46
44
  ? "null"
47
45
  : "JSON.stringify(body)"
48
46
  }, { headers });
49
- console.log(\`Response Body for \${resolvedUrl${i}}: \${res${i}.body}\`);
50
- check(res${i}, {
51
- "status is 2xx": (r) => r.status >= 200 && r.status < 300
52
- });
53
- `
47
+ console.log(\`Response Body for \${resolvedUrl${i}}: \${res${i}.body}\`);
48
+ check(res${i}, {
49
+ "status is 2xx": (r) => r.status >= 200 && r.status < 300
50
+ });
51
+ `
54
52
  )
55
53
  .join("\n")
56
54
  : `
57
- const resolvedUrl = "${resolveEndpoint(endpoint)}";
58
- const res = http.request("${method}", resolvedUrl, ${
55
+ const resolvedUrl = "${resolveEndpoint(endpoint)}";
56
+ const res = http.request("${method}", resolvedUrl, ${
59
57
  method === "GET" || method === "DELETE"
60
58
  ? "null"
61
59
  : "JSON.stringify(body)"
62
60
  }, { headers });
63
- console.log(\`Response Body for \${resolvedUrl}: \${res.body}\`);
64
- check(res, {
65
- "status is 2xx": (r) => r.status >= 200 && r.status < 300
66
- });
61
+ console.log(\`Response Body for \${resolvedUrl}: \${res.body}\`);
62
+ check(res, {
63
+ "status is 2xx": (r) => r.status >= 200 && r.status < 300
64
+ });
67
65
  `
68
66
  }
69
67
  }
70
- `;
68
+
69
+ export function handleSummary(data) {
70
+ const outputDir = __ENV.REPORT_OUTPUT_DIR || "reports";
71
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
72
+ const filename = \`\${outputDir}/k6-report-\${timestamp}.html\`;
73
+ return {
74
+ [filename]: htmlReport(data),
75
+ stdout: textSummary(data, { indent: " ", enableColors: true }),
76
+ };
77
+ }
78
+ `;
71
79
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k6-cucumber-steps",
3
- "version": "1.0.41",
3
+ "version": "1.1.1",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,53 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const reporter = require("cucumber-html-reporter");
4
+
5
+ function getJsonReportPath() {
6
+ // 1. Check for cucumber.js or custom config
7
+ const configFile = path.resolve("cucumber.js");
8
+ if (fs.existsSync(configFile)) {
9
+ const configText = fs.readFileSync(configFile, "utf-8");
10
+
11
+ const match = configText.match(/json:(.*?\.json)/);
12
+ if (match && match[1]) {
13
+ const reportPath = match[1].trim().replace(/['"`]/g, "");
14
+ console.log(`๐Ÿ“ Found report path in cucumber.js: ${reportPath}`);
15
+ return reportPath;
16
+ }
17
+ }
18
+
19
+ // 2. Check environment variable
20
+ if (process.env.CUCUMBER_JSON) {
21
+ console.log(
22
+ `๐Ÿ“ Using report path from CUCUMBER_JSON: ${process.env.CUCUMBER_JSON}`
23
+ );
24
+ return process.env.CUCUMBER_JSON;
25
+ }
26
+
27
+ // 3. Fallback to default
28
+ console.log("๐Ÿ“ Using default report path: reports/load-report.json");
29
+ return "reports/load-report.json";
30
+ }
31
+
32
+ function generateHtmlReports() {
33
+ const jsonReportPath = getJsonReportPath();
34
+
35
+ if (!fs.existsSync(jsonReportPath)) {
36
+ console.warn(`โš ๏ธ Cucumber JSON report not found at: ${jsonReportPath}`);
37
+ return;
38
+ }
39
+
40
+ const reportDir = path.dirname(jsonReportPath);
41
+
42
+ reporter.generate({
43
+ theme: "bootstrap",
44
+ jsonFile: jsonReportPath,
45
+ output: path.join(reportDir, "cucumber-report.html"),
46
+ reportSuiteAsScenarios: true,
47
+ launchReport: false,
48
+ name: "k6-cucumber-steps Performance Report",
49
+ brandTitle: "๐Ÿ“Š Performance Test Summary",
50
+ });
51
+ }
52
+
53
+ module.exports = { generateHtmlReports };
@@ -0,0 +1,60 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ const reportsDir = path.resolve("reports");
5
+
6
+ /**
7
+ * Adds internal cross-links between reports.
8
+ */
9
+ function addLinksToReport(targetFile, otherFiles) {
10
+ const content = fs.readFileSync(targetFile, "utf-8");
11
+
12
+ // Inject the Cucumber Report tab before the Request Metrics tab
13
+ const cucumberTab = `
14
+ <input type="radio" name="tabs" id="tabcucumber">
15
+ <label for="tabcucumber"><i class="fas fa-file-alt"></i> &nbsp; Cucumber Report</label>
16
+ <div class="tab">
17
+ <iframe src="cucumber-report.html" style="width:100%; height:600px; border:none;"></iframe>
18
+ </div>
19
+ `;
20
+
21
+ const modifiedContent = content
22
+ .replace(
23
+ /<input type="radio" name="tabs" id="tabone"/,
24
+ `${cucumberTab}\n<input type="radio" name="tabs" id="tabone"`
25
+ )
26
+ // Remove standalone links to cucumber-report.html or k6-report.html
27
+ .replace(
28
+ /<div style="padding:10px;margin-top:20px;text-align:center">[\s\S]*?View (Cucumber|k6).*?<\/div>/,
29
+ ""
30
+ );
31
+
32
+ fs.writeFileSync(targetFile, modifiedContent, "utf-8");
33
+ }
34
+
35
+ /**
36
+ * Auto-link all HTML reports in the reports directory.
37
+ */
38
+ function linkReports() {
39
+ if (!fs.existsSync(reportsDir)) {
40
+ console.warn("โš ๏ธ No reports directory found.");
41
+ return;
42
+ }
43
+
44
+ const htmlFiles = fs
45
+ .readdirSync(reportsDir)
46
+ .filter((f) => f.endsWith(".html"))
47
+ .map((f) => path.join(reportsDir, f));
48
+
49
+ if (htmlFiles.length < 2) {
50
+ console.warn("โš ๏ธ Not enough HTML files to link.");
51
+ return;
52
+ }
53
+
54
+ for (const file of htmlFiles) {
55
+ const others = htmlFiles.filter((f) => f !== file);
56
+ addLinksToReport(file, others);
57
+ }
58
+ }
59
+
60
+ module.exports = { linkReports };
package/.env.example DELETED
@@ -1,17 +0,0 @@
1
- # .env
2
- TEST_ENVIRONMENT=STAGING
3
- APP_VERSION=1.0.0
4
- BROWSER=Chrome 100.0.4896.88
5
- PLATFORM=Windows 10
6
- PARALLEL=Scenarios
7
- EXECUTED=Remote
8
-
9
- # Base URLs
10
- API_BASE_URL=https://test-api.example.com
11
- BASE_URL=https://example.com
12
- AUTH_URL=https://auth.example.com
13
- PAYMENT_URL=https://payment.example.com
14
-
15
- # Secret Parameters
16
- API_KEY=your-secret-api-key-12345
17
- BEARER_TOKEN=your_bearer_token_here
package/generateReport.js DELETED
@@ -1,24 +0,0 @@
1
- const reporter = require("cucumber-html-reporter");
2
-
3
- // Configuration for the HTML report
4
- const options = {
5
- theme: "bootstrap", // You can change the theme to 'simple', 'compact', etc.
6
- jsonFile: "reports/load-results.json", // Path to the JSON file generated by Cucumber
7
- output: "reports/report.html", // Path where you want to save the HTML report
8
- reportSuiteAsScenarios: true, // Group scenarios by their name
9
- launchReport: true, // Automatically open the report in the browser
10
- metadata: {
11
- browser: {
12
- name: "Chrome" || "unknown",
13
- version: "89" || "unknown",
14
- },
15
- device: "Local test machine",
16
- platform: {
17
- name: "MacOS",
18
- version: "20.04",
19
- },
20
- },
21
- };
22
-
23
- // Generate the report
24
- reporter.generate(options);