@dev-blinq/cucumber_client 1.0.1180-dev → 1.0.1180-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 (47) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +220 -0
  2. package/bin/assets/preload/accessibility.js +1 -1
  3. package/bin/assets/preload/find_context.js +1 -1
  4. package/bin/assets/preload/generateSelector.js +24 -0
  5. package/bin/assets/preload/locators.js +18 -0
  6. package/bin/assets/preload/recorderv3.js +80 -9
  7. package/bin/assets/preload/unique_locators.js +24 -3
  8. package/bin/assets/scripts/aria_snapshot.js +235 -0
  9. package/bin/assets/scripts/dom_attr.js +372 -0
  10. package/bin/assets/scripts/dom_element.js +0 -0
  11. package/bin/assets/scripts/dom_parent.js +185 -0
  12. package/bin/assets/scripts/event_utils.js +105 -0
  13. package/bin/assets/scripts/pw.js +7886 -0
  14. package/bin/assets/scripts/recorder.js +1147 -0
  15. package/bin/assets/scripts/snapshot_capturer.js +155 -0
  16. package/bin/assets/scripts/unique_locators.js +844 -0
  17. package/bin/assets/scripts/yaml.js +4770 -0
  18. package/bin/assets/templates/page_template.txt +2 -16
  19. package/bin/assets/templates/utils_template.txt +65 -12
  20. package/bin/client/cli_helpers.js +0 -1
  21. package/bin/client/code_cleanup/utils.js +43 -14
  22. package/bin/client/code_gen/code_inversion.js +45 -13
  23. package/bin/client/code_gen/index.js +3 -0
  24. package/bin/client/code_gen/page_reflection.js +37 -20
  25. package/bin/client/code_gen/playwright_codeget.js +151 -45
  26. package/bin/client/cucumber/feature.js +96 -42
  27. package/bin/client/cucumber/project_to_document.js +8 -7
  28. package/bin/client/cucumber/steps_definitions.js +49 -16
  29. package/bin/client/local_agent.js +9 -7
  30. package/bin/client/operations/dump_tree.js +159 -5
  31. package/bin/client/playground/playground.js +1 -1
  32. package/bin/client/project.js +6 -2
  33. package/bin/client/recorderv3/bvt_recorder.js +279 -81
  34. package/bin/client/recorderv3/cli.js +1 -0
  35. package/bin/client/recorderv3/implemented_steps.js +111 -11
  36. package/bin/client/recorderv3/index.js +48 -4
  37. package/bin/client/recorderv3/network.js +299 -0
  38. package/bin/client/recorderv3/step_runner.js +183 -13
  39. package/bin/client/recorderv3/step_utils.js +159 -14
  40. package/bin/client/recorderv3/update_feature.js +53 -28
  41. package/bin/client/recording.js +8 -0
  42. package/bin/client/run_cucumber.js +116 -4
  43. package/bin/client/scenario_report.js +112 -50
  44. package/bin/client/test_scenario.js +0 -1
  45. package/bin/index.js +1 -0
  46. package/package.json +15 -8
  47. package/bin/client/code_gen/get_implemented_steps.js +0 -27
@@ -5,9 +5,14 @@ import { Step } from "../client/cucumber/feature.js";
5
5
  This list need to be in sync with the list exist in the commands.js file
6
6
  */
