@dev-blinq/cucumber_client 1.0.1332-dev → 1.0.1332-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 (53) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +110 -110
  2. package/bin/assets/preload/css_gen.js +10 -10
  3. package/bin/assets/preload/recorderv3.js +3 -1
  4. package/bin/assets/preload/toolbar.js +27 -29
  5. package/bin/assets/preload/unique_locators.js +1 -1
  6. package/bin/assets/preload/yaml.js +288 -275
  7. package/bin/assets/scripts/aria_snapshot.js +223 -220
  8. package/bin/assets/scripts/dom_attr.js +329 -329
  9. package/bin/assets/scripts/dom_parent.js +169 -174
  10. package/bin/assets/scripts/event_utils.js +94 -94
  11. package/bin/assets/scripts/pw.js +2050 -1949
  12. package/bin/assets/scripts/recorder.js +5 -17
  13. package/bin/assets/scripts/snapshot_capturer.js +153 -146
  14. package/bin/assets/scripts/unique_locators.js +940 -815
  15. package/bin/assets/scripts/yaml.js +796 -783
  16. package/bin/assets/templates/_hooks_template.txt +41 -0
  17. package/bin/assets/templates/utils_template.txt +1 -44
  18. package/bin/client/apiTest/apiTest.js +6 -0
  19. package/bin/client/cli_helpers.js +11 -13
  20. package/bin/client/code_cleanup/utils.js +5 -1
  21. package/bin/client/code_gen/api_codegen.js +2 -2
  22. package/bin/client/code_gen/code_inversion.js +112 -4
  23. package/bin/client/code_gen/page_reflection.js +839 -906
  24. package/bin/client/code_gen/playwright_codeget.js +26 -18
  25. package/bin/client/cucumber/feature.js +89 -27
  26. package/bin/client/cucumber/feature_data.js +2 -2
  27. package/bin/client/cucumber/project_to_document.js +9 -3
  28. package/bin/client/cucumber/steps_definitions.js +6 -3
  29. package/bin/client/cucumber_selector.js +17 -1
  30. package/bin/client/local_agent.js +6 -5
  31. package/bin/client/parse_feature_file.js +23 -26
  32. package/bin/client/playground/projects/env.json +2 -2
  33. package/bin/client/project.js +186 -196
  34. package/bin/client/recorderv3/bvt_recorder.js +181 -78
  35. package/bin/client/recorderv3/implemented_steps.js +24 -14
  36. package/bin/client/recorderv3/index.js +68 -54
  37. package/bin/client/recorderv3/network.js +22 -5
  38. package/bin/client/recorderv3/scriptTest.js +1 -1
  39. package/bin/client/recorderv3/services.js +4 -16
  40. package/bin/client/recorderv3/step_runner.js +303 -205
  41. package/bin/client/recorderv3/step_utils.js +476 -17
  42. package/bin/client/recorderv3/update_feature.js +32 -30
  43. package/bin/client/recording.js +1 -0
  44. package/bin/client/run_cucumber.js +1 -1
  45. package/bin/client/scenario_report.js +0 -5
  46. package/bin/client/test_scenario.js +0 -1
  47. package/bin/client/upload-service.js +3 -2
  48. package/bin/client/utils/socket_logger.js +132 -0
  49. package/bin/index.js +1 -0
  50. package/bin/logger.js +3 -2
  51. package/bin/min/consoleApi.min.cjs +2 -3
  52. package/bin/min/injectedScript.min.cjs +16 -16
  53. package/package.json +21 -12
