@dev-blinq/cucumber_client 1.0.1444-dev → 1.0.1444-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 +73 -73
- 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 +70 -45
- package/bin/assets/scripts/snapshot_capturer.js +147 -147
- package/bin/assets/scripts/unique_locators.js +170 -49
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +6 -2
- package/bin/assets/templates/utils_template.txt +16 -16
- package/bin/client/code_cleanup/find_step_definition_references.js +0 -1
- package/bin/client/code_cleanup/utils.js +16 -7
- package/bin/client/code_gen/api_codegen.js +2 -2
- package/bin/client/code_gen/code_inversion.js +119 -2
- package/bin/client/code_gen/duplication_analysis.js +2 -1
- package/bin/client/code_gen/function_signature.js +4 -0
- package/bin/client/code_gen/page_reflection.js +52 -11
- package/bin/client/code_gen/playwright_codeget.js +163 -75
- package/bin/client/cucumber/feature.js +4 -17
- 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 +19 -3
- package/bin/client/local_agent.js +1 -0
- package/bin/client/parse_feature_file.js +23 -26
- package/bin/client/playground/projects/env.json +2 -2
- package/bin/client/recorderv3/bvt_init.js +305 -0
- package/bin/client/recorderv3/bvt_recorder.js +1024 -58
- package/bin/client/recorderv3/implemented_steps.js +2 -0
- package/bin/client/recorderv3/index.js +3 -283
- package/bin/client/recorderv3/services.js +818 -142
- package/bin/client/recorderv3/step_runner.js +20 -6
- package/bin/client/recorderv3/step_utils.js +542 -73
- package/bin/client/recorderv3/update_feature.js +87 -39
- package/bin/client/recorderv3/wbr_entry.js +61 -0
- package/bin/client/recording.js +1 -0
- package/bin/client/upload-service.js +4 -2
- package/bin/client/utils/app_dir.js +21 -0
- package/bin/client/utils/socket_logger.js +87 -125
- package/bin/index.js +4 -1
- package/package.json +11 -5
- package/bin/client/recorderv3/app_dir.js +0 -23
- package/bin/client/recorderv3/network.js +0 -299
- package/bin/client/recorderv3/scriptTest.js +0 -5
- package/bin/client/recorderv3/ws_server.js +0 -72
|
@@ -5,6 +5,8 @@ import path from "path";
|
|
|
5
5
|
import { CodePage } from "./page_reflection.js";
|
|
6
6
|
import { convertToIdentifier, escapeNonPrintables } from "./utils.js";
|
|
7
7
|
import socketLogger from "../utils/socket_logger.js";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
|
|
8
10
|
const findElementIdentifier = (node, step, userData, elements) => {
|
|
9
11
|
if (node.key) {
|
|
10
12
|
// incase of rerunning implemented steps
|
|
@@ -47,6 +49,7 @@ const findElementIdentifier = (node, step, userData, elements) => {
|
|
|
47
49
|
return elementIdentifier;
|
|
48
50
|
};
|
|
49
51
|
const _isCodeGenerationStep = (step) => {
|
|
52
|
+
return true;
|
|
50
53
|
if (
|
|
51
54
|
step.type === Types.CLICK ||
|
|
52
55
|
step.type === Types.FILL ||
|
|
@@ -67,12 +70,44 @@ const _isCodeGenerationStep = (step) => {
|
|
|
67
70
|
step.type === Types.VERIFY_PROPERTY ||
|
|
68
71
|
step.type === Types.SET_INPUT_FILES ||
|
|
69
72
|
step.type === Types.VERIFY_PAGE_SNAPSHOT ||
|
|
70
|
-
step.type === Types.CONDITIONAL_WAIT
|
|
73
|
+
step.type === Types.CONDITIONAL_WAIT ||
|
|
74
|
+
step.type === Types.CLOSE_PAGE
|
|
71
75
|
) {
|
|
72
76
|
return true;
|
|
73
77
|
}
|
|
74
78
|
return false;
|
|
75
79
|
};
|
|
80
|
+
|
|
81
|
+
const _isLocatorStrategyStep = (step) => {
|
|
82
|
+
switch (step.type) {
|
|
83
|
+
case Types.VERIFY_PAGE_SNAPSHOT:
|
|
84
|
+
case Types.CLOSE_PAGE:
|
|
85
|
+
case Types.VERIFY_FILE_EXISTS:
|
|
86
|
+
case Types.VERIFY_PAGE_CONTAINS_NO_TEXT:
|
|
87
|
+
case Types.VERIFY_PAGE_CONTAINS_TEXT:
|
|
88
|
+
case Types.VERIFY_PAGE_PATH:
|
|
89
|
+
case Types.VERIFY_PAGE_TITLE:
|
|
90
|
+
case Types.VERIFY_TEXT_RELATED_TO_TEXT:
|
|
91
|
+
case Types.NAVIGATE:
|
|
92
|
+
case Types.RELOAD:
|
|
93
|
+
case Types.GO_BACK:
|
|
94
|
+
case Types.GO_FORWARD:
|
|
95
|
+
case Types.SLEEP:
|
|
96
|
+
case Types.SET_VIEWPORT:
|
|
97
|
+
case Types.VISUAL_VERIFICATION:
|
|
98
|
+
case Types.LOAD_DATA:
|
|
99
|
+
case Types.MAIL_GET_CODE_OR_URL:
|
|
100
|
+
case Types.ASK:
|
|
101
|
+
case Types.WAIT_FOR_USER_INPUT:
|
|
102
|
+
case Types.COMPLETE:
|
|
103
|
+
case Types.CLICK_SIMPLE:
|
|
104
|
+
case Types.FILL_SIMPLE:
|
|
105
|
+
case Types.API:
|
|
106
|
+
return false;
|
|
107
|
+
default:
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
76
111
|
// Note: this function is used to exclude a key from an object
|
|
77
112
|
// Please move it to utils and use it as a reusable function ...
|
|
78
113
|
function excludeKey(obj, keyToRemove) {
|
|
@@ -97,6 +132,20 @@ const splitToLocatorsGroups = (locators) => {
|
|
|
97
132
|
});
|
|
98
133
|
return { basic, no_text, ignore_digit, context };
|
|
99
134
|
};
|
|
135
|
+
|
|
136
|
+
const serializeOptions = (options, context) => {
|
|
137
|
+
if (!options) return "null";
|
|
138
|
+
if (typeof options !== 'object') return "null";
|
|
139
|
+
if (Array.isArray(options)) return "null";
|
|
140
|
+
let result = "{ ";
|
|
141
|
+
if (context) result += `"context": ${context}, `;
|
|
142
|
+
for (const key in options) {
|
|
143
|
+
result += `"${key}": ${JSON.stringify(options[key])}, `;
|
|
144
|
+
}
|
|
145
|
+
result += " }";
|
|
146
|
+
return result;
|
|
147
|
+
}
|
|
148
|
+
|
|
100
149
|
const _generateCodeFromCommand = (step, elements, userData) => {
|
|
101
150
|
let elementsChanged = false;
|
|
102
151
|
|
|
@@ -105,7 +154,12 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
105
154
|
// handle element
|
|
106
155
|
let element_name = null;
|
|
107
156
|
let allStrategyLocators = null;
|
|
108
|
-
|
|
157
|
+
const codeLines = [];
|
|
158
|
+
|
|
159
|
+
if (_isCodeGenerationStep(step) === false)
|
|
160
|
+
return { codeLines, elements: elementsChanged ? elements : null, elementIdentifier, allStrategyLocators };
|
|
161
|
+
|
|
162
|
+
if (_isCodeGenerationStep(step) && _isLocatorStrategyStep(step)) {
|
|
109
163
|
allStrategyLocators = step.allStrategyLocators ?? splitToLocatorsGroups(step.locators);
|
|
110
164
|
let node = null;
|
|
111
165
|
|
|
@@ -167,8 +221,6 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
167
221
|
}
|
|
168
222
|
}
|
|
169
223
|
|
|
170
|
-
const codeLines = [];
|
|
171
|
-
|
|
172
224
|
let line = null;
|
|
173
225
|
let comment = null;
|
|
174
226
|
let input = null;
|
|
@@ -176,7 +228,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
176
228
|
let attribute = null;
|
|
177
229
|
let variable = null;
|
|
178
230
|
let format = null;
|
|
179
|
-
let options = null;
|
|
231
|
+
let options = step.options ?? null;
|
|
180
232
|
let property = null;
|
|
181
233
|
switch (step.type) {
|
|
182
234
|
case Types.SET_INPUT:
|
|
@@ -186,7 +238,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
186
238
|
//parameters.push(step.dataKey);
|
|
187
239
|
input = "_" + step.dataKey;
|
|
188
240
|
}
|
|
189
|
-
line += `${input}, _params,
|
|
241
|
+
line += `${input}, _params, ${serializeOptions(options)}, this);`;
|
|
190
242
|
if (element_name) {
|
|
191
243
|
comment = `// Set ${element_name} to ${input}`;
|
|
192
244
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -199,7 +251,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
199
251
|
comment = `// Check ${element_name}`;
|
|
200
252
|
codeLines.push(escapeNonPrintables(comment));
|
|
201
253
|
}
|
|
202
|
-
line = `await context.web.setCheck(elements["${elementIdentifier}"], ${step.check}, _params,
|
|
254
|
+
line = `await context.web.setCheck(elements["${elementIdentifier}"], ${step.check}, _params, ${serializeOptions(options)}, this);`;
|
|
203
255
|
codeLines.push(line);
|
|
204
256
|
} else {
|
|
205
257
|
switch (step.count) {
|
|
@@ -208,7 +260,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
208
260
|
comment = `// Click on ${element_name}`;
|
|
209
261
|
codeLines.push(escapeNonPrintables(comment));
|
|
210
262
|
}
|
|
211
|
-
line = `await context.web.click(elements["${elementIdentifier}"], _params,
|
|
263
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
212
264
|
codeLines.push(line);
|
|
213
265
|
break;
|
|
214
266
|
case 2:
|
|
@@ -216,7 +268,9 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
216
268
|
comment = `// Double click on ${element_name}`;
|
|
217
269
|
codeLines.push(escapeNonPrintables(comment));
|
|
218
270
|
}
|
|
219
|
-
|
|
271
|
+
options = options ?? {};
|
|
272
|
+
options.clickCount = 2;
|
|
273
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
220
274
|
codeLines.push(line);
|
|
221
275
|
break;
|
|
222
276
|
default:
|
|
@@ -224,7 +278,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
224
278
|
comment = `// Click on ${element_name}`;
|
|
225
279
|
codeLines.push(escapeNonPrintables(comment));
|
|
226
280
|
}
|
|
227
|
-
line = `await context.web.click(elements["${elementIdentifier}"], _params,
|
|
281
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
228
282
|
codeLines.push(line);
|
|
229
283
|
break;
|
|
230
284
|
}
|
|
@@ -235,17 +289,19 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
235
289
|
case 1:
|
|
236
290
|
comment = `// Parameterized click on ${step.value}`;
|
|
237
291
|
codeLines.push(escapeNonPrintables(comment));
|
|
238
|
-
line = `await context.web.click(elements["${elementIdentifier}"], _params,
|
|
292
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
239
293
|
break;
|
|
240
294
|
case 2:
|
|
241
295
|
comment = `// Parameterized double click on ${step.value}`;
|
|
242
296
|
codeLines.push(escapeNonPrintables(comment));
|
|
243
|
-
|
|
297
|
+
options = options ?? {};
|
|
298
|
+
options.clickCount = 2;
|
|
299
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
244
300
|
break;
|
|
245
301
|
default:
|
|
246
302
|
comment = `// Parameterized click on ${step.value}`;
|
|
247
303
|
codeLines.push(escapeNonPrintables(comment));
|
|
248
|
-
line = `await context.web.click(elements["${elementIdentifier}"], _params,
|
|
304
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
249
305
|
}
|
|
250
306
|
codeLines.push(line);
|
|
251
307
|
break;
|
|
@@ -264,7 +320,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
264
320
|
} else {
|
|
265
321
|
enter = '"' + step.parameters[2] + '"';
|
|
266
322
|
}
|
|
267
|
-
line += `${input}, "${format}", ${enter}, _params,
|
|
323
|
+
line += `${input}, "${format}", ${enter}, _params, ${serializeOptions(options)}, this);`;
|
|
268
324
|
if (element_name) {
|
|
269
325
|
comment = `// Set date time ${element_name} to "${input}" with format "${format}"`;
|
|
270
326
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -286,7 +342,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
286
342
|
} else {
|
|
287
343
|
enter = '"' + step.parameters[1] + '"';
|
|
288
344
|
}
|
|
289
|
-
line += `${input}, ${enter}, _params,
|
|
345
|
+
line += `${input}, ${enter}, _params, ${serializeOptions(options)}, this);`;
|
|
290
346
|
if (element_name) {
|
|
291
347
|
comment = `// Fill ${element_name} with "${input}"`;
|
|
292
348
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -308,7 +364,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
308
364
|
} else {
|
|
309
365
|
enter = '"' + step.parameters[1] + '"';
|
|
310
366
|
}
|
|
311
|
-
line += `${input}, ${enter}, _params,
|
|
367
|
+
line += `${input}, ${enter}, _params, ${serializeOptions(options)}, this);`;
|
|
312
368
|
if (element_name) {
|
|
313
369
|
comment = `// Fill ${element_name} with "${input}"`;
|
|
314
370
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -322,15 +378,25 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
322
378
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
323
379
|
input = "_" + step.dataKey;
|
|
324
380
|
}
|
|
325
|
-
let options = "null";
|
|
381
|
+
// let options = "null";
|
|
326
382
|
if (step.regex !== "") {
|
|
327
|
-
options =
|
|
383
|
+
options = options ?? {}
|
|
384
|
+
options = {
|
|
385
|
+
...options,
|
|
386
|
+
regex: step.regex,
|
|
387
|
+
trimSpaces: step.trimSpaces
|
|
388
|
+
} // `{regex: ${JSON.stringify(step.regex)},trimSpaces: ${step.trimSpaces}}`;
|
|
328
389
|
} else if (step.trimSpaces) {
|
|
329
|
-
options =
|
|
390
|
+
options = options ?? {}
|
|
391
|
+
options = {
|
|
392
|
+
...options,
|
|
393
|
+
trimSpaces: step.trimSpaces
|
|
394
|
+
}
|
|
395
|
+
// options = `{trimSpaces: ${step.trimSpaces}}`;
|
|
330
396
|
} else {
|
|
331
|
-
options = "null";
|
|
397
|
+
options = null//"null";
|
|
332
398
|
}
|
|
333
|
-
line = `await context.web.extractAttribute(elements["${elementIdentifier}"], "${attribute}", ${input}, _params
|
|
399
|
+
line = `await context.web.extractAttribute(elements["${elementIdentifier}"], "${attribute}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
334
400
|
|
|
335
401
|
if (element_name) {
|
|
336
402
|
comment = `// Extract attribute ${attribute} from ${element_name} to ${variable}`;
|
|
@@ -346,15 +412,24 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
346
412
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
347
413
|
input = "_" + step.dataKey;
|
|
348
414
|
}
|
|
349
|
-
let options = "null";
|
|
350
415
|
if (step.regex !== "") {
|
|
351
|
-
options =
|
|
416
|
+
options = options ?? {}
|
|
417
|
+
options = {
|
|
418
|
+
...options,
|
|
419
|
+
regex: step.regex,
|
|
420
|
+
trimSpaces: step.trimSpaces
|
|
421
|
+
} // `{regex: ${JSON.stringify(step.regex)},trimSpaces: ${step.trimSpaces}}`;
|
|
352
422
|
} else if (step.trimSpaces) {
|
|
353
|
-
options =
|
|
423
|
+
options = options ?? {}
|
|
424
|
+
options = {
|
|
425
|
+
...options,
|
|
426
|
+
trimSpaces: step.trimSpaces
|
|
427
|
+
}
|
|
428
|
+
// options = `{trimSpaces: ${step.trimSpaces}}`;
|
|
354
429
|
} else {
|
|
355
|
-
options = "null";
|
|
430
|
+
options = null//"null";
|
|
356
431
|
}
|
|
357
|
-
line = `await context.web.extractProperty(elements["${elementIdentifier}"], "${property}", ${input}, _params
|
|
432
|
+
line = `await context.web.extractProperty(elements["${elementIdentifier}"], "${property}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
358
433
|
|
|
359
434
|
if (element_name) {
|
|
360
435
|
comment = `// Extract property ${property} from ${element_name} to ${variable}`;
|
|
@@ -363,23 +438,40 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
363
438
|
codeLines.push(line);
|
|
364
439
|
break;
|
|
365
440
|
}
|
|
366
|
-
case Types.VERIFY_PAGE_SNAPSHOT:
|
|
441
|
+
case Types.VERIFY_PAGE_SNAPSHOT: {
|
|
367
442
|
comment = step.nestFrmLoc
|
|
368
443
|
? `// Verify page snapshot ${step.parameters[0]} in the frame ${step.selectors.iframe_src}`
|
|
369
444
|
: `// Verify page snapshot ${step.parameters[0]}`;
|
|
370
445
|
codeLines.push(escapeNonPrintables(comment));
|
|
371
446
|
line = `const frameLocator = ${JSON.stringify(step.selectors ?? null)}`;
|
|
372
447
|
codeLines.push(line);
|
|
373
|
-
line = `await context.web.snapshotValidation(frameLocator
|
|
448
|
+
line = `await context.web.snapshotValidation(frameLocator,${step.valueInStepText ? "_param_0" : `"${step.parameters[0]}"`}, _params, ${serializeOptions(options)}, this);`;
|
|
374
449
|
codeLines.push(line);
|
|
450
|
+
|
|
451
|
+
const data = step.data;
|
|
452
|
+
if (data) {
|
|
453
|
+
try {
|
|
454
|
+
const { snapshot, fileName, filePath } = data;
|
|
455
|
+
const folderPath = process.env.BVT_TEMP_SNAPSHOTS_FOLDER ?? filePath;
|
|
456
|
+
const filePathWithName = path.join(folderPath, fileName);
|
|
457
|
+
if (!fs.existsSync(folderPath)) {
|
|
458
|
+
fs.mkdirSync(folderPath, { recursive: true });
|
|
459
|
+
}
|
|
460
|
+
fs.writeFileSync(filePathWithName, snapshot, "utf-8");
|
|
461
|
+
} catch (e) {
|
|
462
|
+
console.log(`Error saving snapshot file: ${e}`);
|
|
463
|
+
throw e;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
375
466
|
break;
|
|
467
|
+
}
|
|
376
468
|
case Types.VERIFY_PAGE_CONTAINS_TEXT:
|
|
377
469
|
line = "await context.web.verifyTextExistInPage( ";
|
|
378
470
|
input = `${escapeNonPrintables(JSON.stringify(step.parameters[0]))}`;
|
|
379
471
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
380
472
|
input = "_" + step.dataKey;
|
|
381
473
|
}
|
|
382
|
-
line += `${input},
|
|
474
|
+
line += `${input}, ${serializeOptions(options)}, this);`;
|
|
383
475
|
comment = `// Verify page contains text "${input}"`;
|
|
384
476
|
codeLines.push(escapeNonPrintables(comment));
|
|
385
477
|
codeLines.push(line);
|
|
@@ -393,7 +485,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
393
485
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
394
486
|
input = "_" + step.dataKey;
|
|
395
487
|
}
|
|
396
|
-
line += `${input}, ${step.parameters[1]} ,_params,
|
|
488
|
+
line += `${input}, ${step.parameters[1]} , _params, ${serializeOptions(options)}, this);`;
|
|
397
489
|
if (element_name) {
|
|
398
490
|
comment = `// Verify ${element_name} contains text "${input}"`;
|
|
399
491
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -408,7 +500,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
408
500
|
}
|
|
409
501
|
line = `await context.web.analyzeTable(elements["${elementIdentifier}"], ${JSON.stringify(
|
|
410
502
|
step.parameters[0]
|
|
411
|
-
)}, "${step.parameters[1]}", ${input}, _params,
|
|
503
|
+
)}, "${step.parameters[1]}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
412
504
|
if (element_name) {
|
|
413
505
|
comment = `// Analyze table ${element_name} query ${JSON.stringify(
|
|
414
506
|
step.parameters[0]
|
|
@@ -428,27 +520,27 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
428
520
|
} else if (step.dataSource === "environment") {
|
|
429
521
|
input = `context.environment["_${step.dataKey}"]`;
|
|
430
522
|
}
|
|
431
|
-
line += `${input}, _params,
|
|
523
|
+
line += `${input}, _params, ${serializeOptions(options)}, this);`;
|
|
432
524
|
if (element_name) {
|
|
433
525
|
comment = `// Select "${input}" from ${element_name}`;
|
|
434
526
|
codeLines.push(escapeNonPrintables(comment));
|
|
435
527
|
}
|
|
436
528
|
codeLines.push(line);
|
|
437
529
|
} else if (step.selectMode === "click_combo") {
|
|
438
|
-
line = `await context.web.click(elements["${elementIdentifier}"], _params,
|
|
530
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
439
531
|
if (element_name) {
|
|
440
532
|
comment = `// Open combobox ${element_name}`;
|
|
441
533
|
codeLines.push(escapeNonPrintables(comment));
|
|
442
534
|
}
|
|
443
535
|
codeLines.push(line);
|
|
444
|
-
line = `await context.web.click(elements["${optionIdentifier}"], _params,
|
|
536
|
+
line = `await context.web.click(elements["${optionIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
445
537
|
if (element_name) {
|
|
446
538
|
comment = `// Select "${optionIdentifier}" from ${element_name}`;
|
|
447
539
|
codeLines.push(escapeNonPrintables(comment));
|
|
448
540
|
}
|
|
449
541
|
codeLines.push(line);
|
|
450
542
|
} else if (step.selectMode === "click") {
|
|
451
|
-
line = `await context.web.click(elements["${optionIdentifier}"], _params,
|
|
543
|
+
line = `await context.web.click(elements["${optionIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
452
544
|
if (element_name) {
|
|
453
545
|
comment = `// Select ${optionIdentifier} from ${element_name}`;
|
|
454
546
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -461,13 +553,13 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
461
553
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
462
554
|
input = "_" + step.dataKey;
|
|
463
555
|
}
|
|
464
|
-
line += `${input}, false, _params,
|
|
556
|
+
line += `${input}, false, _params, ${serializeOptions(options)}, this);`;
|
|
465
557
|
if (element_name) {
|
|
466
558
|
comment = `// Fill ${element_name} with "${input}"`;
|
|
467
559
|
codeLines.push(escapeNonPrintables(comment));
|
|
468
560
|
}
|
|
469
561
|
codeLines.push(line);
|
|
470
|
-
line = `await context.web.click(elements["${optionIdentifier}"], _params,
|
|
562
|
+
line = `await context.web.click(elements["${optionIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
471
563
|
codeLines.push(line);
|
|
472
564
|
} else {
|
|
473
565
|
throw new Error(`Unknown select mode ${step.selectMode}`);
|
|
@@ -479,13 +571,13 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
479
571
|
case Types.RELOAD:
|
|
480
572
|
comment = `// Reload page`;
|
|
481
573
|
codeLines.push(escapeNonPrintables(comment));
|
|
482
|
-
line =
|
|
574
|
+
line = `await context.web.reloadPage(${serializeOptions(options)}, this);`;
|
|
483
575
|
codeLines.push(line);
|
|
484
576
|
break;
|
|
485
577
|
case Types.CLOSE_PAGE:
|
|
486
578
|
comment = `// Close page`;
|
|
487
579
|
codeLines.push(escapeNonPrintables(comment));
|
|
488
|
-
line =
|
|
580
|
+
line = `await context.web.closePage(${serializeOptions(options)}, this);`;
|
|
489
581
|
codeLines.push(line);
|
|
490
582
|
break;
|
|
491
583
|
case Types.NAVIGATE:
|
|
@@ -498,7 +590,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
498
590
|
} else if (step.dataSource === "environment") {
|
|
499
591
|
input = `context.environment["_${step.dataKey}"]`;
|
|
500
592
|
}
|
|
501
|
-
line = `await context.web.goto(${input}, this);`;
|
|
593
|
+
line = `await context.web.goto(${input}, this, ${serializeOptions(options)});`;
|
|
502
594
|
codeLines.push(line);
|
|
503
595
|
break;
|
|
504
596
|
case Types.VERIFY_PAGE_PATH:
|
|
@@ -507,7 +599,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
507
599
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
508
600
|
input = "_" + step.dataKey;
|
|
509
601
|
}
|
|
510
|
-
line += `${input},
|
|
602
|
+
line += `${input}, ${serializeOptions(options)}, this);`;
|
|
511
603
|
comment = `// Verify page path "${input}"`;
|
|
512
604
|
codeLines.push(escapeNonPrintables(comment));
|
|
513
605
|
codeLines.push(line);
|
|
@@ -518,7 +610,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
518
610
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
519
611
|
input = "_" + step.dataKey;
|
|
520
612
|
}
|
|
521
|
-
line += `${input},
|
|
613
|
+
line += `${input}, ${serializeOptions(options)}, this);`;
|
|
522
614
|
comment = `// Verify page title "${input}"`;
|
|
523
615
|
codeLines.push(escapeNonPrintables(comment));
|
|
524
616
|
codeLines.push(line);
|
|
@@ -528,13 +620,13 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
528
620
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
529
621
|
input = "_" + step.dataKey;
|
|
530
622
|
}
|
|
531
|
-
line = `await context.web.type(${input}, _params,
|
|
623
|
+
line = `await context.web.type(${input}, _params, ${serializeOptions(options)}, this);`;
|
|
532
624
|
comment = `// Type "${input}"`;
|
|
533
625
|
codeLines.push(escapeNonPrintables(comment));
|
|
534
626
|
codeLines.push(line);
|
|
535
627
|
break;
|
|
536
628
|
case Types.HOVER:
|
|
537
|
-
line = `await context.web.hover(elements["${elementIdentifier}"], _params,
|
|
629
|
+
line = `await context.web.hover(elements["${elementIdentifier}"], _params, ${serializeOptions(options)}, this);`;
|
|
538
630
|
if (element_name) {
|
|
539
631
|
comment = `// Hover ${element_name}`;
|
|
540
632
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -575,13 +667,15 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
575
667
|
case Types.CHECK:
|
|
576
668
|
comment = `// Check ${element_name}`;
|
|
577
669
|
codeLines.push(escapeNonPrintables(comment));
|
|
578
|
-
line = `await context.web.setCheck(elements["${elementIdentifier}"], ${step.check}, _params,
|
|
670
|
+
line = `await context.web.setCheck(elements["${elementIdentifier}"], ${step.check}, _params, ${serializeOptions(options)}, this);`;
|
|
579
671
|
codeLines.push(line);
|
|
580
672
|
break;
|
|
581
673
|
case Types.PRESS:
|
|
582
674
|
comment = `// Press ${step.key}`;
|
|
583
675
|
codeLines.push(escapeNonPrintables(comment));
|
|
584
|
-
|
|
676
|
+
options = options ?? {};
|
|
677
|
+
options.press = true;
|
|
678
|
+
line = `await context.web.clickType( elements["${elementIdentifier}"] ,"${step.key}",null, _params, ${serializeOptions(options)}, this);`;
|
|
585
679
|
codeLines.push(line);
|
|
586
680
|
break;
|
|
587
681
|
case Types.CONTEXT_CLICK:
|
|
@@ -593,7 +687,9 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
593
687
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
594
688
|
input = "_" + step.dataKey;
|
|
595
689
|
}
|
|
596
|
-
|
|
690
|
+
// options = options ?? {};
|
|
691
|
+
// options.context = input;
|
|
692
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options, input)}, this);`;
|
|
597
693
|
codeLines.push(line);
|
|
598
694
|
break;
|
|
599
695
|
case 2:
|
|
@@ -603,7 +699,10 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
603
699
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
604
700
|
input = "_" + step.dataKey;
|
|
605
701
|
}
|
|
606
|
-
|
|
702
|
+
options = options ?? {};
|
|
703
|
+
// options.context = input;
|
|
704
|
+
options.clickCount = 2;
|
|
705
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options, input)}, this);`;
|
|
607
706
|
codeLines.push(line);
|
|
608
707
|
break;
|
|
609
708
|
default:
|
|
@@ -613,7 +712,9 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
613
712
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
614
713
|
input = "_" + step.dataKey;
|
|
615
714
|
}
|
|
616
|
-
|
|
715
|
+
// options = options ?? {};
|
|
716
|
+
// options.context = input;
|
|
717
|
+
line = `await context.web.click(elements["${elementIdentifier}"], _params, ${serializeOptions(options, input)}, this);`;
|
|
617
718
|
codeLines.push(line);
|
|
618
719
|
break;
|
|
619
720
|
}
|
|
@@ -638,24 +739,24 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
638
739
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
639
740
|
input = "_" + step.dataKey;
|
|
640
741
|
}
|
|
641
|
-
line += `"${step.parameters[0]}", ${input}, _params,
|
|
742
|
+
line += `"${step.parameters[0]}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
642
743
|
codeLines.push(line);
|
|
643
744
|
break;
|
|
644
745
|
}
|
|
645
746
|
case Types.VERIFY_PROPERTY: {
|
|
646
747
|
line = `await context.web.verifyProperty(elements["${elementIdentifier}"], `;
|
|
647
|
-
input = "_param_0"
|
|
748
|
+
input = step.valueInStepText ? "_param_0" : `"${escapeNonPrintables(step.parameters[1].replaceAll('"', '\\"'))}"`;
|
|
648
749
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
649
750
|
input = "_" + step.dataKey;
|
|
650
751
|
}
|
|
651
|
-
line += `"${step.parameters[0]}", ${input}, _params,
|
|
752
|
+
line += `"${step.parameters[0]}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
652
753
|
codeLines.push(line);
|
|
653
754
|
break;
|
|
654
755
|
}
|
|
655
756
|
case Types.CONDITIONAL_WAIT: {
|
|
656
757
|
line = `await context.web.conditionalWait(elements["${elementIdentifier}"], `;
|
|
657
|
-
input = "_param_0"
|
|
658
|
-
line += `"${step.parameters[1]}", ${input}, _params,
|
|
758
|
+
input = step.valueInStepText ? "_param_0" : `"${escapeNonPrintables(step.parameters[1].replaceAll('"', '\\"'))}"`;
|
|
759
|
+
line += `"${step.parameters[1]}", ${input}, _params, ${serializeOptions(options)}, this);`;
|
|
659
760
|
codeLines.push(line);
|
|
660
761
|
break;
|
|
661
762
|
}
|
|
@@ -666,7 +767,7 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
666
767
|
if (step.dataSource === "userData" || step.dataSource === "parameters") {
|
|
667
768
|
input = "_" + step.dataKey;
|
|
668
769
|
}
|
|
669
|
-
line += `${input}, _params,
|
|
770
|
+
line += `${input}, _params, ${serializeOptions(options)}, this);`;
|
|
670
771
|
if (element_name) {
|
|
671
772
|
comment = `// Set ${element_name} to ${input}`;
|
|
672
773
|
codeLines.push(escapeNonPrintables(comment));
|
|
@@ -674,6 +775,8 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
674
775
|
codeLines.push(line);
|
|
675
776
|
break;
|
|
676
777
|
}
|
|
778
|
+
|
|
779
|
+
|
|
677
780
|
case Types.CLICK_SIMPLE:
|
|
678
781
|
case Types.FILL_SIMPLE:
|
|
679
782
|
// no code need to be added
|
|
@@ -684,22 +787,6 @@ const _generateCodeFromCommand = (step, elements, userData) => {
|
|
|
684
787
|
return { codeLines, elements: elementsChanged ? elements : null, elementIdentifier, allStrategyLocators };
|
|
685
788
|
};
|
|
686
789
|
|
|
687
|
-
/**
|
|
688
|
-
* Generates a report command based on the given position.
|
|
689
|
-
* @param {"start"|"end"} position
|
|
690
|
-
*/
|
|
691
|
-
const generateReportCommand = (position, cmdId) => {
|
|
692
|
-
const codeLines = [];
|
|
693
|
-
if (position === "start") {
|
|
694
|
-
const line = `await context.web.addCommandToReport("${cmdId}", "PASSED", '{"status":"start","cmdId":"${cmdId}"}', {type:"cmdReport"},this);`;
|
|
695
|
-
codeLines.push(line);
|
|
696
|
-
} else if (position === "end") {
|
|
697
|
-
const line = `await context.web.addCommandToReport("${cmdId}", "PASSED", '{"status":"end","cmdId":"${cmdId}"}', {type:"cmdReport"},this);`;
|
|
698
|
-
codeLines.push(line);
|
|
699
|
-
}
|
|
700
|
-
return codeLines;
|
|
701
|
-
};
|
|
702
|
-
|
|
703
790
|
const generateCode = (recording, codePage, userData, projectDir, methodName) => {
|
|
704
791
|
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
705
792
|
stepsDefinitions.load(false);
|
|
@@ -722,12 +809,10 @@ const generateCode = (recording, codePage, userData, projectDir, methodName) =>
|
|
|
722
809
|
codePage = new CodePage(mjsFullPath);
|
|
723
810
|
codePage.generateModel();
|
|
724
811
|
}
|
|
725
|
-
//console.log("step found");
|
|
726
812
|
}
|
|
727
813
|
let elements = {};
|
|
728
814
|
if (!codePage) {
|
|
729
|
-
socketLogger.info("CodePage is null");
|
|
730
|
-
console.log("codePage is null");
|
|
815
|
+
socketLogger.info("CodePage is null", undefined, "generateCode");
|
|
731
816
|
} else {
|
|
732
817
|
elements = codePage.getVariableDeclarationAsObject("elements");
|
|
733
818
|
}
|
|
@@ -741,6 +826,7 @@ const generateCode = (recording, codePage, userData, projectDir, methodName) =>
|
|
|
741
826
|
if (recordingStep.type === Types.COMPLETE) {
|
|
742
827
|
return;
|
|
743
828
|
}
|
|
829
|
+
socketLogger.info(`Generating code for step: ${recordingStep.type}`, undefined, "generateCode");
|
|
744
830
|
|
|
745
831
|
// if (process.env.TEMP_RUN === "true") {
|
|
746
832
|
// codeLines.push(...generateReportCommand("start", recordingStep.cmdId));
|
|
@@ -752,9 +838,11 @@ const generateCode = (recording, codePage, userData, projectDir, methodName) =>
|
|
|
752
838
|
// codeLines.push(...generateReportCommand("end", recordingStep.cmdId));
|
|
753
839
|
// }
|
|
754
840
|
if (result.elements) {
|
|
841
|
+
socketLogger.info(`Updating elements with ${Object.keys(result.elements)}`, undefined, "generateCode");
|
|
755
842
|
elements = result.elements;
|
|
756
843
|
}
|
|
757
844
|
if (result.elementIdentifier) {
|
|
845
|
+
socketLogger.info(`Adding locator metadata for ${result.elementIdentifier}`, undefined, "generateCode");
|
|
758
846
|
locatorsMetadata[result.elementIdentifier] = result.allStrategyLocators;
|
|
759
847
|
}
|
|
760
848
|
});
|
|
@@ -791,7 +879,7 @@ const generatePageName = (url) => {
|
|
|
791
879
|
}
|
|
792
880
|
// join by _
|
|
793
881
|
return lowerCaseParts.join("_");
|
|
794
|
-
} catch
|
|
882
|
+
} catch {
|
|
795
883
|
return "default";
|
|
796
884
|
}
|
|
797
885
|
};
|
|
@@ -6,7 +6,6 @@ import os from "os";
|
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { parseStepTextParameters, toCucumberExpression, unEscapeNonPrintables } from "./utils.js";
|
|
8
8
|
import stream from "stream";
|
|
9
|
-
import { testStringForRegex } from "../recorderv3/update_feature.js";
|
|
10
9
|
import { generateTestData } from "./feature_data.js";
|
|
11
10
|
import socketLogger from "../utils/socket_logger.js";
|
|
12
11
|
class DataTable {
|
|
@@ -490,8 +489,8 @@ const scenarioResolution = async (featureFilePath) => {
|
|
|
490
489
|
let result = generateTestData(featureFilePath);
|
|
491
490
|
if (result.changed) {
|
|
492
491
|
fs.writeFileSync(tmpFeatureFilePath, result.newContent);
|
|
493
|
-
|
|
494
|
-
|
|
492
|
+
socketLogger.info("Generated fake data for feature", undefined, "scenarioResolution");
|
|
493
|
+
socketLogger.info("Variables generated:", result.variables, "scenarioResolution");
|
|
495
494
|
for (let key in result.variables) {
|
|
496
495
|
console.log(`${key}: ${result.variables[key].fake}`);
|
|
497
496
|
}
|
|
@@ -503,8 +502,7 @@ const scenarioResolution = async (featureFilePath) => {
|
|
|
503
502
|
fs.copyFileSync(featureFilePath, tmpFeatureFilePath);
|
|
504
503
|
}
|
|
505
504
|
const writable = new stream.Writable({
|
|
506
|
-
write:
|
|
507
|
-
//console.log(chunk.toString());
|
|
505
|
+
write: (chunk, encoding, next) => {
|
|
508
506
|
next();
|
|
509
507
|
},
|
|
510
508
|
});
|
|
@@ -521,23 +519,12 @@ const scenarioResolution = async (featureFilePath) => {
|
|
|
521
519
|
// load the support code upfront
|
|
522
520
|
const support = await loadSupport(runConfiguration, environment);
|
|
523
521
|
// run cucumber, using the support code we loaded already
|
|
524
|
-
await runCucumber({ ...runConfiguration, support }, environment,
|
|
525
|
-
// if (event.source) {
|
|
526
|
-
// scenarioInfo.source = event.source.data;
|
|
527
|
-
// }
|
|
528
|
-
// if (event.pickle && event.pickle.name === scenarioName) {
|
|
529
|
-
// scenarioInfo.pickle = event.pickle;
|
|
530
|
-
// }
|
|
522
|
+
await runCucumber({ ...runConfiguration, support }, environment, (event) => {
|
|
531
523
|
if (event.gherkinDocument) {
|
|
532
524
|
gherkinDocument = event.gherkinDocument;
|
|
533
525
|
}
|
|
534
|
-
//console.log(event);
|
|
535
|
-
//console.log(JSON.stringify(event, null, 2));
|
|
536
|
-
// console.log("");
|
|
537
526
|
});
|
|
538
527
|
const feature = new Feature(gherkinDocument, featureFileContent);
|
|
539
|
-
//const scenario = feature.getScenario(scenarioName);
|
|
540
|
-
//return scenario;
|
|
541
528
|
return feature;
|
|
542
529
|
} finally {
|
|
543
530
|
try {
|