@dev-blinq/cucumber_client 1.0.1438-dev → 1.0.1438-stage

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.
Files changed (50) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +73 -73
  2. package/bin/assets/preload/css_gen.js +10 -10
  3. package/bin/assets/preload/toolbar.js +27 -29
  4. package/bin/assets/preload/unique_locators.js +1 -1
  5. package/bin/assets/preload/yaml.js +288 -275
  6. package/bin/assets/scripts/aria_snapshot.js +223 -220
  7. package/bin/assets/scripts/dom_attr.js +329 -329
  8. package/bin/assets/scripts/dom_parent.js +169 -174
  9. package/bin/assets/scripts/event_utils.js +94 -94
  10. package/bin/assets/scripts/pw.js +2050 -1949
  11. package/bin/assets/scripts/recorder.js +70 -45
  12. package/bin/assets/scripts/snapshot_capturer.js +147 -147
  13. package/bin/assets/scripts/unique_locators.js +170 -49
  14. package/bin/assets/scripts/yaml.js +796 -783
  15. package/bin/assets/templates/_hooks_template.txt +6 -2
  16. package/bin/assets/templates/utils_template.txt +16 -16
  17. package/bin/client/code_cleanup/find_step_definition_references.js +0 -1
  18. package/bin/client/code_cleanup/utils.js +16 -7
  19. package/bin/client/code_gen/api_codegen.js +2 -2
  20. package/bin/client/code_gen/code_inversion.js +63 -2
  21. package/bin/client/code_gen/duplication_analysis.js +2 -1
  22. package/bin/client/code_gen/function_signature.js +4 -0
  23. package/bin/client/code_gen/page_reflection.js +52 -11
  24. package/bin/client/code_gen/playwright_codeget.js +46 -28
  25. package/bin/client/cucumber/feature.js +4 -17
  26. package/bin/client/cucumber/feature_data.js +2 -2
  27. package/bin/client/cucumber/project_to_document.js +8 -2
  28. package/bin/client/cucumber/steps_definitions.js +19 -3
  29. package/bin/client/local_agent.js +3 -2
  30. package/bin/client/parse_feature_file.js +23 -26
  31. package/bin/client/playground/projects/env.json +2 -2
  32. package/bin/client/recorderv3/bvt_init.js +305 -0
  33. package/bin/client/recorderv3/bvt_recorder.js +1025 -57
  34. package/bin/client/recorderv3/implemented_steps.js +2 -0
  35. package/bin/client/recorderv3/index.js +3 -283
  36. package/bin/client/recorderv3/services.js +818 -142
  37. package/bin/client/recorderv3/step_runner.js +21 -7
  38. package/bin/client/recorderv3/step_utils.js +540 -72
  39. package/bin/client/recorderv3/update_feature.js +86 -39
  40. package/bin/client/recorderv3/wbr_entry.js +61 -0
  41. package/bin/client/recording.js +1 -0
  42. package/bin/client/upload-service.js +4 -2
  43. package/bin/client/utils/app_dir.js +21 -0
  44. package/bin/client/utils/socket_logger.js +87 -125
  45. package/bin/index.js +4 -1
  46. package/package.json +11 -5
  47. package/bin/client/recorderv3/app_dir.js +0 -23
  48. package/bin/client/recorderv3/network.js +0 -299
  49. package/bin/client/recorderv3/scriptTest.js +0 -5
  50. package/bin/client/recorderv3/ws_server.js +0 -72
@@ -1,8 +1,9 @@
1
- import { existsSync, readFileSync, writeFileSync } from "fs";
2
- import path from "path";
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
3
  import { getDefaultPrettierConfig } from "../code_cleanup/utils.js";
4
4
  import prettier from "prettier";