@@ -0,0 +1,41 @@
1
+ import dotenv from "dotenv";
2
+ // Load .env into process.env
3
+ dotenv.config();
4
+
5
+ import {
6
+ After,
7
+ setDefaultTimeout,
8
+ Before,
9
+ AfterStep,
10
+ BeforeStep,
11
+ } from "@dev-blinq/cucumber-js";
12
+ import { closeContext, initContext, navigate, executeBrunoRequest, verifyFileExists } from "automation_model";
13
+ setDefaultTimeout(60 * 1000);
14
+
15
+ const url = null;
16
+
17
+ const elements = {};
18
+
19
+ let context = null;
20
+ Before(async function (scenario) {
21
+ context = await initContext(url, false, false, this);
22
+ await navigate(url);
23
+ await context.web.beforeScenario(this, scenario);
24
+ });
25
+ After(async function (scenario) {
26
+ await context.web.afterScenario(this, scenario);
27
+ await closeContext();
28
+ context = null;
29
+ });
30
+
31
+ BeforeStep(async function (step) {
32
+ if (context) {
33
+ await context.web.beforeStep(this, step);
34
+ }
35
+ });
36
+
37
+ AfterStep(async function (step) {
38
+ if (context) {
39
+ await context.web.afterStep(this, step);
40
+ }
41
+ });
@@ -2,53 +2,10 @@ import {
2
2
  Given,
3
3
  When,
4
4
  Then,
5
- After,
6
- setDefaultTimeout,
7
- Before,
8
5
  defineStep,
9
- AfterStep,
10
- BeforeStep,
11
6
  } from "@dev-blinq/cucumber-js";
12
- import { closeContext, initContext, navigate, executeBrunoRequest, verifyFileExists } from "automation_model";
7
+ import { closeContext, initContext, navigate, executeBrunoRequest, verifyFileExists, TestContext as context } from "automation_model";
13
8
  import path from "path";
14
- setDefaultTimeout(60 * 1000);
15
-
16
- const url = null;
17
-
18
- const elements = {};
19
-
20
- let context = null;
21
- Before(async function (scenario) {
22
- context = await initContext(url, false, false, this);
23
- await navigate(url);
24
- await context.web.beforeScenario(this, scenario);
25
- });
26
- After(async function (scenario) {
27
- await context.web.afterScenario(this, scenario);
28
- await closeContext();
29
- context = null;
30
- });
31
-
32
- BeforeStep(async function (step) {
33
- if (context) {
34
- await context.web.beforeStep(this, step);
35
- }
36
- });
37
-
38
- AfterStep(async function (step) {
39
- if (context) {
40
- await context.web.afterStep(this, step);
41
- }
42
- });
43
-
44
- /**
45
- * Load test data for a user
46
- * @param {string} user name of the user to load test data for
47
- * @protect
48
- */
49
- async function loadUserData(user) {
50
- await context.web.loadTestDataAsync("users", user, this);
51
- }
52
9
 
