@dev-blinq/cucumber_client 1.0.1178-dev → 1.0.1180-dev
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/preload/recorderv3.js +5 -2
- package/bin/client/code_gen/code_inversion.js +70 -8
- package/bin/client/code_gen/playwright_codeget.js +2 -4
- package/bin/client/cucumber/steps_definitions.js +10 -0
- package/bin/client/recorderv3/bvt_recorder.js +10 -0
- package/bin/client/recorderv3/index.js +6 -0
- package/bin/client/recorderv3/update_feature.js +1 -1
- package/package.json +1 -1
|
@@ -304,13 +304,16 @@ function findMatchingElements(inputSnapshot, objectSet) {
|
|
|
304
304
|
|
|
305
305
|
// For each subtree, check for matches in the object set
|
|
306
306
|
subtrees.forEach((subtree) => {
|
|
307
|
-
const subtreeText = subtree.join("\n");
|
|
307
|
+
const subtreeText = subtree.map((t) => t.trim()).join("\n");
|
|
308
308
|
|
|
309
309
|
// Look for matching snapshots in the object set
|
|
310
310
|
for (const obj of objectSet) {
|
|
311
311
|
// Normalize snapshots for comparison (trim whitespace, etc.)
|
|
312
312
|
const normalizedSubtree = subtreeText.trim();
|
|
313
|
-
const normalizedSnapshot = obj.snapshot
|
|
313
|
+
const normalizedSnapshot = obj.snapshot
|
|
314
|
+
.split("\n")
|
|
315
|
+
.map((s) => s.trim())
|
|
316
|
+
.join("\n");
|
|
314
317
|
|
|
315
318
|
// Check if the current object's snapshot matches our subtree
|
|
316
319
|
if (normalizedSnapshot === normalizedSubtree) {
|
|
@@ -387,7 +387,10 @@ const invertStableCommand = (call, elements, stepParams) => {
|
|
|
387
387
|
|
|
388
388
|
case "snapshotValidation": {
|
|
389
389
|
step.type = Types.VERIFY_PAGE_SNAPSHOT;
|
|
390
|
-
|
|
390
|
+
const inputParam = parseDataSource(call.arguments[1], stepParams);
|
|
391
|
+
if (inputParam.type === "literal") {
|
|
392
|
+
step.parameters = [inputParam.value];
|
|
393
|
+
}
|
|
391
394
|
step.nestFrmLoc = call.arguments[0].value;
|
|
392
395
|
break;
|
|
393
396
|
}
|
|
@@ -429,10 +432,70 @@ const invertStableCommand = (call, elements, stepParams) => {
|
|
|
429
432
|
return step;
|
|
430
433
|
};
|
|
431
434
|
|
|
432
|
-
|
|
435
|
+
/* Inspired from https://github.com/hypervillain/ast-to-literal */
|
|
436
|
+
// This function is not used in the current code, but it is a utility function to convert AST nodes to JSON.
|
|
437
|
+
const interestedLiterals = ["BooleanLiteral", "StringLiteral", "NumericLiteral"];
|
|
438
|
+
|
|
439
|
+
const toJSON = (node) => {
|
|
440
|
+
if (interestedLiterals.includes(node.type)) {
|
|
441
|
+
return node.value;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (node.name === "undefined" && !node.value) {
|
|
445
|
+
return undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (node.type === "NullLiteral") {
|
|
449
|
+
return null;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (node.type === "ObjectExpression") {
|
|
453
|
+
return computeProps(node.properties);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (node.type === "ArrayExpression") {
|
|
457
|
+
return node.elements.reduce(
|
|
458
|
+
(acc, element) => [...acc, ...(element.type === "SpreadElement" ? toJSON(element.argument) : [toJSON(element)])],
|
|
459
|
+
[]
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
const computeProps = (props) => {
|
|
465
|
+
return props.reduce((acc, prop) => {
|
|
466
|
+
if (prop.type === "SpreadElement") {
|
|
467
|
+
return {
|
|
468
|
+
...acc,
|
|
469
|
+
...toJSON(prop.argument),
|
|
470
|
+
};
|
|
471
|
+
} else if (prop.type === "ObjectMethod") {
|
|
472
|
+
const val = toJSON(prop.value);
|
|
473
|
+
if (val !== undefined) {
|
|
474
|
+
return {
|
|
475
|
+
...acc,
|
|
476
|
+
[prop.key.name]: val,
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return acc;
|
|
481
|
+
}, {});
|
|
482
|
+
};
|
|
433
483
|
|
|
434
|
-
|
|
435
|
-
|
|
484
|
+
const invertApiCommand = (stepsDefinitions, codePage, stepName) => {
|
|
485
|
+
let apiData = null;
|
|
486
|
+
const step = { type: Types.API, value: null };
|
|
487
|
+
const apiStep = stepsDefinitions.findMatchingStep(stepName);
|
|
488
|
+
for (const method of codePage.methods) {
|
|
489
|
+
if (method.getMethodType() === "api" && method.name == apiStep.functionName) {
|
|
490
|
+
apiData = method.getVariableDeclerationObject("apiData");
|
|
491
|
+
break;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
step.value = apiData;
|
|
495
|
+
return step;
|
|
496
|
+
// const apiData = toJSON(call.arguments[0]);
|
|
497
|
+
};
|
|
498
|
+
const invertCodeToCommand = (codeString, elements = {}, stepParams, stepsDefinitions, codePage, stepName) => {
|
|
436
499
|
const walker = new Walker();
|
|
437
500
|
const steps = [];
|
|
438
501
|
|
|
@@ -455,13 +518,12 @@ const invertCodeToCommand = (codeString, elements = {}, stepParams) => {
|
|
|
455
518
|
|
|
456
519
|
const propName = call.callee.object.property.name;
|
|
457
520
|
|
|
458
|
-
// if (propName === 'api') {
|
|
459
|
-
// const step = invertApiCommand(call);
|
|
460
|
-
// if (step) steps.push(step);
|
|
461
|
-
// } else
|
|
462
521
|
if (propName === "web" || propName === "stable") {
|
|
463
522
|
const step = invertStableCommand(call, elements, stepParams);
|
|
464
523
|
if (step) steps.push(step);
|
|
524
|
+
// } else if (propName === "api") {
|
|
525
|
+
// const step = invertApiCommand(stepsDefinitions, codePage, stepName);
|
|
526
|
+
// if (step) steps.push(step);
|
|
465
527
|
} else {
|
|
466
528
|
return;
|
|
467
529
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { Types } from "../recording.js";
|
|
2
|
-
|
|
3
2
|
import logger from "../../logger.js";
|
|
4
3
|
import { StepsDefinitions } from "../cucumber/steps_definitions.js";
|
|
5
4
|
import path from "path";
|
|
6
5
|
import { CodePage } from "./page_reflection.js";
|
|
7
6
|
import { convertToIdentifier, escapeNonPrintables } from "./utils.js";
|
|
8
|
-
import { all } from "axios";
|
|
9
7
|
const findElementIdentifier = (node, step, userData, elements) => {
|
|
10
8
|
if (node.key) {
|
|
11
9
|
// incase of rerunning implemented steps
|
|
@@ -290,12 +288,12 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
290
288
|
}
|
|
291
289
|
case Types.VERIFY_PAGE_SNAPSHOT:
|
|
292
290
|
comment = step.nestFrmLoc
|
|
293
|
-
? `// Verify page snapshot ${step.parameters[0]} in the frame`
|
|
291
|
+
? `// Verify page snapshot ${step.parameters[0]} in the frame ${step.nestFrmLoc}`
|
|
294
292
|
: `// Verify page snapshot ${step.parameters[0]}`;
|
|
295
293
|
codeLines.push(escapeNonPrintables(comment));
|
|
296
294
|
line = `const frameLocator = ${JSON.stringify(step.nestFrmLoc ?? null)}`;
|
|
297
295
|
codeLines.push(line);
|
|
298
|
-
line = `await context.web.snapshotValidation(frameLocator
|
|
296
|
+
line = `await context.web.snapshotValidation(frameLocator, _param_0 , _params, ${JSON.stringify(options)}, this);`;
|
|
299
297
|
codeLines.push(line);
|
|
300
298
|
break;
|
|
301
299
|
case Types.VERIFY_PAGE_CONTAINS_TEXT:
|
|
@@ -224,6 +224,16 @@ class StepsDefinitions {
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
|
+
} else if (codeObj.type === "VariableDeclaration") {
|
|
228
|
+
if (codeObj.code.includes("context.api.")) {
|
|
229
|
+
codeObj.local_type = "context_api";
|
|
230
|
+
// set api_type to request, etc
|
|
231
|
+
let startIndex = codeObj.code.indexOf("context.api.") + "context.api.".length;
|
|
232
|
+
let endIndex = codeObj.code.indexOf("(", startIndex);
|
|
233
|
+
if (endIndex >= 0) {
|
|
234
|
+
codeObj.api_type = codeObj.code.substring(startIndex, endIndex);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
227
237
|
}
|
|
228
238
|
}
|
|
229
239
|
analyzeStepDefinitionwithStep(step) {
|
|
@@ -495,6 +495,16 @@ export class BVTRecorder {
|
|
|
495
495
|
this.sendEvent(this.events.onGoto, { url: transition.userTypedURL });
|
|
496
496
|
}
|
|
497
497
|
}
|
|
498
|
+
|
|
499
|
+
async getCurrentPageTitle() {
|
|
500
|
+
const title = await this.page.title();
|
|
501
|
+
return title;
|
|
502
|
+
}
|
|
503
|
+
async getCurrentPageUrl() {
|
|
504
|
+
const url = await this.page.url();
|
|
505
|
+
return url;
|
|
506
|
+
}
|
|
507
|
+
|
|
498
508
|
_addPagelisteners(context) {
|
|
499
509
|
context.on("page", async (page) => {
|
|
500
510
|
try {
|
|
@@ -216,6 +216,12 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
|
|
|
216
216
|
return { folder: snapshotFolder, files: ymlFiles };
|
|
217
217
|
} else return { folder: null, files: [] };
|
|
218
218
|
},
|
|
219
|
+
"recorderWindow.getCurrentPageTitle": async (input) => {
|
|
220
|
+
return await recorder.getCurrentPageTitle();
|
|
221
|
+
},
|
|
222
|
+
"recorderWindow.getCurrentPageUrl": async (input) => {
|
|
223
|
+
return await recorder.getCurrentPageUrl();
|
|
224
|
+
},
|
|
219
225
|
"recorderWindow.sendAriaSnapshot": async (input) => {
|
|
220
226
|
const snapshot = input?.snapshot;
|
|
221
227
|
const deselect = input?.deselect;
|
|
@@ -96,7 +96,7 @@ export function getCommandContent(command) {
|
|
|
96
96
|
return `send a ${command.value.method} API request to ${command.value.url}`;
|
|
97
97
|
}
|
|
98
98
|
case "verify_page_snapshot": {
|
|
99
|
-
return `verify page snapshot stored in ${command.
|
|
99
|
+
return `verify page snapshot stored in ${command.parameters[0]}`;
|
|
100
100
|
}
|
|
101
101
|
default: {
|
|
102
102
|
return "";
|