k6-cucumber-steps 1.1.3 → 1.1.4
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/.vscode/settings.json +2 -1
- package/bin/k6-cucumber-steps.js +45 -30
- package/package.json +15 -19
- package/scripts/linkReports.js +31 -27
package/.vscode/settings.json
CHANGED
package/bin/k6-cucumber-steps.js
CHANGED
|
@@ -3,11 +3,9 @@
|
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const fs = require("fs");
|
|
5
5
|
const { spawn } = require("child_process");
|
|
6
|
-
const yargs = require("yargs/yargs");
|
|
7
|
-
const { hideBin } = require("yargs/helpers");
|
|
6
|
+
const yargs = require("yargs/yargs");
|
|
7
|
+
const { hideBin } = require("yargs/helpers");
|
|
8
8
|
require("dotenv").config();
|
|
9
|
-
const { generateHtmlReports } = require("../scripts/generateHtmlReports");
|
|
10
|
-
const { linkReports } = require("../scripts/linkReports");
|
|
11
9
|
|
|
12
10
|
console.log(`
|
|
13
11
|
-----------------------------------------
|
|
@@ -15,6 +13,7 @@ console.log(`
|
|
|
15
13
|
-----------------------------------------
|
|
16
14
|
`);
|
|
17
15
|
|
|
16
|
+
// Parse CLI arguments
|
|
18
17
|
const argv = yargs(hideBin(process.argv))
|
|
19
18
|
.usage("Usage: $0 run [options]")
|
|
20
19
|
.option("feature", {
|
|
@@ -24,7 +23,7 @@ const argv = yargs(hideBin(process.argv))
|
|
|
24
23
|
})
|
|
25
24
|
.option("tags", {
|
|
26
25
|
alias: "t",
|
|
27
|
-
describe: "Cucumber tags to filter scenarios",
|
|
26
|
+
describe: "Cucumber tags to filter scenarios (e.g., @smoke)",
|
|
28
27
|
type: "string",
|
|
29
28
|
})
|
|
30
29
|
.option("reporter", {
|
|
@@ -46,8 +45,10 @@ const argv = yargs(hideBin(process.argv))
|
|
|
46
45
|
})
|
|
47
46
|
.help().argv;
|
|
48
47
|
|
|
48
|
+
// Base Cucumber arguments
|
|
49
49
|
const cucumberArgs = ["cucumber-js"];
|
|
50
50
|
|
|
51
|
+
// Load custom configuration file if provided
|
|
51
52
|
const configFileName =
|
|
52
53
|
argv.configFile || process.env.CUCUMBER_CONFIG_FILE || "cucumber.js";
|
|
53
54
|
const configFilePath = path.resolve(process.cwd(), configFileName);
|
|
@@ -58,8 +59,8 @@ if (fs.existsSync(configFilePath)) {
|
|
|
58
59
|
try {
|
|
59
60
|
const loadedConfig = require(configFilePath);
|
|
60
61
|
configOptions = loadedConfig.default || loadedConfig;
|
|
61
|
-
} catch {
|
|
62
|
-
console.warn("⚠️
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.warn("⚠️ Could not load config file:", err.message);
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
@@ -69,18 +70,18 @@ if (tags) {
|
|
|
69
70
|
cucumberArgs.push("--tags", tags);
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
// Feature
|
|
73
|
+
// Feature file(s)
|
|
73
74
|
let featureFiles = [];
|
|
74
75
|
if (argv.feature) {
|
|
75
76
|
featureFiles.push(path.resolve(argv.feature));
|
|
76
77
|
} else if (configOptions.paths && configOptions.paths.length > 0) {
|
|
77
|
-
featureFiles.push(...configOptions.paths);
|
|
78
|
+
featureFiles.push(...configOptions.paths.map((p) => path.resolve(p)));
|
|
78
79
|
}
|
|
79
80
|
if (featureFiles.length > 0) {
|
|
80
81
|
cucumberArgs.push(...featureFiles);
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
// Require
|
|
84
|
+
// Require step definitions
|
|
84
85
|
const defaultStepsPath = path.resolve(
|
|
85
86
|
process.cwd(),
|
|
86
87
|
"node_modules",
|
|
@@ -89,15 +90,17 @@ const defaultStepsPath = path.resolve(
|
|
|
89
90
|
);
|
|
90
91
|
cucumberArgs.push("--require", defaultStepsPath);
|
|
91
92
|
|
|
92
|
-
//
|
|
93
|
+
// Include additional custom step definitions from config
|
|
93
94
|
if (configOptions.require && Array.isArray(configOptions.require)) {
|
|
94
95
|
for (const reqPath of configOptions.require) {
|
|
95
|
-
cucumberArgs.push("--require", reqPath);
|
|
96
|
+
cucumberArgs.push("--require", path.resolve(reqPath));
|
|
96
97
|
}
|
|
97
98
|
}
|
|
98
99
|
|
|
99
|
-
//
|
|
100
|
+
// Reports directory setup
|
|
100
101
|
const reportsDir = path.join(process.cwd(), "reports");
|
|
102
|
+
|
|
103
|
+
// Clean and prepare reports directory
|
|
101
104
|
const cleanReportsDir = () => {
|
|
102
105
|
if (fs.existsSync(reportsDir)) {
|
|
103
106
|
try {
|
|
@@ -120,6 +123,7 @@ const cleanReportsDir = () => {
|
|
|
120
123
|
|
|
121
124
|
cleanReportsDir();
|
|
122
125
|
|
|
126
|
+
// Determine base report name
|
|
123
127
|
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
124
128
|
|
|
125
129
|
let baseReportName = "load-report";
|
|
@@ -136,10 +140,15 @@ const shouldOverwrite =
|
|
|
136
140
|
process.env.K6_CUCUMBER_OVERWRITE === "true" ||
|
|
137
141
|
configOptions.overwrite === true;
|
|
138
142
|
|
|
139
|
-
let reportJsonPath =
|
|
143
|
+
let reportJsonPath = path.join(reportsDir, `${baseReportName}.json`);
|
|
140
144
|
let reportHtmlPath = path.join(reportsDir, `${baseReportName}.html`);
|
|
141
145
|
|
|
142
|
-
|
|
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
|
|
143
152
|
if (Array.isArray(configOptions.format)) {
|
|
144
153
|
const jsonFmt = configOptions.format.find((f) => f.startsWith("json:"));
|
|
145
154
|
if (jsonFmt) {
|
|
@@ -152,8 +161,7 @@ const formatInConfig =
|
|
|
152
161
|
Array.isArray(configOptions.format) && configOptions.format.length > 0;
|
|
153
162
|
|
|
154
163
|
if (shouldGenerateReports && !formatInConfig) {
|
|
155
|
-
|
|
156
|
-
cucumberArgs.push("--format", `summary`);
|
|
164
|
+
cucumberArgs.push("--format", "summary");
|
|
157
165
|
cucumberArgs.push("--format", `json:${reportJsonPath}`);
|
|
158
166
|
cucumberArgs.push("--format", `html:${reportHtmlPath}`);
|
|
159
167
|
}
|
|
@@ -161,6 +169,7 @@ if (shouldGenerateReports && !formatInConfig) {
|
|
|
161
169
|
console.log("\n▶️ Final arguments passed to cucumber-js:");
|
|
162
170
|
console.log(["npx", ...cucumberArgs].join(" ") + "\n");
|
|
163
171
|
|
|
172
|
+
// Execute Cucumber process
|
|
164
173
|
const cucumberProcess = spawn("npx", cucumberArgs, {
|
|
165
174
|
stdio: "inherit",
|
|
166
175
|
env: {
|
|
@@ -174,9 +183,6 @@ const cucumberProcess = spawn("npx", cucumberArgs, {
|
|
|
174
183
|
});
|
|
175
184
|
|
|
176
185
|
function detectMostRecentK6Report() {
|
|
177
|
-
const reportsDir = path.join(process.cwd(), "reports");
|
|
178
|
-
if (!fs.existsSync(reportsDir)) return null;
|
|
179
|
-
|
|
180
186
|
const files = fs
|
|
181
187
|
.readdirSync(reportsDir)
|
|
182
188
|
.filter((file) => /^k6-report.*\.html$/.test(file))
|
|
@@ -186,7 +192,7 @@ function detectMostRecentK6Report() {
|
|
|
186
192
|
}))
|
|
187
193
|
.sort((a, b) => b.time - a.time);
|
|
188
194
|
|
|
189
|
-
return files.length > 0 ? path.join(
|
|
195
|
+
return files.length > 0 ? path.join(reportsDir, files[0].name) : null;
|
|
190
196
|
}
|
|
191
197
|
|
|
192
198
|
cucumberProcess.on("close", async (code) => {
|
|
@@ -194,17 +200,26 @@ cucumberProcess.on("close", async (code) => {
|
|
|
194
200
|
console.log("-----------------------------------------");
|
|
195
201
|
console.log("✅ k6-cucumber-steps execution completed successfully.");
|
|
196
202
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
+
}
|
|
202
212
|
|
|
203
|
-
|
|
213
|
+
// Link reports
|
|
214
|
+
try {
|
|
215
|
+
await linkReports();
|
|
216
|
+
console.log(
|
|
217
|
+
"🔗 Combined and minified HTML report available at: reports/combined-report.html"
|
|
218
|
+
);
|
|
219
|
+
} catch (err) {
|
|
220
|
+
console.error("⚠️ Failed to link reports:", err.message);
|
|
221
|
+
}
|
|
204
222
|
|
|
205
|
-
console.log(
|
|
206
|
-
"📦 Combined and minified HTML report available at: reports/combined-report.html"
|
|
207
|
-
);
|
|
208
223
|
console.log("-----------------------------------------");
|
|
209
224
|
} else {
|
|
210
225
|
console.error("-----------------------------------------");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "k6-cucumber-steps",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -49,26 +49,22 @@
|
|
|
49
49
|
},
|
|
50
50
|
"author": "qaPaschalE",
|
|
51
51
|
"description": "Cucumber step definitions for running k6 performance tests.",
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"@cucumber/cucumber": "*",
|
|
54
|
+
"k6": "*"
|
|
55
|
+
},
|
|
52
56
|
"devDependencies": {
|
|
53
|
-
"@babel/cli": "
|
|
54
|
-
"@babel/core": "
|
|
55
|
-
"@babel/preset-env": "
|
|
56
|
-
"@
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"k6": "latest",
|
|
63
|
-
"tsconfig-paths": "latest"
|
|
57
|
+
"@babel/cli": "^7.27.2",
|
|
58
|
+
"@babel/core": "^7.27.4",
|
|
59
|
+
"@babel/preset-env": "^7.27.2",
|
|
60
|
+
"@faker-js/faker": "^9.8.0",
|
|
61
|
+
"@types/k6": "^1.0.2",
|
|
62
|
+
"axios": "^1.10.0",
|
|
63
|
+
"dotenv": "^16.5.0",
|
|
64
|
+
"html-minifier-terser": "^7.2.0",
|
|
65
|
+
"yargs": "^18.0.0"
|
|
64
66
|
},
|
|
65
67
|
"dependencies": {
|
|
66
|
-
"@babel/register": "
|
|
67
|
-
"@cucumber/cucumber": "latest",
|
|
68
|
-
"@faker-js/faker": "latest",
|
|
69
|
-
"axios": "^1.9.0",
|
|
70
|
-
"dotenv": "latest",
|
|
71
|
-
"html-minifier-terser": "^7.2.0",
|
|
72
|
-
"yargs": "latest"
|
|
68
|
+
"@babel/register": "^7.27.1"
|
|
73
69
|
}
|
|
74
70
|
}
|
package/scripts/linkReports.js
CHANGED
|
@@ -4,18 +4,29 @@ const path = require("path");
|
|
|
4
4
|
const reportsDir = path.resolve("reports");
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* Finds the first file that looks like a Cucumber HTML report.
|
|
8
8
|
*/
|
|
9
|
-
function
|
|
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) {
|
|
10
18
|
const content = fs.readFileSync(targetFile, "utf-8");
|
|
11
19
|
|
|
12
|
-
// Inject the Cucumber Report tab before the Request Metrics tab
|
|
13
20
|
const cucumberTab = `
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
<input type="radio" name="tabs" id="tabcucumber">
|
|
22
|
+
<label for="tabcucumber"><i class="fas fa-file-alt"></i> 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>
|
|
19
30
|
`;
|
|
20
31
|
|
|
21
32
|
const modifiedContent = content
|
|
@@ -23,22 +34,13 @@ function addLinksToReport(targetFile, otherFiles) {
|
|
|
23
34
|
/<input type="radio" name="tabs" id="tabone"/,
|
|
24
35
|
`${cucumberTab}\n<input type="radio" name="tabs" id="tabone"`
|
|
25
36
|
)
|
|
26
|
-
|
|
27
|
-
.replace(
|
|
28
|
-
/<div style="padding:10px;margin-top:20px;text-align:center">[\s\S]*?View (Cucumber|k6).*?<\/div>/,
|
|
29
|
-
""
|
|
30
|
-
);
|
|
37
|
+
.replace(/<div style="[^>]*margin-top:20px;[^>]*">[\s\S]*?<\/div>/g, "");
|
|
31
38
|
|
|
32
39
|
fs.writeFileSync(targetFile, modifiedContent, "utf-8");
|
|
33
|
-
console.log(
|
|
34
|
-
`🔗 Updated ${path.basename(
|
|
35
|
-
targetFile
|
|
36
|
-
)} with Cucumber tab and removed standalone links.`
|
|
37
|
-
);
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
43
|
+
* Adds a Cucumber tab to every K6 HTML report found in /reports.
|
|
42
44
|
*/
|
|
43
45
|
function linkReports() {
|
|
44
46
|
if (!fs.existsSync(reportsDir)) {
|
|
@@ -46,20 +48,22 @@ function linkReports() {
|
|
|
46
48
|
return;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
const cucumberFile = findCucumberReportFile();
|
|
52
|
+
|
|
49
53
|
const htmlFiles = fs
|
|
50
54
|
.readdirSync(reportsDir)
|
|
51
|
-
.filter((f) => f
|
|
52
|
-
.map((f) => path.join(reportsDir, f));
|
|
55
|
+
.filter((f) => /^k6-report.*\.html$/.test(f));
|
|
53
56
|
|
|
54
|
-
if (htmlFiles.length
|
|
55
|
-
console.warn("⚠️
|
|
57
|
+
if (htmlFiles.length === 0) {
|
|
58
|
+
console.warn("⚠️ No K6 reports found to inject.");
|
|
56
59
|
return;
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
const
|
|
61
|
-
addLinksToReport(
|
|
62
|
-
|
|
62
|
+
htmlFiles.forEach((file) => {
|
|
63
|
+
const fullPath = path.join(reportsDir, file);
|
|
64
|
+
addLinksToReport(fullPath, cucumberFile);
|
|
65
|
+
console.log(`🔗 Injected Cucumber tab into: ${file}`);
|
|
66
|
+
});
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
module.exports = { linkReports };
|