53
10
  /**
54
11
  * Verify text exsits in page
@@ -75,6 +75,12 @@ class ApiTest {
75
75
  const utilsTemplateFilePath = path.join(__dirname, "../../assets", "templates", "utils_template.txt");
76
76
  const utilsContent = readFileSync(utilsTemplateFilePath, "utf8");
77
77
  writeFileSync(utilsFilePath, utilsContent, "utf8");
78
+ const hooksTemplateFilePath = path.join(__dirname, "../../assets", "templates", "_hooks_template.txt");
79
+ if (existsSync(hooksTemplateFilePath)) {
80
+ const hooksFilePath = path.join(stepDefinitionFolderPath, "_hooks.mjs");
81
+ const hooksContent = readFileSync(hooksTemplateFilePath, "utf8");
82
+ writeFileSync(hooksFilePath, hooksContent, "utf8");
83
+ }
78
84
  } catch (error) {
79
85
  console.log("error", error);
80
86
  }
@@ -1,17 +1,15 @@
1
-
2
1
  const validateCLIArg = (arg, name) => {
3
2
  if (!arg) {
4
- throw new Error(`${name} is required`)
3
+ throw new Error(`${name} is required`);
5
4
  }
6
- }
5
+ };
7
6
  const showUsage = (error, usage) => {
8
- console.error(error.message)
9
- console.info(usage)
10
- process.exit(1)
11
- }
12
- const loadArgs = ()=>{
13
- const args = process.argv.slice(2)
14
- return args
15
- }
16
-
17
- export { validateCLIArg, loadArgs, showUsage };
7
+ console.error(error.message);
8
+ console.info(usage);
9
+ process.exit(1);
10
+ };
11
+ const loadArgs = () => {
12
+ const args = process.argv.slice(2);
13
+ return args;
14
+ };
15
+ export { validateCLIArg, loadArgs, showUsage };
@@ -7,10 +7,11 @@ const { default: traverse } = pkg;
7
7
  import pkg1 from "@babel/generator";
8
8
  const { default: generate } = pkg1;
9
9
  import * as t from "@babel/types";
10
-
11
10
  import { CucumberExpression, ParameterTypeRegistry } from "@cucumber/cucumber-expressions";
12
11
  import { existsSync, readFileSync, writeFileSync } from "fs";
13
12
  import { getAiConfig } from "../code_gen/page_reflection.js";
13
+ import socketLogger from "../utils/socket_logger.js";
14
+
14
15
  const STEP_KEYWORDS = new Set(["Given", "When", "Then"]);
15
16
 
16
17
  /**
@@ -307,14 +308,17 @@ export function getDefaultPrettierConfig() {
307
308
  const configContent = readFileSync(prettierConfigPath, "utf-8");
308
309
  prettierConfig = JSON.parse(configContent);
309
310
  } catch (error) {
311
+ socketLogger.error("Error parsing Prettier config file", error);
310
312
  console.error(`Error parsing Prettier config file: ${error}`);
311
313
  }
312
314
  } else {
313
315
  // save the default config to .prettierrc
314
316
  try {
315
317
  writeFileSync(prettierConfigPath, JSON.stringify(prettierConfig, null, 2), "utf-8");
318
+ socketLogger.info(`Created default Prettier config at ${prettierConfigPath}`);
316
319
  console.log(`Created default Prettier config at ${prettierConfigPath}`);
317
320
  } catch (error) {
321
+ socketLogger.error(`Error writing Prettier config file: ${error}`);
318
322
  console.error(`Error writing Prettier config file: ${error}`);
319
323
  }
320
324
  }
@@ -50,7 +50,7 @@ const generateApiCode = async (
50
50
  // create new codePage
51
51
  mjsFullPath = path.join(
52
52
  projectDir,
53
- stepsDefinitions.isTemp ? process.env.tempFeaturesFolderPath ?? "__temp_features" : "features",
53
+ stepsDefinitions.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features",
54
54
  "step_definitions",
55
55
  `api_tests_page.mjs`
56
56
  );
@@ -60,7 +60,7 @@ const generateApiCode = async (
60
60
  if (!codePage) {
61
61
  mjsFullPath = path.join(
62
62
  projectDir,
63
- stepsDefinitions.isTemp ? process.env.tempFeaturesFolderPath ?? "__temp_features" : "features",
63
+ stepsDefinitions.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features",
64
64
  "step_definitions",
65
65
  `api_tests_page.mjs`
66
66
  );
@@ -374,10 +374,15 @@ const invertStableCommand = (call, elements, stepParams) => {
374
374
  }
375
375
  case "verifyTextRelatedToText": {
376
376
  step.type = Types.VERIFY_TEXT_RELATED_TO_TEXT;
377
- const textAnchor = parseDataSource(call.arguments[0], stepParams);
378
- const climb = parseDataSource(call.arguments[1], stepParams);
379
- const textToVerify = parseDataSource(call.arguments[2], stepParams);
380
- step.parameters = [textAnchor.value, +climb.value, textToVerify.value];
377
+ const textAnchorParse = parseDataSource(call.arguments[0], stepParams);
378
+ const textAnchor =
379
+ textAnchorParse.type === "literal" ? textAnchorParse.value : toVariableName(textAnchorParse.dataKey);
380
+ const climbParse = parseDataSource(call.arguments[1], stepParams);
381
+ const climb = climbParse.type === "literal" ? climbParse.value : toVariableName(climbParse.dataKey);
382
+ const textToVerifyParse = parseDataSource(call.arguments[2], stepParams);
383
+ const textToVerify =
384
+ textToVerifyParse.type === "literal" ? textToVerifyParse.value : toVariableName(textToVerifyParse.dataKey);
385
+ step.parameters = [textAnchor, climb, textToVerify];
381
386
  break;
382
387
  }
383
388
  case "setInputFiles": {
@@ -426,6 +431,109 @@ const invertStableCommand = (call, elements, stepParams) => {
426
431
  }
427
432
  break;
428
433
  }
434
+ case "verifyProperty": {
435
+ step.type = Types.VERIFY_PROPERTY;
436
+ step.element = extractElement(call.arguments[0]);
437
+ const property = call.arguments[1].value;
438
+ const value = parseDataSource(call.arguments[2], stepParams);
439
+ if (value.type === "literal") {
440
+ step.parameters = [property, value.value];
441
+ } else {
442
+ step.dataSource = value.dataSource;
443
+ step.dataKey = value.dataKey;
444
+ step.parameters = [property, toVariableName(value.dataKey)];
445
+ }
446
+ break;
447
+ }
448
+ case "extractProperty": {
449
+ step.type = Types.EXTRACT_PROPERTY;
450
+ step.element = extractElement(call.arguments[0]);
451
+ const attribute = call.arguments[1].value;
452
+ const variable = parseDataSource(call.arguments[2], stepParams);
453
+ if (variable.type === "literal") {
454
+ step.parameters = [attribute, variable.value];
455
+ } else {
456
+ step.dataSource = variable.dataSource;
457
+ step.dataKey = variable.dataKey;
458
+ step.parameters = [attribute, toVariableName(variable.dataKey)];
459
+ }
460
+ if (call.arguments[4].type === "ObjectExpression") {
461
+ const properties = call.arguments[4].properties;
462
+ const regexProp = properties.findIndex((prop) => prop.key.name === "regex");
463
+ if (regexProp !== -1) {
464
+ const regex = properties[regexProp].value.value;
465
+ step.regex = regex;
466
+ }
467
+ const trimSpacesProp = properties.findIndex((prop) => prop.key.name === "trimSpaces");
468
+ if (trimSpacesProp !== -1) {
469
+ const trimSpaces = properties[trimSpacesProp].value.value;
470
+ step.trimSpaces = trimSpaces;
471
+ }
472
+ } else {
473
+ step.regex = "";
474
+ step.trimSpaces = false;
475
+ }
476
+ break;
477
+ }
478
+
479
+ case "conditionalWait": {
480
+ step.type = Types.CONDITIONAL_WAIT;
481
+ step.element = extractElement(call.arguments[0]);
482
+ const condition = call.arguments[1].value;
483
+
484
+ const _timeout = parseDataSource(call.arguments[2], stepParams);
485
+ let timeout = 30;
486
+ if (_timeout.type === "literal") {
487
+ if (isNaN(_timeout.value)) {
488
+ throw new Error(`Timeout value must be a number, got ${_timeout.value}`);
489
+ }
490
+ timeout = Number(_timeout.value) * 1000;
491
+ } else {
492
+ step.dataSource = _timeout.dataSource;
493
+ step.dataKey = _timeout.dataKey;
494
+ timeout = toVariableName(_timeout.dataKey);
495
+ }
496
+ // step.timeout = timeout;
497
+ // step.value = "true";
498
+ step.parameters = [timeout, condition, step.value];
499
+ // step.condition = condition;
500
+ break;
501
+ }
502
+
503
+ case "sleep": {
504
+ step.type = Types.SLEEP;
505
+ const duration = parseDataSource(call.arguments[0], stepParams);
506
+ if (duration.type === "literal") {
507
+ if (isNaN(duration.value)) {
508
+ throw new Error(`Sleep duration must be a number, got ${duration.value}`);
509
+ }
510
+ step.parameters = [Number(duration.value)];
511
+ } else {
512
+ step.dataSource = duration.dataSource;
513
+ step.dataKey = duration.dataKey;
514
+ step.parameters = [toVariableName(duration.dataKey)];
515
+ }
516
+ break;
517
+ }
518
+ case "verify_file_exists": {
519
+ step.type = Types.VERIFY_FILE_EXISTS;
520
+ const filePath = parseDataSource(call.arguments[0], stepParams);
521
+ if (filePath.type === "literal") {
522
+ step.parameters = [filePath.value];
523
+ } else {
524
+ step.dataSource = filePath.dataSource;
525
+ step.dataKey = filePath.dataKey;
526
+ step.parameters = [toVariableName(filePath.dataKey)];
527
+ }
528
+ break;
529
+ }
530
+
531
+ // case "verifyPagePath":
532
+ // {
533
+ // step.type = Types.VERIFY_PAGE_PATH;
534
+ // step.parameters = [call.arguments[0].value];
535
+ // break;
536
+ // }
429
537
  default:
430
538
  return; // Skip if no matching method
431
539
  }