7
7
  const Types = {
8
+ API: "api",
8
9
  CLICK: "click_element",
9
10
  CLICK_SIMPLE: "click_simple",
11
+ PARAMETERIZED_CLICK: "parameterized_click",
12
+ CONTEXT_CLICK: "context_click",
10
13
  NAVIGATE: "navigate",
14
+ GO_BACK: "browser_go_back",
15
+ GO_FORWARD: "browser_go_forward",
11
16
  FILL: "fill_element",
12
17
  FILL_SIMPLE: "fill_simple",
13
18
  EXECUTE: "execute_page_method",
@@ -29,6 +34,7 @@ const Types = {
29
34
  SET_COMBO: "set_combo",
30
35
  HOVER: "hover_element",
31
36
  EXTRACT_ATTRIBUTE: "extract_attribute",
37
+ EXTRACT_PROPERTY: "extract_property",
32
38
  CLOSE_PAGE: "close_page",
33
39
  SET_DATE_TIME: "set_date_time",
34
40
  SET_VIEWPORT: "set_viewport",
@@ -40,11 +46,13 @@ const Types = {
40
46
  SET_INPUT: "set_input",
41
47
  WAIT_FOR_USER_INPUT: "wait_for_user_input",
42
48
  VERIFY_ATTRIBUTE: "verify_element_attribute",
49
+ VERIFY_PROPERTY: "verify_element_property",
43
50
  FILL_UNKNOWN: "fill_unknown",
44
51
  VERIFY_TEXT_RELATED_TO_TEXT: "verify_text_in_relation",
45
52
  VERIFY_FILE_EXISTS: "verify_file_exists",
46
53
  SET_INPUT_FILES: "set_input_files",
47
54
  VERIFY_PAGE_SNAPSHOT: "verify_page_snapshot",
55
+ CONDITIONAL_WAIT: "conditional_wait",
48
56
  };
49
57
  class Recording {
50
58
  steps = [];
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync } from "fs";
1
+ import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
2
2
  import logger from "../logger.js";
3
3
  import path from "path";
4
4
  import { scenarioResolution } from "./cucumber/feature.js";
@@ -13,6 +13,77 @@ import crypto from "crypto";
13
13
  //import debug from "debug";
14
14
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
15
15
 
16
+ // Initialize the editorLogs array to collect all logs
17
+ const editorLogs = [];
18
+
19
+ // Store original console methods
20
+ const originalConsoleLog = console.log;
21
+ const originalConsoleError = console.error;
22
+
23
+ // Store original process stdout and stderr write methods
24
+ const originalStdoutWrite = process.stdout.write;
25
+ const originalStderrWrite = process.stderr.write;
26
+
27
+ // Override console.log
28
+ console.log = function (...args) {
29
+ const logEntry = {
30
+ message: args.map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : String(arg))).join(" "),
31
+ };
32
+
33
+ editorLogs.push(logEntry);
34
+ originalConsoleLog.apply(console, args);
35
+ };
36
+
37
+ // Override console.error
38
+ console.error = function (...args) {
39
+ const logEntry = {
40
+ message: args.map((arg) => (typeof arg === "object" ? JSON.stringify(arg) : String(arg))).join(" "),
41
+ };
42
+
43
+ editorLogs.push(logEntry);
44
+ originalConsoleError.apply(console, args);
45
+ };
46
+
47
+ // Override process.stdout.write
48
+ process.stdout.write = function (chunk, encoding, callback) {
49
+ const logEntry = {
50
+ message: chunk.toString(),
51
+ };
52
+
53
+ editorLogs.push(logEntry);
54
+ return originalStdoutWrite.apply(process.stdout, arguments);
55
+ };
56
+
57
+ // Override process.stderr.write
58
+ process.stderr.write = function (chunk, encoding, callback) {
59
+ const logEntry = {
60
+ message: chunk.toString(),
61
+ };
62
+
63
+ editorLogs.push(logEntry);
64
+ return originalStderrWrite.apply(process.stderr, arguments);
65
+ };
66
+
67
+ // Function to write logs to file
68
+ const writeLogsToFile = (filePath) => {
69
+ try {
70
+ const dirPath = path.dirname(filePath);
71
+
72
+ // Create directory if it doesn't exist
73
+ if (!existsSync(dirPath)) {
74
+ mkdirSync(dirPath, { recursive: true });
75
+ }
76
+
77
+ // Format logs as plain message on each line
78
+ const logText = editorLogs.map((log) => `${log.message}`).join("\n");
79
+
80
+ // Write logs to plain text file
81
+ writeFileSync(filePath, logText, { encoding: "utf8" });
82
+ } catch (error) {
83
+ logger.error(`Failed to write logs to file: ${error.message}`);
84
+ }
85
+ };
86
+
16
87
  //do something when app is closing
17
88
 
