k6-cucumber-steps 1.0.35 → 1.0.37

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
@@ -150,6 +150,7 @@ npx k6-cucumber-steps run --configFile cucumber.prod.js
150
150
 
151
151
  ```env
152
152
  BASE_URL=[https://api.example.com](https://api.example.com)
153
+ API_BASE_URL=[https://api.example.com](https://api.example.com)
153
154
  API_KEY=your_api_key
154
155
  BEARER_TOKEN=your_bearer_token
155
156
  BASIC_USER=your_basic_user
@@ -217,16 +218,20 @@ When I set the authentication type to "api_key"
217
218
  When I set the authentication type to "bearer_token"
218
219
  When I set the authentication type to "basic"
219
220
  When I set the authentication type to "none"
221
+ When I set the authentication type to "custom-alias"
220
222
  ```
221
223
 
222
224
  ### Request Configuration Steps
223
225
 
224
226
  ```gherkin
225
227
  Given I set a k6 script for {word} testing
228
+ Given I login via POST to {string} with payload from {string}
226
229
  When I set to run the k6 script with the following configurations:
227
230
  When I set the request headers:
228
231
  When I set the following endpoints used:
229
232
  When I set the following {word} body is used for {string}
233
+ When I store the value at {string} as alias {string}
234
+
230
235
  ```
231
236
 
232
237
  ### Assertion Steps
@@ -1,5 +1,6 @@
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
4
5
  if (!endpoints?.length && !endpoint) {
5
6
  throw new Error(
@@ -7,10 +8,12 @@ module.exports = function buildK6Script(config) {
7
8
  );
8
9
  }
9
10
 
10
- // Get BASE_URL from environment variables
11
- const BASE_URL = process.env.BASE_URL;
11
+ // Prefer API_BASE_URL, fallback to BASE_URL
12
+ const BASE_URL = process.env.API_BASE_URL || process.env.BASE_URL;
12
13
  if (!BASE_URL) {
13
- throw new Error("BASE_URL is not defined in the environment variables.");
14
+ throw new Error(
15
+ "Neither API_BASE_URL nor BASE_URL is defined in the environment variables."
16
+ );
14
17
  }
15
18
 
16
19
  // Resolve relative endpoints by prepending BASE_URL
@@ -47,7 +50,7 @@ export default function () {
47
50
  .join("\n")
48
51
  : `
49
52
  const resolvedUrl = "${resolveEndpoint(endpoint)}";
50
- \ const res = http.request("${method}", resolvedUrl, ${
53
+ const res = http.request("${method}", resolvedUrl, ${
51
54
  method === "GET" || method === "DELETE"
52
55
  ? "null"
53
56
  : JSON.stringify(body)
@@ -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"] = env.API_KEY || "";
15
+ headers["x-api-key"] = getValue("API_KEY");
14
16
  } else if (authType === "bearer_token") {
15
- headers["Authorization"] = `Bearer ${env.BEARER_TOKEN || ""}`;
17
+ headers["Authorization"] = `Bearer ${getValue("token")}`;
16
18
  } else if (authType === "basic") {
17
- const base64 = Buffer.from(`${env.BASIC_USER}:${env.BASIC_PASS}`).toString(
18
- "base64"
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
- // No additional headers for "no auth"
23
- // Default headers (e.g., Content-Type) are still included
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(`Unsupported authentication type: ${authType}`);
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.35",
3
+ "version": "1.0.37",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -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.