k6-cucumber-steps 1.0.34 → 1.0.36
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 +4 -0
- package/lib/helpers/generateHeaders.js +15 -9
- package/package.json +8 -6
- package/step_definitions/load_test_steps.js +107 -0
package/README.md
CHANGED
|
@@ -217,16 +217,20 @@ When I set the authentication type to "api_key"
|
|
|
217
217
|
When I set the authentication type to "bearer_token"
|
|
218
218
|
When I set the authentication type to "basic"
|
|
219
219
|
When I set the authentication type to "none"
|
|
220
|
+
When I set the authentication type to "custom-alias"
|
|
220
221
|
```
|
|
221
222
|
|
|
222
223
|
### Request Configuration Steps
|
|
223
224
|
|
|
224
225
|
```gherkin
|
|
225
226
|
Given I set a k6 script for {word} testing
|
|
227
|
+
Given I login via POST to {string} with payload from {string}
|
|
226
228
|
When I set to run the k6 script with the following configurations:
|
|
227
229
|
When I set the request headers:
|
|
228
230
|
When I set the following endpoints used:
|
|
229
231
|
When I set the following {word} body is used for {string}
|
|
232
|
+
When I store the value at {string} as alias {string}
|
|
233
|
+
|
|
230
234
|
```
|
|
231
235
|
|
|
232
236
|
### Assertion Steps
|
|
@@ -6,23 +6,29 @@
|
|
|
6
6
|
* Generates HTTP headers based on the specified authentication type.
|
|
7
7
|
* Supported auth types: api_key, bearer_token, basic, none.
|
|
8
8
|
*/
|
|
9
|
-
module.exports = function generateHeaders(authType, env) {
|
|
9
|
+
module.exports = function generateHeaders(authType, env, aliases = {}) {
|
|
10
10
|
const headers = { "Content-Type": "application/json" };
|
|
11
11
|
|
|
12
|
+
const getValue = (key) => env[key] || aliases[key] || "";
|
|
13
|
+
|
|
12
14
|
if (authType === "api_key") {
|
|
13
|
-
headers["x-api-key"] =
|
|
15
|
+
headers["x-api-key"] = getValue("API_KEY");
|
|
14
16
|
} else if (authType === "bearer_token") {
|
|
15
|
-
headers["Authorization"] = `Bearer ${
|
|
17
|
+
headers["Authorization"] = `Bearer ${getValue("token")}`;
|
|
16
18
|
} else if (authType === "basic") {
|
|
17
|
-
const base64 = Buffer.from(
|
|
18
|
-
"
|
|
19
|
-
);
|
|
19
|
+
const base64 = Buffer.from(
|
|
20
|
+
`${getValue("BASIC_USER")}:${getValue("BASIC_PASS")}`
|
|
21
|
+
).toString("base64");
|
|
20
22
|
headers["Authorization"] = `Basic ${base64}`;
|
|
21
23
|
} else if (authType === "none") {
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
+
// Do nothing extra
|
|
25
|
+
} else if (aliases[authType]) {
|
|
26
|
+
// Dynamic alias token support
|
|
27
|
+
headers["Authorization"] = `Bearer ${getValue(authType)}`;
|
|
24
28
|
} else {
|
|
25
|
-
throw new Error(
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Unsupported authentication type or missing alias: ${authType}`
|
|
31
|
+
);
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
return headers;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "k6-cucumber-steps",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.36",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -53,18 +53,20 @@
|
|
|
53
53
|
"@babel/cli": "latest",
|
|
54
54
|
"@babel/core": "latest",
|
|
55
55
|
"@babel/preset-env": "latest",
|
|
56
|
-
"@babel/register": "latest",
|
|
57
|
-
"@cucumber/cucumber": "latest",
|
|
58
|
-
"@faker-js/faker": "latest",
|
|
59
56
|
"@types/k6": "latest",
|
|
60
57
|
"child_process": "latest",
|
|
61
58
|
"cucumber-console-formatter": "latest",
|
|
62
59
|
"cucumber-html-reporter": "latest",
|
|
63
|
-
"dotenv": "latest",
|
|
64
60
|
"esbuild": "latest",
|
|
65
61
|
"form-data": "latest",
|
|
66
62
|
"k6": "latest",
|
|
67
|
-
"tsconfig-paths": "latest"
|
|
63
|
+
"tsconfig-paths": "latest"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@babel/register": "latest",
|
|
67
|
+
"@cucumber/cucumber": "latest",
|
|
68
|
+
"@faker-js/faker": "latest",
|
|
69
|
+
"dotenv": "latest",
|
|
68
70
|
"yargs": "latest"
|
|
69
71
|
}
|
|
70
72
|
}
|
|
@@ -9,6 +9,7 @@ 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");
|
|
12
13
|
|
|
13
14
|
// Validate thresholds (e.g., "rate<0.01")
|
|
14
15
|
const validateThreshold = (threshold) => {
|
|
@@ -141,6 +142,49 @@ When(
|
|
|
141
142
|
}
|
|
142
143
|
);
|
|
143
144
|
|
|
145
|
+
When(
|
|
146
|
+
"I use JSON payload from {string} for {word} to {string}",
|
|
147
|
+
function (fileName, method, endpoint) {
|
|
148
|
+
const allowedMethods = ["POST", "PUT", "PATCH"];
|
|
149
|
+
const methodUpper = method.toUpperCase();
|
|
150
|
+
|
|
151
|
+
if (!allowedMethods.includes(methodUpper)) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Method "${method}" is not supported. Use one of: ${allowedMethods.join(
|
|
154
|
+
", "
|
|
155
|
+
)}`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const payloadPath = path.resolve(__dirname, "../../payloads", fileName);
|
|
160
|
+
if (!fs.existsSync(payloadPath)) {
|
|
161
|
+
throw new Error(`Payload file not found: ${fileName}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const rawTemplate = fs.readFileSync(payloadPath, "utf-8");
|
|
165
|
+
const resolved = resolveBody(rawTemplate, {
|
|
166
|
+
...process.env,
|
|
167
|
+
...(this.aliases || {}),
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
this.config = {
|
|
171
|
+
method: methodUpper,
|
|
172
|
+
endpoint,
|
|
173
|
+
body: resolved,
|
|
174
|
+
headers: this.config?.headers || {},
|
|
175
|
+
options: {
|
|
176
|
+
vus: 1,
|
|
177
|
+
iterations: 1,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
this.lastRequest = {
|
|
182
|
+
method: methodUpper,
|
|
183
|
+
endpoint,
|
|
184
|
+
body: resolved,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
);
|
|
144
188
|
/**
|
|
145
189
|
* @param {string} authType - Authentication type (api_key, bearer_token, basic, none).
|
|
146
190
|
* @example
|
|
@@ -152,6 +196,69 @@ When(
|
|
|
152
196
|
When("I set the authentication type to {string}", function (authType) {
|
|
153
197
|
this.config.headers = generateHeaders(authType, process.env);
|
|
154
198
|
});
|
|
199
|
+
/**
|
|
200
|
+
* Then I store the value at "data.token" as alias "token"
|
|
201
|
+
*/
|
|
202
|
+
Then(
|
|
203
|
+
"I store the value at {string} as alias {string}",
|
|
204
|
+
function (jsonPath, alias) {
|
|
205
|
+
if (!this.lastResponse) {
|
|
206
|
+
throw new Error("No previous response available.");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const pathParts = jsonPath.split(".");
|
|
210
|
+
let value = this.lastResponse;
|
|
211
|
+
|
|
212
|
+
for (const key of pathParts) {
|
|
213
|
+
value = value?.[key];
|
|
214
|
+
if (value === undefined) break;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (value === undefined) {
|
|
218
|
+
throw new Error(`Could not resolve path "${jsonPath}" in the response`);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!this.aliases) this.aliases = {};
|
|
222
|
+
this.aliases[alias] = value;
|
|
223
|
+
|
|
224
|
+
console.log(`🧩 Stored alias "${alias}":`, value);
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
When(
|
|
228
|
+
"I login via POST to {string} with payload from {string}",
|
|
229
|
+
async function (endpoint, fileName) {
|
|
230
|
+
const payloadPath = path.resolve(__dirname, "../../payloads", fileName);
|
|
231
|
+
|
|
232
|
+
if (!fs.existsSync(payloadPath)) {
|
|
233
|
+
throw new Error(`Payload file not found: ${fileName}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const rawTemplate = fs.readFileSync(payloadPath, "utf-8");
|
|
237
|
+
|
|
238
|
+
const resolved = resolveBody(rawTemplate, {
|
|
239
|
+
...process.env,
|
|
240
|
+
...(this.aliases || {}),
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const response = await axios.post(
|
|
245
|
+
`${process.env.BASE_URL}${endpoint}`,
|
|
246
|
+
resolved,
|
|
247
|
+
{
|
|
248
|
+
headers: {
|
|
249
|
+
"Content-Type": "application/json",
|
|
250
|
+
},
|
|
251
|
+
}
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
this.lastResponse = response.data; // ✅ Makes aliasing work
|
|
255
|
+
console.log("🔐 Login successful, response saved to alias context.");
|
|
256
|
+
} catch (err) {
|
|
257
|
+
console.error("❌ Login request failed:", err.message);
|
|
258
|
+
throw new Error("Login request failed");
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
);
|
|
155
262
|
|
|
156
263
|
/**
|
|
157
264
|
* @param {string} method - HTTP method of the request.
|