@dev-blinq/cucumber_client 1.0.1377-dev → 1.0.1377-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.
- package/bin/assets/bundled_scripts/recorder.js +107 -107
- package/bin/assets/preload/css_gen.js +10 -10
- package/bin/assets/preload/toolbar.js +27 -29
- package/bin/assets/preload/unique_locators.js +1 -1
- package/bin/assets/preload/yaml.js +288 -275
- package/bin/assets/scripts/aria_snapshot.js +223 -220
- package/bin/assets/scripts/dom_attr.js +329 -329
- package/bin/assets/scripts/dom_parent.js +169 -174
- package/bin/assets/scripts/event_utils.js +94 -94
- package/bin/assets/scripts/pw.js +2050 -1949
- package/bin/assets/scripts/recorder.js +13 -23
- package/bin/assets/scripts/snapshot_capturer.js +147 -147
- package/bin/assets/scripts/unique_locators.js +163 -44
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +41 -0
- package/bin/assets/templates/utils_template.txt +2 -45
- package/bin/client/apiTest/apiTest.js +6 -0
- package/bin/client/code_cleanup/utils.js +5 -1
- package/bin/client/code_gen/api_codegen.js +2 -2
- package/bin/client/code_gen/code_inversion.js +107 -2
- package/bin/client/code_gen/function_signature.js +4 -0
- package/bin/client/code_gen/page_reflection.js +846 -906
- package/bin/client/code_gen/playwright_codeget.js +32 -3
- package/bin/client/cucumber/feature.js +4 -0
- package/bin/client/cucumber/feature_data.js +2 -2
- package/bin/client/cucumber/project_to_document.js +8 -2
- package/bin/client/cucumber/steps_definitions.js +6 -3
- package/bin/client/cucumber_selector.js +17 -1
- package/bin/client/local_agent.js +3 -2
- package/bin/client/parse_feature_file.js +23 -26
- package/bin/client/playground/projects/env.json +2 -2
- package/bin/client/project.js +186 -196
- package/bin/client/recorderv3/bvt_init.js +325 -0
- package/bin/client/recorderv3/bvt_recorder.js +301 -102
- package/bin/client/recorderv3/implemented_steps.js +8 -0
- package/bin/client/recorderv3/index.js +4 -303
- package/bin/client/recorderv3/scriptTest.js +1 -1
- package/bin/client/recorderv3/services.js +430 -154
- package/bin/client/recorderv3/step_runner.js +315 -206
- package/bin/client/recorderv3/step_utils.js +479 -25
- package/bin/client/recorderv3/update_feature.js +9 -5
- package/bin/client/recorderv3/wbr_entry.js +61 -0
- package/bin/client/recording.js +1 -0
- package/bin/client/upload-service.js +3 -2
- package/bin/client/utils/socket_logger.js +132 -0
- package/bin/index.js +4 -1
- package/bin/logger.js +3 -2
- package/bin/min/consoleApi.min.cjs +2 -3
- package/bin/min/injectedScript.min.cjs +16 -16
- package/package.json +20 -10
|
@@ -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 ({ result, pickleStep }) {
|
|
38
|
+
if (context) {
|
|
39
|
+
await context.web.afterStep(this, pickleStep, result);
|
|
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
|
|
@@ -214,6 +171,6 @@ Then("Verify the page title is {string}", verify_page_title);
|
|
|
214
171
|
* @returns Promise that resolves after the specified duration
|
|
215
172
|
*/
|
|
216
173
|
async function sleep(duration) {
|
|
217
|
-
await context.web.sleep(duration, {},
|
|
174
|
+
await context.web.sleep(duration, {}, this);
|
|
218
175
|
}
|
|
219
176
|
Then("Sleep for {string} ms", { timeout: -1 }, sleep);
|
|
@@ -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
|
}
|
|
@@ -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
|
);
|
|
@@ -375,11 +375,13 @@ const invertStableCommand = (call, elements, stepParams) => {
|
|
|
375
375
|
case "verifyTextRelatedToText": {
|
|
376
376
|
step.type = Types.VERIFY_TEXT_RELATED_TO_TEXT;
|
|
377
377
|
const textAnchorParse = parseDataSource(call.arguments[0], stepParams);
|
|
378
|
-
const textAnchor =
|
|
378
|
+
const textAnchor =
|
|
379
|
+
textAnchorParse.type === "literal" ? textAnchorParse.value : toVariableName(textAnchorParse.dataKey);
|
|
379
380
|
const climbParse = parseDataSource(call.arguments[1], stepParams);
|
|
380
381
|
const climb = climbParse.type === "literal" ? climbParse.value : toVariableName(climbParse.dataKey);
|
|
381
382
|
const textToVerifyParse = parseDataSource(call.arguments[2], stepParams);
|
|
382
|
-
const textToVerify =
|
|
383
|
+
const textToVerify =
|
|
384
|
+
textToVerifyParse.type === "literal" ? textToVerifyParse.value : toVariableName(textToVerifyParse.dataKey);
|
|
383
385
|
step.parameters = [textAnchor, climb, textToVerify];
|
|
384
386
|
break;
|
|
385
387
|
}
|
|
@@ -429,6 +431,109 @@ const invertStableCommand = (call, elements, stepParams) => {
|
|
|
429
431
|
}
|
|
430
432
|
break;
|
|
431
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
|
+
// }
|
|
432
537
|
default:
|
|
433
538
|
return; // Skip if no matching method
|
|
434
539
|
}
|
|
@@ -11,6 +11,8 @@ async function verify_the_opportunity_name_was_created(_name) {
|
|
|
11
11
|
}
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
+
import strip from "strip-comments";
|
|
15
|
+
|
|
14
16
|
function generateSignature(page, functionName) {
|
|
15
17
|
let functionCode = null;
|
|
16
18
|
let method = null;
|
|
@@ -28,6 +30,8 @@ function generateSignature(page, functionName) {
|
|
|
28
30
|
method.node.body.parent.params.forEach((param) => {
|
|
29
31
|
parameters.push(param.name);
|
|
30
32
|
});
|
|
33
|
+
const strippedFunctionCode = strip(functionCode);
|
|
34
|
+
functionCode = strippedFunctionCode !== "" ? strippedFunctionCode : functionCode;
|
|
31
35
|
let lines = functionCode.split("\n");
|
|
32
36
|
// trim all lines
|
|
33
37
|
lines = lines.map((line) => line.trim());
|