18
89
  const runCucumber = async (
@@ -60,6 +131,10 @@ const runCucumber = async (
60
131
  } else if (!process.env.NODE_ENV_BLINQ) {
61
132
  serviceUrl = "https://logic.blinq.io";
62
133
  logger.info("Running in prod mode");
134
+ } else if (process.env.WHITELABEL === "true") {
135
+ // if it's a whitelabel it will use "api" instead of "logic"
136
+ serviceUrl = process.env.NODE_ENV_BLINQ;
137
+ logger.info("Running in custom mode: " + serviceUrl);
63
138
  } else {
64
139
  serviceUrl = process.env.NODE_ENV_BLINQ.replace("api", "logic");
65
140
  logger.info("Running in custom mode: " + serviceUrl);
@@ -93,7 +168,14 @@ const runCucumber = async (
93
168
  }
94
169
  return true;
95
170
  });
96
- process.on("exit", async () => await aiAgent.endScenario());
171
+ process.on("exit", async () => {
172
+ // Write logs to file before exiting
173
+ if (result.scenarioPath) {
174
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
175
+ writeLogsToFile(logsFilePath);
176
+ }
177
+ await aiAgent.endScenario();
178
+ });
97
179
  const context = {};
98
180
  result.context = context;
99
181
  if (process.env.E2E === "true") {
@@ -105,6 +187,9 @@ const runCucumber = async (
105
187
  envFile = await aiAgent.initProjectAndEnvironment(context);
106
188
  } catch (e) {
107
189
  logger.error(e.message);
190
+ // Write logs to file before exiting due to error
191
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
192
+ writeLogsToFile(logsFilePath);
108
193
  if (exit) {
109
194
  process.exit(1);
110
195
  }
@@ -118,6 +203,9 @@ const runCucumber = async (
118
203
  }
119
204
  if (!existsSync(fullFeatureFilePath)) {
120
205
  logger.error("Feature file not found: " + fullFeatureFilePath);
206
+ // Write logs to file before exiting due to error
207
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
208
+ writeLogsToFile(logsFilePath);
121
209
  if (exit) {
122
210
  process.exit(1);
123
211
  }
@@ -128,6 +216,9 @@ const runCucumber = async (
128
216
  feature = await scenarioResolution(fullFeatureFilePath);
129
217
  } catch (e) {
130
218
  logger.error("Error parsing feature file: " + fullFeatureFilePath);
219
+ // Write logs to file before exiting due to error
220
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
221
+ writeLogsToFile(logsFilePath);
131
222
  if (exit) {
132
223
  process.exit(1);
133
224
  }
@@ -136,6 +227,9 @@ const runCucumber = async (
136
227
  const scenario = feature.getScenario(scenarioName);
137
228
  if (!scenario) {
138
229
  logger.error("Scenario not found: " + scenarioName);
230
+ // Write logs to file before exiting due to error
231
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
232
+ writeLogsToFile(logsFilePath);
139
233
  if (exit) {
140
234
  process.exit(1);
141
235
  }
@@ -146,6 +240,15 @@ const runCucumber = async (
146
240
 
147
241
  let scenarioId = findNextIdInFolder("./reports");
148
242
  let scenarioPath = "./reports" + "/" + scenarioId;
243
+ const dataFilePath = path.join(scenarioPath, "data.json");
244
+ mkdirSync(path.dirname(dataFilePath), { recursive: true });
245
+ if (process.env.NODE_ENV_BLINQ === "local") {
246
+ let dataPath = aiAgent.project.rootFolder + "/data/data.json";
247
+ if (existsSync(dataPath)) {
248
+ const poolData = JSON.parse(readFileSync(dataPath, "utf-8"));
249
+ writeFileSync(dataFilePath, JSON.stringify(poolData, null, 2), "utf-8");
250
+ }
251
+ }
149
252
  result.scenarioPath = scenarioPath;
150
253
  aiAgent.initTestData(envFile, path.join(scenarioPath, "data.json"));
151
254
  let featureFileRelative = path.relative(projectDir, fullFeatureFilePath);
@@ -256,7 +359,7 @@ const runCucumber = async (
256
359
  await aiAgent.createNewStepLocal(
257
360
  featureName,
258
361
  cucumberStep,
259
- feature,
362
+ feature.comments,
260
363
  userData,
261
364
  first,
262
365
  previousTasks,
@@ -283,6 +386,9 @@ const runCucumber = async (
283
386
  ) {
284
387
  aiAgent.evaluateScenario();
285
388
  }
389
+ // Write logs to file on successful completion
390
+ const logsFilePath = path.join(scenarioPath, "editorLogs.log");
391
+ writeLogsToFile(logsFilePath);
286
392
  await aiAgent.endScenario();
287
393
  } catch (e) {
288
394
  if (reconnect) {
@@ -303,7 +409,12 @@ const runCucumber = async (
303
409
  logger.error(e.stack);
304
410
  message = e.message + "\n" + e.stack;
305
411
  }
412
+ aiAgent.scenarioReport.updateLastCommand({ status: false, error: message });
413
+ // Write logs to file on error
414
+ const logsFilePath = path.join(result.scenarioPath, "editorLogs.log");
415
+ writeLogsToFile(logsFilePath);
306
416
  await aiAgent.endScenario();
417
+
307
418
  if (exit) {
308
419
  process.exit(1);
309
420
  }
@@ -316,4 +427,5 @@ const runCucumber = async (
316
427
  return result;
317
428
  }
318
429
  };
319
- export { runCucumber };
430
+
431
+ export { runCucumber, editorLogs, writeLogsToFile };
@@ -7,6 +7,8 @@ import { getJsonReport } from "./bvt_json_report.js";
7
7
  import axios from "axios";
8
8
  import { getRunsServiceBaseURL } from "./utils/index.js";
9
9
  import { axiosClient } from "./utils/axiosClient.js";
10
+ import { promisify } from "util";
11
+ import { exec } from "child_process";
10
12
 
11
13
  const BATCH_SIZE = 10;
12
14
  const MAX_RETRIES = 3;
@@ -31,17 +33,12 @@ const findNextIdInFolder = (folder) => {
31
33
  // get temp file path from --temp-file arg
32
34
  const getTempFilePath = () => {
33
35
  let tempFilePath = null;
34
-
35
36
  for (const arg of process.argv) {
36
37
  const [key, path] = arg.split("=");
37
38
  if (key === "--temp-file" && !!path) {
38
39
  tempFilePath = path;
39
40
  }
40
41
  }
41
-
42
- if (tempFilePath === null) {
43
- tempFilePath = process.env.TEMP_FILE_PATH;
44
- }
45
42
  return tempFilePath;
46
43
  };
47
44
 
@@ -193,64 +190,114 @@ class ScenarioReport {
193
190
  fs.writeFileSync(path, zipBlob);
194
191
  return path;
195
192
  }
196
-
193
+ // Note to future self:
194
+ // Increased the max retries to 3 and added exponential backoff to increase consistency but traded off availability :)
197
195
  async _uploadScenario() {
198
196
  try {
199
- const scenarioDoc = await this.scenarioUploadService.createScenarioDocument(this.name);
197
+ let scenarioDoc;
198
+ let attempts = 1;
199
+ while (attempts < MAX_RETRIES) {
200
+ try {
201
+ scenarioDoc = await this.scenarioUploadService.createScenarioDocument(this.name);
202
+
203
+ break; // exit loop if successful
204
+ } catch (err) {
205
+ attempts++;
206
+ await this._delay(2 ** attempts * 1000);
207
+ if (attempts >= MAX_RETRIES) {
208
+ logger.error(`Failed to upload scenario document (Attempt ${attempts})`);
209
+ return;
210
+ }
211
+ }
212
+ }
200
213
  const scenarioDocId = scenarioDoc._id;
201
214
  const projectId = scenarioDoc.project_id;
202
215
  this.scenario_id = scenarioDocId;
203
216
  this._saveToFile();
204
-
205
- // console.log("scenarioDocId", scenarioDocId);
206
217
  await this.sendRetrainStats(scenarioDocId);
207
- // create zip file
208
218
  if (process.env.NODE_ENV_BLINQ === "local") {
209
- const zipFilePath = await this.createScenarioZip();
210
- // upload to server
211
- const formData = new FormData();
212
- // const file = File(zipFileBlob, "report.zip");
213
- formData.append(scenarioDocId, fs.readFileSync(zipFilePath), "report.zip");
214
- await this.scenarioUploadService.upload(formData);
219
+ await this._uploadLocalBundle(scenarioDocId);
215
220
  } else {
216
- const report = getJsonReport(this);
217
- fs.writeFileSync(path.join(this.scenarioPath, "scenario.json"), JSON.stringify(report, null, 2));
218
- const fileUris = [...this.getFileUrisScreenShotDir(this.scenarioPath), "scenario.json", "network.json"];
219
- const networkJsonPath = path.join(this.scenarioPath, "network.json");
220
- if (!fs.existsSync(networkJsonPath)) {
221
- fs.writeFileSync(networkJsonPath, JSON.stringify({}), "utf-8");
222
- }
223
- const presignedUrls = await this.scenarioUploadService.getPresignedUrls(fileUris, scenarioDocId);
224
- for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
225
- const batch = fileUris.slice(i, Math.min(i + BATCH_SIZE, fileUris.length));
226
- await Promise.all(
227
- batch
228
- .filter((fileUrl) => presignedUrls[fileUrl] !== undefined)
229
- .map(async (fileUrl) => {
230
- const filePath = path.join(this.scenarioPath, fileUrl);
231
- for (let j = 0; j < MAX_RETRIES; j++) {
232
- const success = await this.scenarioUploadService.uploadFile(filePath, presignedUrls[fileUrl]);
233
- if (success) {
234
- return;
235
- }
236
- }
237
- console.error("Failed to upload file", fileUrl);
238
- })
239
- );
240
- }
241
- await this.scenarioUploadService.uploadComplete(scenarioDocId, projectId);
221
+ await this._uploadRemoteBundle(scenarioDocId, projectId);
242
222
  }
243
223
  logger.info("Scenario uploaded successfully");
244
-
245
224
  this.logReportLink(projectId, scenarioDocId);
246
-
247
- // delete zip file
248
- // fs.unlinkSync(this.scenarioPath + '/example.zip');
249
225
  } catch (err) {
250
- logger.info("Failed to upload scenario - ignored");
251
- logger.debug(err);
252
- //console.error(err);
226
+ logger.error("Scenario upload failed");
227
+ logger.debug("Error while uploading : ", err);
228
+ }
229
+ }
230
+ // Local environment uploader decomposed the function for better readability
231
+ async _uploadLocalBundle(scenarioDocId) {
232
+ const zipFilePath = await this.createScenarioZip();
233
+ const formData = new FormData();
234
+ formData.append("scenarioId", scenarioDocId);
235
+ formData.append("file", fs.createReadStream(zipFilePath));
236
+
237
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
238
+ try {
239
+ await this.scenarioUploadService.upload(formData);
240
+ fs.unlinkSync(zipFilePath);
241
+ return;
242
+ } catch (err) {
243
+ logger.debug("Local upload attempt failed", { attempt, error: err });
244
+ // added delays between retries for better consistency over availability
245
+ await this._delay(2 ** attempt * 1000);
246
+ }
247
+ }
248
+ throw new Error(`Local upload failed after ${MAX_RETRIES} attempts`);
249
+ }
250
+
251
+ // decomposed the function for better readability this function is used to upload
252
+ async _uploadRemoteBundle(scenarioDocId, projectId) {
253
+ const report = getJsonReport(this);
254
+ fs.writeFileSync(path.join(this.scenarioPath, "scenario.json"), JSON.stringify(report, null, 2));
255
+
256
+ const fileUris = [
257
+ ...this.getFileUrisScreenShotDir(this.scenarioPath),
258
+ "scenario.json",
259
+ "network.json",
260
+ "editorLogs.log",
261
+ ];
262
+ const networkJsonPath = path.join(this.scenarioPath, "network.json");
263
+ if (!fs.existsSync(networkJsonPath)) {
264
+ fs.writeFileSync(networkJsonPath, JSON.stringify({}), "utf-8");
265
+ }
266
+
267
+ const presignedUrls = await this.scenarioUploadService.getPresignedUrls(fileUris, scenarioDocId);
268
+ const missing = fileUris.filter((uri) => !presignedUrls[uri]);
269
+ if (missing.length) {
270
+ throw new Error(`Missing presigned URLs for: ${missing.join(", ")}`);
271
+ }
272
+
273
+ // Upload files in batches with retries
274
+ for (let i = 0; i < fileUris.length; i += BATCH_SIZE) {
275
+ const batch = fileUris.slice(i, i + BATCH_SIZE);
276
+ await Promise.all(batch.map((uri) => this._retryUploadFile(uri, presignedUrls[uri])));
253
277
  }
278
+
279
+ await this.scenarioUploadService.uploadComplete(scenarioDocId, projectId);
280
+ }
281
+
282
+ // Retry helper it will retry the upload of a file if it fails given file uri and url here Max_retires is and each retiry wait time : 2secs ,4secs, 8 secs
283
+ // Note to self : if the still upload fails a lot we have to investigate the file formats too
284
+ async _retryUploadFile(fileUri, url) {
285
+ const filePath = path.join(this.scenarioPath, fileUri);
286
+ for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
287
+ try {
288
+ await this.scenarioUploadService.uploadFile(filePath, url);
289
+ return;
290
+ } catch (err) {
291
+ logger.debug("Upload file attempt failed ", { fileUri, attempt, error: err });
292
+ await this._delay(2 ** attempt * 1000);
293
+ }
294
+ }
295
+ throw new Error(`Failed to upload file ${fileUri} after ${MAX_RETRIES} attempts`);
296
+ }
297
+
298
+ // Utility delay can be used to delay anything (Note to self : Replace it with the built in delay function later)
299
+ _delay(ms) {
300
+ return new Promise((resolve) => setTimeout(resolve, ms));
254
301
  }
255
302
 
256
303
  logReportLink(projectId, scenarioId) {
@@ -269,6 +316,12 @@ class ScenarioReport {
269
316
  baseUrl = process.env.NODE_ENV_BLINQ.replace("api", "app");
270
317
  }
271
318
  const reportLink = baseUrl + "/" + projectId + "/scenario-report/" + scenarioId;
319
+ try {
320
+ const status = getJsonReport(this).result.status;
321
+ publishReportLinkToGuacServer(reportLink, status === "PASSED");
322
+ } catch (err) {
323
+ logger.error(`Failed to publish report link to guac server: ${err}`);
324
+ }
272
325
  logger.info(`Report link :- ${reportLink}`);
273
326
  }
274
327
 
@@ -424,5 +477,14 @@ class ScenarioReport {
424
477
  }
425
478
  }
426
479
  }
427
-
480
+ function publishReportLinkToGuacServer(reportLink, status) {
481
+ try {
482
+ if (existsSync('/tmp/report_publish.sh')) {
483
+ const execAsync = promisify(exec);
484
+ execAsync("sh /tmp/report_publish.sh " + reportLink + " " + status);
485
+ }
486
+ } catch (error) {
487
+ logger.error("Error while publishing report link to Guac server: " + error);
488
+ }
489
+ }
428
490
  export { ScenarioReport, findNextIdInFolder };
@@ -267,7 +267,6 @@ try {
267
267
  }
268
268
  if (validatePath !== "null") {
269
269
  await prevrunResult.context.stable.verifyPagePath(validatePath);
270
-
271
270
  }
272
271
  //finalCompare = true;
273
272
  } catch (e) {
package/bin/index.js CHANGED
@@ -13,4 +13,5 @@ export * from "./client/cucumber/feature_data.js";
13
13
  export * from "./client/cucumber/steps_definitions.js";
14
14
  export * from "./client/profiler.js";
15
15
  export * from "./client/code_cleanup/utils.js";
16
+
16
17
  export * from "./client/code_cleanup/find_step_definition_references.js";
package/package.json CHANGED
@@ -1,22 +1,26 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1180-dev",
4
- "description": "",
3
+ "version": "1.0.1180-stage",
4
+ "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
- "pack": "mkdir build && mkdir build/bin && cp -R ./src/* ./build/bin && cp ./package.json ./build",
9
+ "pack": "npm run bundle && mkdir build && mkdir build/bin && cp -R ./src/* ./build/bin && cp ./package.json ./build",
10
10
  "test": "node ./test/test.js",
11
11
  "tests_prod": "rm -rf results.json && cross-env NODE_ENV_BLINQ=prod TOKEN=xxx npx mocha --parallel --jobs=10 ./tests",
12
12
  "tests": "node ./multi_test_runner.js",
13
13
  "lint": "eslint ./src/**/*.js",
14
14
  "clean": "rm -rf ./build",
15
15
  "build": "npm run clean && npm run pack",
16
+ "build:watch": "npx nodemon --watch src/client --exec 'npm run build'",
16
17
  "update_logic": "rm -rf ../logic/node_modules/@dev-blinq && mkdir ../logic/node_modules/@dev-blinq && mkdir ../logic/node_modules/@dev-blinq/cucumber_client && mkdir ../logic/node_modules/@dev-blinq/cucumber_client/bin && mkdir ../logic/node_modules/@dev-blinq/cucumber_client/node_modules && cp -R ./build/* ../logic/node_modules/@dev-blinq/cucumber_client/bin && cp -R ./node_modules/* ../logic/node_modules/@dev-blinq/cucumber_client/node_modules && cp ./package.json ../logic/node_modules/@dev-blinq/cucumber_client/",
17
18
  "version-bump": "npm version prepatch --preid=dev",
18
- "scripts_regression": "cross-env HEADLESS=true npx mocha --bail --parallel --jobs=12 ./scripts_regression/ --timeout 120000",
19
- "runtime_reg": "cross-env HEADLESS=true npx mocha --bail --parallel --jobs=12 ./runtime_regression/ --timeout 4800000"
19
+ "scripts_regression": "npm run bundle && cross-env HEADLESS=true npx mocha --bail --parallel --jobs=12 ./scripts_regression/ --timeout 120000",
20
+ "runtime_reg": "npm run bundle && cross-env HEADLESS=true npx mocha --bail --parallel --jobs=12 ./runtime_regression/ --timeout 4800000",
21
+ "bundle": "npx tsup",
22
+ "bundle:watch": "npx tsup --watch",
23
+ "regenerate_baselines": "rm -rf ./scripts_regression/locators_baseline/* ./scripts_regression/commands_baseline/* && npm run scripts_regression && npm run scripts_regression"
20
24
  },
21
25
  "author": "",
22
26
  "license": "ISC",
@@ -26,9 +30,9 @@
26
30
  "@babel/traverse": "^7.27.1",
27
31
  "@babel/types": "^7.27.1",
28
32
  "@cucumber/tag-expressions": "^6.1.1",
29
- "@dev-blinq/cucumber-js": "1.0.171-dev",
33
+ "@dev-blinq/cucumber-js": "1.0.91-stage",
30
34
  "@faker-js/faker": "^8.1.0",
31
- "automation_model": "1.0.715-dev",
35
+ "automation_model": "1.0.691-stage",
32
36
  "axios": "^1.7.4",
33
37
  "chokidar": "^3.6.0",
34
38
  "create-require": "^1.1.1",
@@ -43,6 +47,7 @@
43
47
  "patch-package": "^8.0.0",
44
48
  "playwright-core": "1.52.0",
45
49
  "prettier": "^3.2.5",
50
+ "prettier-plugin-gherkin": "^3.1.2",
46
51
  "pureimage": "0.4.9",
47
52
  "socket.io": "^4.7.5",
48
53
  "socket.io-client": "^4.7.5",
@@ -59,6 +64,8 @@
59
64
  "eslint": "^8.50.0",
60
65
  "http-server": "^14.1.1",
61
66
  "mocha": "^10.2.0",
62
- "readline-sync": "^1.4.10"
67
+ "readline-sync": "^1.4.10",
68
+ "tsup": "^8.5.0",
69
+ "typescript": "^5.8.3"
63
70
  }
64
71
  }
@@ -1,27 +0,0 @@
1
- import { StepsDefinitions } from "../cucumber/steps_definitions.js";
2
- import fs from "fs";
3
- const getImplementedSteps = (projectDir) => {
4
- try {
5
- const stepsDefinitions = new StepsDefinitions(projectDir);
6
- stepsDefinitions.load(false);
7
- const keys = Object.keys(stepsDefinitions.steps).filter((key) => key !== "Before" && key !== "After");
8
- return keys;
9
- } catch (error) {
10
- console.log(error);
11
- process.exit(1);
12
- }
13
- };
14
- const args = process.argv.slice(2);
15
- if (args.length < 1 || args.length > 2) {
16
- console.log("Usage: node get_implemented_steps.js <projectDir> [<outputFilePath>]");
17
- process.exit(1);
18
- }
19
- const projectDir = args[0];
20
- const implementedSteps = getImplementedSteps(projectDir);
21
- const output = JSON.stringify(implementedSteps, null, 2);
22
- if (args.length === 2) {
23
- const outputFilePath = args[1];
24
- fs.writeFileSync(outputFilePath, output);
25
- } else {
26
- console.log(output);
27
- }