5
- export function containsScenario({ featureFileContent, scenarioName }) {
5
+
6
+ function containsScenario({ featureFileContent, scenarioName }) {
6
7
  const lines = featureFileContent.split("\n");
7
8
  for (const line of lines) {
8
9
  const trimmedLine = line.trim();
@@ -14,7 +15,7 @@ export function containsScenario({ featureFileContent, scenarioName }) {
14
15
  }
15
16
  }
16
17
 
17
- export function testStringForRegex(text) {
18
+ function testStringForRegex(text) {
18
19
  const regexEndPattern = /\/([gimuy]*)$/;
19
20
  if (text.startsWith("/")) {
20
21
  const match = regexEndPattern.test(text);
@@ -31,7 +32,7 @@ export function testStringForRegex(text) {
31
32
  return false;
32
33
  }
33
34
 
34
- const escapeNonPrintables = (text) => {
35
+ function escapeNonPrintables(text) {
35
36
  const t = text.replace(/\n/g, "\\n").replace(/\t/g, "\\t"); // .replace(/\|/g, "\\|");
36
37
  let result = "";
37
38
  // replace \ with \\ and | with \|
@@ -60,8 +61,9 @@ const escapeNonPrintables = (text) => {
60
61
  }
61
62
  }
62
63
  return result;
63
- };
64
- export function getCommandContent(command) {
64
+ }
65
+
66
+ function getCommandContent(command) {
65
67
  switch (command.type) {
66
68
  case "click_element": {
67
69
  return `${command.count === 2 ? "Double click" : "Click"} on ${escapeNonPrintables(command.element.name)}`;
@@ -108,7 +110,18 @@ export function getCommandContent(command) {
108
110
  }
109
111
  }
110
112
 
111
- export function getExamplesContent(parametersMap) {
113
+ function getExamplesContent(parametersMap, datasets) {
114
+ if (datasets && datasets.length > 0) {
115
+ let result = "";
116
+ const keys = Object.keys(parametersMap);
117
+ result += "\t\tExamples:\n";
118
+
119
+ result += `\t\t| ${keys.join(" | ")} |\n`;
120
+ for (const dataset of datasets) {
121
+ result += `\t\t| ${dataset.data.map((d) => escapeNonPrintables(d.value)).join(" | ")} |\n`;
122
+ }
123
+ return result;
124
+ }
112
125
  const keys = Object.keys(parametersMap);
113
126
  const l = keys.length;
114
127
  let result = "\t\tExamples:\n";
@@ -144,19 +157,19 @@ function getTagsContent(scenario, featureFileObject) {
144
157
  return tagsContent;
145
158
  }
146
159
 
147
- export function getScenarioContent({ scenario }, featureFileObject) {
160
+ function getScenarioContent({ scenario }, featureFileObject) {
148
161
  const prametersMap = scenario.parametersMap ?? {};
149
162
  const isParmatersMapEmpty = Object.keys(prametersMap).length === 0;
150
163
  let scenarioContent = isParmatersMapEmpty ? `Scenario: ${scenario.name}\n` : `Scenario Outline: ${scenario.name}\n`;
151
164
 
152
- let tagsContent = getTagsContent(scenario, featureFileObject);
165
+ const tagsContent = getTagsContent(scenario, featureFileObject);
153
166
 
154
- scenarioContent = "\t" + tagsContent + "\n" + scenarioContent;
167
+ scenarioContent = `\t${tagsContent}\n${scenarioContent}`;
155
168
 
156
169
  for (const step of scenario.steps) {
157
170
  const commands = step.commands ?? [];
158
- let commentContents = commands.map(getCommandContent).map(escapeNonPrintables);
159
- let commentContent = commentContents.filter((content) => content.length > 0).join(", ");
171
+ const commentContents = commands.map(getCommandContent).map(escapeNonPrintables);
172
+ const commentContent = commentContents.filter((content) => content.length > 0).join(", ");
160
173
 
161
174
  if (commentContent) {
162
175
  scenarioContent += `\t# ${commentContent}\n`;
@@ -164,18 +177,19 @@ export function getScenarioContent({ scenario }, featureFileObject) {
164
177
  scenarioContent += `\t${step.keyword} ${escapeString(step.text)}\n`;
165
178
  }
166
179
  if (!isParmatersMapEmpty) {
167
- scenarioContent += getExamplesContent(prametersMap);
180
+ scenarioContent += getExamplesContent(prametersMap, scenario.datasets);
168
181
  }
169
182
  return scenarioContent;
170
183
  }
171
- export const escapeString = (str) => {
184
+
185
+ function escapeString(str) {
172
186
  // Step 1: Replace all literal newline characters with a temporary placeholder
173
187
  const placeholder = "\\n";
174
188
  str = str.replace(/\n/g, placeholder);
175
189
  return str;
176
- };
190
+ }
177
191
 
178
- const GherkinToObject = (gherkin) => {
192
+ function GherkinToObject(gherkin) {
179
193
  const obj = {
180
194
  featureName: "",
181
195
  scenarios: [],
@@ -211,7 +225,7 @@ const GherkinToObject = (gherkin) => {
211
225
  }
212
226
 
213
227
  const getScenario = () => {
214
- let scenario = {
228
+ const scenario = {
215
229
  name: "",
216
230
  tags: [],
217
231
  steps: [],
@@ -235,7 +249,7 @@ const GherkinToObject = (gherkin) => {
235
249
  skipEmptyLines();
236
250
 
237
251
  if (idx >= lines.length) {
238
- return -1;
252
+ return scenario;
239
253
  }
240
254
 
241
255
  while (
@@ -288,29 +302,50 @@ const GherkinToObject = (gherkin) => {
288
302
  skipEmptyLines();
289
303
  }
290
304
  return obj;
291
- };
305
+ }
292
306
 
293
307
  // remove lines starting with "Scenario:" or "Scenario Outline:" that contain the scenario name until the next scenario and then append the new scenario content
294
308
  // assumes that there are no multiple scenarios with the same name and having comments and tags in each scenario
295
- function updateExistingScenario({ featureFileContent, scenarioName, scenarioContent }) {
309
+ function updateExistingScenario({
310
+ featureFileContent,
311
+ scenarioName: newScenarioName,
312
+ scenarioContent: newScenarioContent,
313
+ }) {
296
314
  const featureFileObject = GherkinToObject(featureFileContent);
297
315
  if (featureFileObject.error) return "error";
316
+
298
317
  const results = [];
299
- let skipScenarioIndex = -1;
300
318
  results.push(`Feature: ${featureFileObject.featureName}`);
319
+
320
+ let indexOfScenarioToUpdate = -1;
321
+
322
+ for (let i = 0; i < featureFileObject.scenarios.length; i++) {
323
+ if (featureFileObject.scenarios[i].name === newScenarioName) {
324
+ indexOfScenarioToUpdate = i;
325
+ break;
326
+ }
327
+ }
328
+
301
329
  for (let i = 0; i < featureFileObject.scenarios.length; i++) {
302
330
  const scenario = featureFileObject.scenarios[i];
303
- if (scenario.name === scenarioName) {
304
- skipScenarioIndex = i;
331
+
332
+ if (i === indexOfScenarioToUpdate) {
333
+ results.push("");
334
+ results.push(newScenarioContent.trim());
335
+ results.push("");
305
336
  continue;
306
337
  }
307
- let scenarioContent = `${scenario.hasParams ? "Scenario Outline" : "Scenario"}: ${scenario.name}`;
338
+
339
+ const scenarioHeader = `${scenario.hasParams ? "Scenario Outline" : "Scenario"}: ${scenario.name}`;
308
340
  let tagsLine;
341
+
309
342
  if (scenario.tags?.length > 0) {
310
- tagsLine = `${scenario.tags.map((t) => `@${t}`).join(" ")}`;
343
+ tagsLine = scenario.tags.map((t) => `@${t}`).join(" ");
311
344
  }
312
- if (tagsLine) results.push("\t" + tagsLine);
313
- results.push(`\t${scenarioContent}`);
345
+
346
+ if (tagsLine) results.push(`\t${tagsLine}`);
347
+ results.push(`\t${scenarioHeader}`);
348
+
314
349
  for (const step of scenario.steps) {
315
350
  if (step.type === "examples") {
316
351
  results.push(`\t\tExamples:`);
@@ -323,14 +358,12 @@ function updateExistingScenario({ featureFileContent, scenarioName, scenarioCont
323
358
  }
324
359
  results.push("");
325
360
  }
326
- let finalContent = results.join("\n");
327
- if (skipScenarioIndex !== -1) {
328
- finalContent = results.join("\n") + "\n" + scenarioContent;
329
- }
330
- return finalContent;
361
+
362
+ return results.join("\n");
331
363
  }
332
- export async function updateFeatureFile({ featureName, scenario, override, projectDir }) {
333
- const featureFilePath = path.join(projectDir, "features", featureName + ".feature");
364
+
365
+ async function updateFeatureFile({ featureName, scenario, override, projectDir, logger }) {
366
+ const featureFilePath = path.join(projectDir, "features", `${featureName}.feature`);
334
367
  const isFeatureFileExists = existsSync(featureFilePath);
335
368
  const scenarioContent = getScenarioContent(
336
369
  { scenario },
@@ -361,13 +394,13 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
361
394
  plugins: ["prettier-plugin-gherkin"],
362
395
  });
363
396
  } catch (error) {
364
- console.error("Error formatting feature file content with Prettier:", error);
397
+ logger.error("Error formatting feature file content with Prettier:", error);
365
398
  }
366
399
  writeFileSync(featureFilePath, updatedFeatureFileContent);
367
400
  return;
368
401
  }
369
402
  }
370
- let updatedFeatureFileContent = featureFileContent + "\n" + scenarioContent;
403
+ let updatedFeatureFileContent = `${featureFileContent}\n${scenarioContent}`;
371
404
  try {
372
405
  updatedFeatureFileContent = await prettier.format(updatedFeatureFileContent, {
373
406
  ...prettierConfig,
@@ -375,7 +408,7 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
375
408
  plugins: ["prettier-plugin-gherkin"],
376
409
  });
377
410
  } catch (error) {
378
- console.error("Error formatting feature file content with Prettier:", error);
411
+ logger.error("Error formatting feature file content with Prettier:", error);
379
412
  }
380
413
  writeFileSync(featureFilePath, updatedFeatureFileContent);
381
414
  } else {
@@ -387,8 +420,22 @@ export async function updateFeatureFile({ featureName, scenario, override, proje
387
420
  plugins: ["prettier-plugin-gherkin"],
388
421
  });
389
422
  } catch (error) {
390
- console.error("Error formatting feature file content with Prettier:", error);
423
+ logger.error("Error formatting feature file content with Prettier:", error);
391
424
  }
392
425
  writeFileSync(featureFilePath, featureFileContent);
393
426
  }
394
427
  }
428
+
429
+ export {
430
+ containsScenario,
431
+ testStringForRegex,
432
+ escapeNonPrintables,
433
+ getCommandContent,
434
+ getExamplesContent,
435
+ getTagsContent,
436
+ getScenarioContent,
437
+ escapeString,
438
+ GherkinToObject,
439
+ updateExistingScenario,
440
+ updateFeatureFile,
441
+ };
@@ -0,0 +1,61 @@
1
+ import { io } from "socket.io-client";
2
+ import { BVTRecorderInit } from "./bvt_init.js";
3
+ import { loadArgs, showUsage, validateCLIArg } from "../cli_helpers.js";
4
+ const requiredEnvVars = ["PROJECT_ID", "BLINQ_TOKEN", "SESSION_ID", "WORKER_WS_SERVER_URL", "REMOTE_ORIGINS_URL"];
5
+ function validateEnvVariables() {
6
+ const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]);
7
+ if (missingVars.length > 0) {
8
+ throw new Error(`Missing required environment variables: ${missingVars.join(", ")}`);
9
+ }
10
+ else {
11
+ console.log("All required environment variables are set.");
12
+ requiredEnvVars.forEach((varName) => {
13
+ console.log(`${varName}: ${process.env[varName]}`);
14
+ });
15
+ }
16
+ }
17
+ function getEnvironmentConfig() {
18
+ const args = loadArgs();
19
+ const projectDir = args[0] || process.env.PROJECT_ID;
20
+ const envName = args[1]?.split("=")[1] || process.env.ENV_NAME;
21
+ const roomId = args[2] || process.env.SESSION_ID;
22
+ const shouldTakeScreenshot = args[3] || process.env.SHOULD_TAKE_SCREENSHOT;
23
+ const TOKEN = process.env.BLINQ_TOKEN;
24
+ try {
25
+ validateCLIArg(projectDir, "projectDir");
26
+ validateCLIArg(envName, "envName");
27
+ validateCLIArg(roomId, "roomId");
28
+ validateCLIArg(shouldTakeScreenshot, "shouldTakeScreenshot");
29
+ if (!TOKEN) {
30
+ throw new Error("BLINQ_TOKEN env variable not set");
31
+ }
32
+ }
33
+ catch (error) {
34
+ const usage = `Usage: node bvt_recorder.js <projectDir> <envName> <roomId>`;
35
+ if (error instanceof Error) {
36
+ showUsage(error, usage);
37
+ }
38
+ else {
39
+ const unknownError = new Error("An unknown error occurred");
40
+ showUsage(unknownError, usage);
41
+ }
42
+ }
43
+ return { envName, projectDir, roomId, TOKEN };
44
+ }
45
+ function initWebBVTRecorder() {
46
+ const socket = io(process.env.WORKER_WS_SERVER_URL, {
47
+ path: "/ws",
48
+ transports: ["websocket", "polling"],
49
+ reconnection: true,
50
+ });
51
+ validateEnvVariables();
52
+ const { envName, projectDir, roomId, TOKEN } = getEnvironmentConfig();
53
+ BVTRecorderInit({
54
+ envName: envName,
55
+ projectDir,
56
+ roomId,
57
+ TOKEN,
58
+ socket: socket,
59
+ });
60
+ }
61
+ initWebBVTRecorder();
@@ -53,6 +53,7 @@ const Types = {
53
53
  SET_INPUT_FILES: "set_input_files",
54
54
  VERIFY_PAGE_SNAPSHOT: "verify_page_snapshot",
55
55
  CONDITIONAL_WAIT: "conditional_wait",
56
+ SLEEP: "sleep",
56
57
  };
57
58
  class Recording {
58
59
  steps = [];
@@ -12,6 +12,7 @@ class ScenarioUploadService {
12
12
  this.runsApiBaseURL + "/scenarios/create",
13
13
  {
14
14
  name,
15
+ branch: process.env.GIT_BRANCH ? process.env.GIT_BRANCH : "main",
15
16
  },
16
17
  {
17
18
  headers: {
@@ -37,7 +38,7 @@ class ScenarioUploadService {
37
38
  },
38
39
  });
39
40
 
40
- if(response.status === 401) {
41
+ if (response.status === 401) {
41
42
  throw new Error("Your trial plan has ended. Cannot upload reports and perform retraining");
42
43
  }
43
44
 
@@ -63,7 +64,7 @@ class ScenarioUploadService {
63
64
  }
64
65
  );
65
66
 
66
- if(response.status === 403) {
67
+ if (response.status === 403) {
67
68
  throw new Error("Your trial plan has ended. Cannot upload reports and perform retraining");
68
69
  }
69
70
 
@@ -107,6 +108,7 @@ class ScenarioUploadService {
107
108
  {
108
109
  scenarioId,
109
110
  projectId,
111
+ testcase_id: process.env.TESTCASE_ID,
110
112
  },
111
113
  {
112
114
  headers: {
@@ -0,0 +1,21 @@
1
+ import path from "node:path";
2
+ import os from "node:os";
3
+ function getAppDataDir(project_id) {
4
+ if (process.env.BLINQ_APPDATA_DIR) {
5
+ return path.join(process.env.BLINQ_APPDATA_DIR, "blinq.io", project_id);
6
+ }
7
+ let appDataDir;
8
+ switch (process.platform) {
9
+ case "win32":
10
+ appDataDir = path.join(process.env.APPDATA, "blinq.io", project_id);
11
+ break;
12
+ case "darwin":
13
+ appDataDir = path.join(os.homedir(), "Library", "Application Support", "blinq.io", project_id);
14
+ break;
15
+ default:
16
+ appDataDir = path.join(os.homedir(), ".config", "blinq.io", project_id);
17
+ break;
18
+ }
19
+ return appDataDir;
20
+ }
21
+ export { getAppDataDir };
@@ -1,132 +1,94 @@
1
- /**
2
- * @typedef {Object} SocketLoggerEventPayload
3
- * @property {string} level Log level (e.g. "info", "warn", "error", "debug")
4
- * @property {string} context Log context/subsystem (e.g. "BVTRecorder")
5
- * @property {*} data The log message payload (string, object, etc)
6
- * @property {string} timestamp ISO string when the log was emitted
7
- * @property {number} dataSize Size of data in bytes (-1 if unknown)
8
- */
9
-
10
- /**
11
- * @typedef {Object} SocketLoggerInitOptions
12
- * @property {string=} context Default context for all logs (optional)
13
- * @property {string=} eventName Default event name (default: "recorder.log")
14
- */
15
-
1
+ function getErrorMessage(err) {
2
+ if (typeof err === "string") {
3
+ return err;
4
+ }
5
+ else if (err instanceof Error) {
6
+ return err.message;
7
+ }
8
+ else {
9
+ try {
10
+ return JSON.stringify(err);
11
+ }
12
+ catch {
13
+ return String(err);
14
+ }
15
+ }
16
+ }
16
17
  /**
17
18
  * SocketLogger - Singleton for structured socket-based logging.
18
19
  *
19
- * @namespace SocketLogger
20
- * @property {function(import('socket.io-client').Socket|import('socket.io').Socket, SocketLoggerInitOptions=):void} init
21
- * @property {function(string, (string|*), Object=, string=, string=):void} log
22
- * @property {function((string|*), Object=):void} info
23
- * @property {function((string|*), Object=):void} warn
24
- * @property {function((string|*), Object=):void} debug
25
- * @property {function((string|*), Object=):void} error
26
- *
27
20
  * @example
28
- * import logger from "./socket_logger.js";
29
- * logger.init(socket, { context: "BVTRecorder" });
30
- * logger.info("Step started", { step: 2 });
31
- * logger.error("Failed!", { error: "bad stuff" });
21
+ * import SocketLogger from "./socket_logger";
22
+ * SocketLogger.getInstance().init(socket, { context: "BVTRecorder" });
23
+ * SocketLogger.getInstance().info("Step started", { step: 2 });
24
+ * SocketLogger.getInstance().error("Failed!", { error: "bad stuff" });
32
25
  */
33
- const SocketLogger = (function () {
34
- /** @type {import('socket.io-client').Socket|import('socket.io').Socket|null} */
35
- let socket = null;
36
- /** @type {string} */
37
- let defaultContext = "";
38
- /** @type {string} */
39
- let defaultEventName = "recorder.log";
40
-
41
- /**
42
- * Initialize the logger (call once).
43
- * @param {import('socket.io-client').Socket|import('socket.io').Socket} sock
44
- * @param {SocketLoggerInitOptions=} opts
45
- */
46
- function init(sock, opts) {
47
- socket = sock;
48
- defaultContext = (opts && opts.context) || "";
49
- defaultEventName = (opts && opts.eventName) || "recorder.log";
50
- }
51
-
52
- /**
53
- * Low-level log method (most users use info/warn/debug/error).
54
- * @param {string} level Log level ("info", "warn", "debug", "error")
55
- * @param {string|*} message The log message or object
56
- * @param {Object=} extra Extra fields (will be merged into log payload)
57
- * @param {string=} eventName Override event name for this log (default: "recorder.log")
58
- * @param {string=} context Override log context for this log (default: set in init)
59
- */
60
- function log(level, message, extra, eventName, context) {
61
- if (!socket || typeof socket.emit !== "function") return;
62
- /** @type {*} */
63
- var data = typeof message === "object" ? message : { message: message };
64
- /** @type {number} */
65
- var dataSize = 0;
66
- try {
67
- dataSize = Buffer.byteLength(JSON.stringify(data || ""), "utf8");
68
- } catch (e) {
69
- dataSize = -1;
26
+ export class SocketLogger {
27
+ static instance;
28
+ socket = null;
29
+ defaultContext = "BVTRecorder";
30
+ defaultEventName = "BVTRecorder.log";
31
+ constructor() { }
32
+ static getInstance() {
33
+ if (!SocketLogger.instance) {
34
+ SocketLogger.instance = new SocketLogger();
35
+ }
36
+ return SocketLogger.instance;
37
+ }
38
+ init(sock, opts) {
39
+ this.socket = sock;
40
+ this.defaultContext = opts?.context || "";
41
+ this.defaultEventName = opts?.eventName || "recorder.log";
42
+ }
43
+ log(level, message, extra, context) {
44
+ if (!this.socket || typeof this.socket.emit !== "function")
45
+ return;
46
+ const data = typeof message === "object" ? message : { message };
47
+ let dataSize = 0;
48
+ try {
49
+ dataSize = Buffer.byteLength(JSON.stringify(data || ""), "utf8");
50
+ }
51
+ catch {
52
+ dataSize = -1;
53
+ }
54
+ const eventPayload = {
55
+ level,
56
+ context: context || this.defaultContext,
57
+ data: JSON.stringify({
58
+ ...data,
59
+ errorMessage: level === "error" && data ? getErrorMessage(data) : undefined,
60
+ }),
61
+ timestamp: new Date().toISOString(),
62
+ dataSize,
63
+ ...extra,
64
+ };
65
+ try {
66
+ if (this.socket) {
67
+ this.socket.emit(this.defaultEventName, eventPayload);
68
+ }
69
+ console.log(`${context ?? this.defaultContext} [${level.toUpperCase()}]:`, {
70
+ ...data,
71
+ ...extra,
72
+ });
73
+ }
74
+ catch (e) {
75
+ console.error("Socket logging error:", e);
76
+ console.log("Socket event payload:", eventPayload);
77
+ }
78
+ }
79
+ info(msg, ext, ctx) {
80
+ this.log("info", msg, ext, ctx);
81
+ }
82
+ warn(msg, ext, ctx) {
83
+ this.log("warn", msg, ext, ctx);
84
+ }
85
+ debug(msg, ext, ctx) {
86
+ this.log("debug", msg, ext, ctx);
70
87
  }
71
- /** @type {SocketLoggerEventPayload} */
72
- var eventPayload = Object.assign(
73
- {
74
- level: level,
75
- context: context || defaultContext,
76
- data: data,
77
- timestamp: new Date().toISOString(),
78
- dataSize: dataSize,
79
- },
80
- extra || {}
81
- );
82
- // @ts-ignore
83
- try {
84
- if (socket) {
85
- socket.emit(eventName || defaultEventName, eventPayload);
86
- }
87
- } catch (e) {
88
- console.error("Socket logging error:", e);
89
- console.log("Socket event payload:", eventPayload);
88
+ error(msg, ext, ctx) {
89
+ this.log("error", msg, ext, ctx);
90
90
  }
91
- }
92
-
93
- /**
94
- * Write an info-level log event.
95
- * @param {string|*} msg The message or object
96
- * @param {Object=} ext Any extra fields/metadata
97
- */
98
- function info(msg, ext) {
99
- log("info", msg, ext);
100
- }
101
-
102
- /**
103
- * Write a warn-level log event.
104
- * @param {string|*} msg The message or object
105
- * @param {Object=} ext Any extra fields/metadata
106
- */
107
- function warn(msg, ext) {
108
- log("warn", msg, ext);
109
- }
110
-
111
- /**
112
- * Write a debug-level log event.
113
- * @param {string|*} msg The message or object
114
- * @param {Object=} ext Any extra fields/metadata
115
- */
116
- function debug(msg, ext) {
117
- log("debug", msg, ext);
118
- }
119
-
120
- /**
121
- * Write an error-level log event.
122
- * @param {string|*} msg The message or object
123
- * @param {Object=} ext Any extra fields/metadata
124
- */
125
- function error(msg, ext) {
126
- log("error", msg, ext);
127
- }
128
-
129
- return { init, log, info, warn, debug, error };
130
- })();
131
-
132
- export default SocketLogger;
91
+ }
92
+ const socketLoggerInstance = SocketLogger.getInstance();
93
+ export default socketLoggerInstance;
94
+ export { getErrorMessage };
package/bin/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./client/code_gen/page_reflection.js";
2
+
2
3
  export * from "./client/code_gen/playwright_codeget.js";
3
4
  export * from "./client/cucumber/feature.js";
4
5
  export * from "./client/cucumber/project_to_document.js";
@@ -13,5 +14,7 @@ export * from "./client/cucumber/feature_data.js";
13
14
  export * from "./client/cucumber/steps_definitions.js";
14
15
  export * from "./client/profiler.js";
15
16
  export * from "./client/code_cleanup/utils.js";
16
-
17
17
  export * from "./client/code_cleanup/find_step_definition_references.js";
18
+ export * from "./client/recorderv3/step_utils.js";
19
+ export * from "./client/recorderv3/update_feature.js";
20
+ export * from "./client/recorderv3/bvt_init.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1438-dev",
3
+ "version": "1.0.1438-stage",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
@@ -14,6 +14,8 @@
14
14
  "tests_prod": "rm -rf results.json && cross-env NODE_ENV_BLINQ=prod TOKEN=xxx npx mocha --parallel --jobs=10 ./tests",
15
15
  "tests": "node ./multi_test_runner.js",
16
16
  "lint": "eslint ./src/**/*.js",
17
+ "test:unit": "vitest run",
18
+ "test:unit:watch": "vitest watch",
17
19
  "clean_old": "rimraf -g build1 && rimraf -g types1",
18
20
  "clean": "rimraf -g build && rimraf -g types",
19
21
  "build_old": "npm run clean_old && npm run pack_old",
@@ -37,9 +39,9 @@
37
39
  "@babel/traverse": "^7.27.1",
38
40
  "@babel/types": "^7.27.1",
39
41
  "@cucumber/tag-expressions": "^6.1.1",
40
- "@dev-blinq/cucumber-js": "1.0.184-dev",
41
- "@faker-js/faker": "^8.1.0",
42
- "automation_model": "1.0.831-dev",
42
+ "@dev-blinq/cucumber-js": "1.0.121-stage",
43
+ "@faker-js/faker": "^8.4.1",
44
+ "automation_model": "1.0.798-stage",
43
45
  "axios": "^1.7.4",
44
46
  "chokidar": "^3.6.0",
45
47
  "create-require": "^1.1.1",
@@ -57,6 +59,7 @@
57
59
  "pureimage": "0.4.9",
58
60
  "socket.io": "^4.7.5",
59
61
  "socket.io-client": "^4.7.5",
62
+ "strip-comments": "^2.0.1",
60
63
  "tunnel": "^0.0.6",
61
64
  "unzipper": "^0.12.3",
62
65
  "win-ca": "^3.5.1",
@@ -74,7 +77,10 @@
74
77
  "mocha": "^10.2.0",
75
78
  "ncp": "^2.0.0",
76
79
  "readline-sync": "^1.4.10",
80
+ "ts-node": "^10.9.2",
77
81
  "tsup": "^8.5.0",
78
- "typescript": "^5.9.2"
82
+ "typescript": "^5.9.2",
83
+ "vite-tsconfig-paths": "^6.0.4",
84
+ "vitest": "^2.1.4"
79
85
  }
80
86
  }