@dev-blinq/cucumber_client 1.0.1309-dev → 1.0.1309-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 +106 -106
- package/bin/assets/preload/css_gen.js +10 -10
- package/bin/assets/preload/recorderv3.js +3 -1
- 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 +5 -17
- package/bin/assets/scripts/snapshot_capturer.js +153 -146
- package/bin/assets/scripts/unique_locators.js +925 -793
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +41 -0
- package/bin/assets/templates/utils_template.txt +1 -46
- package/bin/client/apiTest/apiTest.js +6 -0
- package/bin/client/cli_helpers.js +11 -13
- 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 +53 -4
- package/bin/client/code_gen/page_reflection.js +839 -906
- package/bin/client/code_gen/playwright_codeget.js +48 -14
- package/bin/client/cucumber/feature.js +89 -27
- package/bin/client/cucumber/feature_data.js +2 -2
- package/bin/client/cucumber/project_to_document.js +9 -3
- package/bin/client/cucumber/steps_definitions.js +90 -87
- package/bin/client/cucumber_selector.js +17 -1
- package/bin/client/local_agent.js +6 -5
- 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_recorder.js +167 -54
- package/bin/client/recorderv3/implemented_steps.js +74 -16
- package/bin/client/recorderv3/index.js +69 -22
- package/bin/client/recorderv3/network.js +299 -0
- package/bin/client/recorderv3/scriptTest.js +1 -1
- package/bin/client/recorderv3/services.js +4 -16
- package/bin/client/recorderv3/step_runner.js +329 -72
- package/bin/client/recorderv3/step_utils.js +574 -5
- package/bin/client/recorderv3/update_feature.js +32 -30
- package/bin/client/run_cucumber.js +5 -1
- package/bin/client/scenario_report.js +0 -5
- package/bin/client/test_scenario.js +0 -1
- package/bin/client/upload-service.js +2 -2
- package/bin/client/utils/socket_logger.js +132 -0
- package/bin/index.js +1 -0
- 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 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import url from "url";
|
|
4
4
|
import logger from "../../logger.js";
|
|
@@ -9,9 +9,424 @@ import { Step } from "../cucumber/feature.js";
|
|
|
9
9
|
import { locateDefinitionPath, StepsDefinitions } from "../cucumber/steps_definitions.js";
|
|
10
10
|
import { Recording } from "../recording.js";
|
|
11
11
|
import { generateApiCode } from "../code_gen/api_codegen.js";
|
|
12
|
+
import { tmpdir } from "os";
|
|
13
|
+
import { createHash } from "crypto";
|
|
12
14
|
|
|
13
15
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
14
16
|
|
|
17
|
+
const convertToIdentifier = (text) => {
|
|
18
|
+
// replace all invalid characters with _
|
|
19
|
+
return text.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const isVariable = (text) => {
|
|
23
|
+
if (typeof text !== "string") return false;
|
|
24
|
+
const isParametric = text.startsWith("<") && text.endsWith(">");
|
|
25
|
+
if (!isParametric) return false;
|
|
26
|
+
const l = text.length;
|
|
27
|
+
if (l < 2) return false;
|
|
28
|
+
const leftindex = text.indexOf("<");
|
|
29
|
+
const rightindex = text.indexOf(">");
|
|
30
|
+
return leftindex === 0 && rightindex === l - 1;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const extractQuotes = (text) => {
|
|
34
|
+
const stringRegex = /"([^"]*)"/g;
|
|
35
|
+
const matches = text.match(stringRegex);
|
|
36
|
+
if (!matches) return [];
|
|
37
|
+
const quotes = [];
|
|
38
|
+
for (const match of matches) {
|
|
39
|
+
const value = match.slice(1, -1);
|
|
40
|
+
quotes.push(value);
|
|
41
|
+
}
|
|
42
|
+
return quotes;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const replaceLastOccurence = (str, search, replacement) => {
|
|
46
|
+
const lastIndex = str.lastIndexOf(search);
|
|
47
|
+
if (lastIndex === -1) return str;
|
|
48
|
+
return str.substring(0, lastIndex) + replacement + str.substring(lastIndex + search.length);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const _toRecordingStep = (cmd) => {
|
|
52
|
+
switch (cmd.type) {
|
|
53
|
+
case "hover_element": {
|
|
54
|
+
return {
|
|
55
|
+
type: "hover_element",
|
|
56
|
+
element: {
|
|
57
|
+
role: cmd.role,
|
|
58
|
+
name: cmd.label,
|
|
59
|
+
},
|
|
60
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
case "click_element": {
|
|
64
|
+
return {
|
|
65
|
+
type: "click_element",
|
|
66
|
+
element: {
|
|
67
|
+
role: cmd.role,
|
|
68
|
+
name: cmd.label,
|
|
69
|
+
},
|
|
70
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
71
|
+
count: cmd.count ?? 1,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
case "context_click": {
|
|
75
|
+
return {
|
|
76
|
+
type: "context_click",
|
|
77
|
+
element: {
|
|
78
|
+
role: cmd.role,
|
|
79
|
+
name: cmd.label,
|
|
80
|
+
},
|
|
81
|
+
label: cmd.label,
|
|
82
|
+
value: cmd.value,
|
|
83
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
84
|
+
text: cmd.text,
|
|
85
|
+
count: cmd.count ?? 1,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
case "parameterized_click": {
|
|
89
|
+
return {
|
|
90
|
+
type: "parameterized_click",
|
|
91
|
+
element: {
|
|
92
|
+
role: cmd.role,
|
|
93
|
+
name: cmd.label,
|
|
94
|
+
},
|
|
95
|
+
label: cmd.label,
|
|
96
|
+
value: cmd.value,
|
|
97
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
98
|
+
count: cmd.count ?? 1,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
case "fill_element": {
|
|
102
|
+
return {
|
|
103
|
+
type: "fill_element",
|
|
104
|
+
element: {
|
|
105
|
+
role: cmd.role,
|
|
106
|
+
name: cmd.label,
|
|
107
|
+
},
|
|
108
|
+
parameters: [cmd.value, cmd.enter ?? false],
|
|
109
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
case "select_combobox": {
|
|
113
|
+
return {
|
|
114
|
+
type: "select_combobox",
|
|
115
|
+
element: {
|
|
116
|
+
role: "combobox",
|
|
117
|
+
name: cmd.label,
|
|
118
|
+
},
|
|
119
|
+
selectMode: "select",
|
|
120
|
+
parameters: [cmd.value],
|
|
121
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
case "verify_page_contains_text": {
|
|
125
|
+
return {
|
|
126
|
+
type: "verify_page_contains_text",
|
|
127
|
+
parameters: [cmd.value, cmd.isRegex],
|
|
128
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
case "verify_element_contains_text": {
|
|
132
|
+
return {
|
|
133
|
+
type: "verify_element_contains_text",
|
|
134
|
+
element: {
|
|
135
|
+
role: cmd.role,
|
|
136
|
+
name: cmd.label,
|
|
137
|
+
},
|
|
138
|
+
parameters: [cmd.value, cmd.climb],
|
|
139
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
case "close_page": {
|
|
143
|
+
return {
|
|
144
|
+
type: "close_page",
|
|
145
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case "check_element": {
|
|
149
|
+
return {
|
|
150
|
+
type: "check_element",
|
|
151
|
+
element: {
|
|
152
|
+
role: cmd.role,
|
|
153
|
+
name: cmd.label,
|
|
154
|
+
},
|
|
155
|
+
check: cmd.check,
|
|
156
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
case "press_key": {
|
|
160
|
+
return {
|
|
161
|
+
type: "press_key",
|
|
162
|
+
element: {
|
|
163
|
+
role: cmd.role,
|
|
164
|
+
name: cmd.label,
|
|
165
|
+
},
|
|
166
|
+
key: cmd.value,
|
|
167
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
case "load_user": {
|
|
171
|
+
return {
|
|
172
|
+
type: "load_data",
|
|
173
|
+
parameters: ["users", cmd.value],
|
|
174
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
case "load_csv": {
|
|
178
|
+
return {
|
|
179
|
+
type: "load_data",
|
|
180
|
+
parameters: ["csv", `${cmd.label}:${cmd.value}`],
|
|
181
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
case "set_date_time": {
|
|
185
|
+
return {
|
|
186
|
+
type: "set_date_time",
|
|
187
|
+
element: {
|
|
188
|
+
role: cmd.role,
|
|
189
|
+
name: cmd.label,
|
|
190
|
+
},
|
|
191
|
+
parameters: [cmd.value],
|
|
192
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
case "set_input": {
|
|
196
|
+
return {
|
|
197
|
+
type: "set_input",
|
|
198
|
+
element: {
|
|
199
|
+
role: cmd.role,
|
|
200
|
+
name: cmd.label,
|
|
201
|
+
},
|
|
202
|
+
value: cmd.value,
|
|
203
|
+
parameters: [cmd.value],
|
|
204
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
case "extract_attribute": {
|
|
208
|
+
return {
|
|
209
|
+
type: "extract_attribute",
|
|
210
|
+
element: {
|
|
211
|
+
role: cmd.role,
|
|
212
|
+
name: cmd.label,
|
|
213
|
+
},
|
|
214
|
+
parameters: [cmd.selectedField, cmd.variableName],
|
|
215
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
216
|
+
regex: cmd.regex,
|
|
217
|
+
trimSpaces: cmd.trimSpaces,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
case "extract_property": {
|
|
221
|
+
return {
|
|
222
|
+
type: "extract_property",
|
|
223
|
+
element: {
|
|
224
|
+
role: cmd.role,
|
|
225
|
+
name: cmd.label,
|
|
226
|
+
},
|
|
227
|
+
parameters: [cmd.selectedField, cmd.variableName],
|
|
228
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
229
|
+
regex: cmd.regex,
|
|
230
|
+
trimSpaces: cmd.trimSpaces,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
case "verify_element_attribute": {
|
|
234
|
+
return {
|
|
235
|
+
type: "verify_element_attribute",
|
|
236
|
+
element: {
|
|
237
|
+
role: cmd.role,
|
|
238
|
+
name: cmd.label,
|
|
239
|
+
},
|
|
240
|
+
parameters: [cmd.selectedField, cmd.value],
|
|
241
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
case "verify_element_property": {
|
|
245
|
+
return {
|
|
246
|
+
type: "verify_element_property",
|
|
247
|
+
element: {
|
|
248
|
+
role: cmd.role,
|
|
249
|
+
name: cmd.label,
|
|
250
|
+
},
|
|
251
|
+
parameters: [cmd.selectedField, cmd.value],
|
|
252
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
case "conditional_wait": {
|
|
256
|
+
return {
|
|
257
|
+
type: "conditional_wait",
|
|
258
|
+
element: {
|
|
259
|
+
role: cmd.role,
|
|
260
|
+
name: cmd.label,
|
|
261
|
+
},
|
|
262
|
+
parameters: [cmd.timeout, cmd.selectedField, cmd.value],
|
|
263
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
case "navigate": {
|
|
267
|
+
return {
|
|
268
|
+
type: "navigate",
|
|
269
|
+
parameters: [cmd.value],
|
|
270
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
case "browser_go_back": {
|
|
274
|
+
return {
|
|
275
|
+
type: "browser_go_back",
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
case "browser_go_forward": {
|
|
279
|
+
return {
|
|
280
|
+
type: "browser_go_forward",
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
case "set_input_files": {
|
|
284
|
+
return {
|
|
285
|
+
type: "set_input_files",
|
|
286
|
+
element: {
|
|
287
|
+
role: cmd.role,
|
|
288
|
+
name: cmd.label,
|
|
289
|
+
},
|
|
290
|
+
parameters: [cmd.files],
|
|
291
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
case "verify_page_snapshot": {
|
|
295
|
+
return {
|
|
296
|
+
type: "verify_page_snapshot",
|
|
297
|
+
parameters: [cmd.value],
|
|
298
|
+
selectors: cmd.selectors,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
default: {
|
|
302
|
+
return {
|
|
303
|
+
type: cmd.type,
|
|
304
|
+
parameters: [cmd.value],
|
|
305
|
+
lastKnownUrlPath: cmd.lastKnownUrlPath,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
function getBestStrategy(allStrategyLocators) {
|
|
312
|
+
const orderedPriorities = ["custom", "context", "basic", "text_with_index", "ignore_digit", "no_text"];
|
|
313
|
+
for (const strategy of orderedPriorities) {
|
|
314
|
+
if (allStrategyLocators[strategy] && allStrategyLocators[strategy].length > 0) {
|
|
315
|
+
return strategy;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const _parameterizeLocators = (locators, replacementFromValue, replacementToValue) => {
|
|
322
|
+
for (const loc of locators) {
|
|
323
|
+
if (loc?.css?.includes(replacementFromValue)) {
|
|
324
|
+
loc.css = loc.css.replaceAll(replacementFromValue, replacementToValue);
|
|
325
|
+
}
|
|
326
|
+
if (loc?.text?.includes(replacementFromValue)) {
|
|
327
|
+
loc.text = loc.text.replaceAll(replacementFromValue, replacementToValue);
|
|
328
|
+
}
|
|
329
|
+
if (loc?.climb && typeof loc.climb === "string" && loc.climb?.includes(replacementFromValue)) {
|
|
330
|
+
loc.climb = loc.climb.replaceAll(replacementFromValue, replacementToValue);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return locators;
|
|
334
|
+
};
|
|
335
|
+
const parameterizeLocators = ({ cmd, locs, isValueVariable, isTextVariable, parametersMap }) => {
|
|
336
|
+
if (isValueVariable) {
|
|
337
|
+
const variable = cmd.value.slice(1, -1);
|
|
338
|
+
const val = parametersMap[variable];
|
|
339
|
+
const replacementFromValue = val.trim();
|
|
340
|
+
const replacementToValue = `{${variable}}`;
|
|
341
|
+
locs = _parameterizeLocators(locs, replacementFromValue, replacementToValue);
|
|
342
|
+
}
|
|
343
|
+
if (isTextVariable) {
|
|
344
|
+
const variable = cmd.text.slice(1, -1);
|
|
345
|
+
const val = parametersMap[variable];
|
|
346
|
+
const replacementFromValue = val.trim();
|
|
347
|
+
const replacementToValue = `{${variable}}`;
|
|
348
|
+
locs = _parameterizeLocators(locs, replacementFromValue, replacementToValue);
|
|
349
|
+
}
|
|
350
|
+
return locs;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
//TODO: IMPORTAN
|
|
354
|
+
export const toRecordingStep = (cmd, parametersMap) => {
|
|
355
|
+
if (cmd.type === "api") {
|
|
356
|
+
return {
|
|
357
|
+
type: "api",
|
|
358
|
+
value: cmd.value,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
const step = _toRecordingStep(cmd);
|
|
362
|
+
const cmdID = {
|
|
363
|
+
cmdId: cmd.id,
|
|
364
|
+
};
|
|
365
|
+
Object.assign(step, cmdID);
|
|
366
|
+
|
|
367
|
+
const locatorsObject = JSON.parse(JSON.stringify(cmd.locators ?? null));
|
|
368
|
+
|
|
369
|
+
if (!locatorsObject) return step;
|
|
370
|
+
|
|
371
|
+
const element_name = cmd?.locators?.element_name ?? `${cmd.label} ${cmd.role ?? "Text"}`;
|
|
372
|
+
locatorsObject.element_name = element_name;
|
|
373
|
+
|
|
374
|
+
const isValueVariable = isVariable(cmd.value);
|
|
375
|
+
const isTextVariable = isVariable(cmd.text);
|
|
376
|
+
const allStrategyLocators = JSON.parse(JSON.stringify(cmd?.allStrategyLocators ?? null));
|
|
377
|
+
step.locators = locatorsObject;
|
|
378
|
+
step.allStrategyLocators = allStrategyLocators;
|
|
379
|
+
step.isLocatorsAssigned = true;
|
|
380
|
+
|
|
381
|
+
if (!isValueVariable && !isTextVariable) {
|
|
382
|
+
return step;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (isValueVariable) {
|
|
386
|
+
step.dataSource = "parameters";
|
|
387
|
+
step.dataKey = convertToIdentifier(cmd.value.slice(1, -1));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (!allStrategyLocators) {
|
|
391
|
+
let locs = locatorsObject.locators;
|
|
392
|
+
locs = parameterizeLocators({
|
|
393
|
+
cmd,
|
|
394
|
+
locs,
|
|
395
|
+
isValueVariable,
|
|
396
|
+
isTextVariable,
|
|
397
|
+
parametersMap,
|
|
398
|
+
});
|
|
399
|
+
locatorsObject.locators = locs;
|
|
400
|
+
return {
|
|
401
|
+
...step,
|
|
402
|
+
locators: locatorsObject,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
for (const key in allStrategyLocators) {
|
|
407
|
+
if (key === "strategy") continue;
|
|
408
|
+
if (key === "no_text" || key === "custom") continue;
|
|
409
|
+
const locators = allStrategyLocators[key];
|
|
410
|
+
if (locators.length === 0) continue;
|
|
411
|
+
parameterizeLocators({
|
|
412
|
+
cmd,
|
|
413
|
+
locs: locators,
|
|
414
|
+
isValueVariable,
|
|
415
|
+
isTextVariable,
|
|
416
|
+
parametersMap,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
locatorsObject.locators = allStrategyLocators[allStrategyLocators.strategy] ?? locatorsObject.locators;
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
...step,
|
|
424
|
+
locators: locatorsObject,
|
|
425
|
+
allStrategyLocators,
|
|
426
|
+
isLocatorsAssigned: true,
|
|
427
|
+
};
|
|
428
|
+
};
|
|
429
|
+
|
|
15
430
|
export const toMethodName = (str) => {
|
|
16
431
|
// Remove any non-word characters (excluding underscore) and trim spaces
|
|
17
432
|
let cleanStr = str.trim().replace(/[^\w\s]/gi, "");
|
|
@@ -68,22 +483,82 @@ function makeStepTextUnique(step, stepsDefinitions) {
|
|
|
68
483
|
step.text = stepText;
|
|
69
484
|
}
|
|
70
485
|
|
|
71
|
-
export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions }) {
|
|
72
|
-
|
|
486
|
+
export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions, parametersMap }) {
|
|
487
|
+
if (step.commands && Array.isArray(step.commands)) {
|
|
488
|
+
step.commands = step.commands.map((cmd) => toRecordingStep(cmd, parametersMap));
|
|
489
|
+
}
|
|
490
|
+
let routesPath = path.join(tmpdir(), "blinq_temp_routes");
|
|
491
|
+
|
|
492
|
+
if (process.env.TEMP_RUN === "true") {
|
|
493
|
+
if (existsSync(routesPath)) {
|
|
494
|
+
rmSync(routesPath, { recursive: true });
|
|
495
|
+
}
|
|
496
|
+
mkdirSync(routesPath, { recursive: true });
|
|
497
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
498
|
+
} else {
|
|
499
|
+
if (existsSync(routesPath)) {
|
|
500
|
+
// remove the folder
|
|
501
|
+
try {
|
|
502
|
+
rmSync(routesPath, { recursive: true });
|
|
503
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
504
|
+
} catch (error) {
|
|
505
|
+
console.error("Error removing temp_routes folder", error);
|
|
506
|
+
}
|
|
507
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
508
|
+
if (!existsSync(routesPath)) {
|
|
509
|
+
mkdirSync(routesPath, { recursive: true });
|
|
510
|
+
}
|
|
511
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
73
515
|
if (step.isImplementedWhileRecording && !process.env.TEMP_RUN) {
|
|
74
516
|
return;
|
|
75
517
|
}
|
|
518
|
+
|
|
76
519
|
if (step.isImplemented && step.shouldOverride) {
|
|
77
520
|
let stepDef = stepsDefinitions.findMatchingStep(step.text);
|
|
78
521
|
codePage = getCodePage(stepDef.file);
|
|
79
522
|
} else {
|
|
80
523
|
const isUtilStep = makeStepTextUnique(step, stepsDefinitions);
|
|
524
|
+
|
|
81
525
|
if (isUtilStep) {
|
|
82
526
|
return;
|
|
83
527
|
}
|
|
84
528
|
}
|
|
529
|
+
|
|
530
|
+
routesPath = path.join(tmpdir(), "blinq_temp_routes");
|
|
531
|
+
if (process.env.TEMP_RUN === "true") {
|
|
532
|
+
console.log("Save routes in temp folder for running:", routesPath);
|
|
533
|
+
if (existsSync(routesPath)) {
|
|
534
|
+
console.log("Removing existing temp_routes_folder:", routesPath);
|
|
535
|
+
rmSync(routesPath, { recursive: true });
|
|
536
|
+
}
|
|
537
|
+
mkdirSync(routesPath, { recursive: true });
|
|
538
|
+
console.log("Created temp_routes_folder:", routesPath);
|
|
539
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
540
|
+
} else {
|
|
541
|
+
console.log("Saving routes in project directory:", projectDir);
|
|
542
|
+
if (existsSync(routesPath)) {
|
|
543
|
+
// remove the folder
|
|
544
|
+
try {
|
|
545
|
+
rmSync(routesPath, { recursive: true });
|
|
546
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
547
|
+
} catch (error) {
|
|
548
|
+
console.error("Error removing temp_routes folder", error);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
552
|
+
console.log("Saving routes to:", routesPath);
|
|
553
|
+
if (!existsSync(routesPath)) {
|
|
554
|
+
mkdirSync(routesPath, { recursive: true });
|
|
555
|
+
}
|
|
556
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
557
|
+
}
|
|
558
|
+
|
|
85
559
|
cucumberStep.text = step.text;
|
|
86
560
|
const recording = new Recording();
|
|
561
|
+
|
|
87
562
|
const steps = step.commands;
|
|
88
563
|
|
|
89
564
|
recording.loadFromObject({ steps, step: cucumberStep });
|
|
@@ -108,6 +583,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
108
583
|
isStaticToken,
|
|
109
584
|
status,
|
|
110
585
|
} = step.commands[0].value;
|
|
586
|
+
|
|
111
587
|
const result = await generateApiCode(
|
|
112
588
|
{
|
|
113
589
|
url,
|
|
@@ -132,6 +608,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
132
608
|
step.keyword,
|
|
133
609
|
stepsDefinitions
|
|
134
610
|
);
|
|
611
|
+
|
|
135
612
|
if (!step.isImplemented) {
|
|
136
613
|
stepsDefinitions.addStep({
|
|
137
614
|
name: step.text,
|
|
@@ -139,6 +616,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
139
616
|
source: "recorder",
|
|
140
617
|
});
|
|
141
618
|
}
|
|
619
|
+
|
|
142
620
|
cucumberStep.methodName = result.methodName;
|
|
143
621
|
return result.codePage;
|
|
144
622
|
} else {
|
|
@@ -156,12 +634,18 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
156
634
|
if (step.commands && step.commands.length > 0 && step.commands[0]) {
|
|
157
635
|
path = step.commands[0].lastKnownUrlPath;
|
|
158
636
|
}
|
|
637
|
+
let protect = false;
|
|
638
|
+
if (step.commands && step.commands.length > 0 && step.commands[0].type) {
|
|
639
|
+
if (step.commands[0].type === "verify_element_property" || step.commands[0].type === "conditional_wait") {
|
|
640
|
+
protect = true;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
159
643
|
const infraResult = codePage.addInfraCommand(
|
|
160
644
|
methodName,
|
|
161
645
|
description,
|
|
162
646
|
cucumberStep.getVariablesList(),
|
|
163
647
|
generateCodeResult.codeLines,
|
|
164
|
-
|
|
648
|
+
protect,
|
|
165
649
|
"recorder",
|
|
166
650
|
path
|
|
167
651
|
);
|
|
@@ -183,6 +667,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
183
667
|
}
|
|
184
668
|
|
|
185
669
|
codePage.removeUnusedElements();
|
|
670
|
+
codePage.mergeSimilarElements();
|
|
186
671
|
cucumberStep.methodName = methodName;
|
|
187
672
|
if (generateCodeResult.locatorsMetadata) {
|
|
188
673
|
codePage.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
|
|
@@ -312,6 +797,12 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
312
797
|
const utilsTemplateFilePath = path.join(__dirname, "../../assets", "templates", "utils_template.txt");
|
|
313
798
|
const utilsContent = readFileSync(utilsTemplateFilePath, "utf8");
|
|
314
799
|
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
800
|
+
const hooksTemplateFilePath = path.join(__dirname, "../../assets", "templates", "_hooks_template.txt");
|
|
801
|
+
if (existsSync(hooksTemplateFilePath)) {
|
|
802
|
+
const hooksFilePath = path.join(stepDefinitionFolderPath, "_hooks.mjs");
|
|
803
|
+
const hooksContent = readFileSync(hooksTemplateFilePath, "utf8");
|
|
804
|
+
writeFileSync(hooksFilePath, hooksContent, "utf8");
|
|
805
|
+
}
|
|
315
806
|
const steps = scenario.steps;
|
|
316
807
|
|
|
317
808
|
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
@@ -327,6 +818,35 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
327
818
|
}
|
|
328
819
|
}
|
|
329
820
|
if ((step.isImplemented && !step.shouldOverride) || step.commands.length === 0) {
|
|
821
|
+
let routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
822
|
+
if (process.env.TEMP_RUN === "true") {
|
|
823
|
+
console.log("Save routes in temp folder for running:", routesPath);
|
|
824
|
+
if (existsSync(routesPath)) {
|
|
825
|
+
console.log("Removing existing temp_routes_folder:", routesPath);
|
|
826
|
+
routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
827
|
+
rmSync(routesPath, { recursive: true });
|
|
828
|
+
}
|
|
829
|
+
mkdirSync(routesPath, { recursive: true });
|
|
830
|
+
console.log("Created temp_routes_folder:", routesPath);
|
|
831
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
832
|
+
} else {
|
|
833
|
+
console.log("Saving routes in project directory:", projectDir);
|
|
834
|
+
if (existsSync(routesPath)) {
|
|
835
|
+
// remove the folder
|
|
836
|
+
try {
|
|
837
|
+
rmSync(routesPath, { recursive: true });
|
|
838
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
839
|
+
} catch (error) {
|
|
840
|
+
console.error("Error removing temp_routes folder", error);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
844
|
+
console.log("Saving routes to:", routesPath);
|
|
845
|
+
if (!existsSync(routesPath)) {
|
|
846
|
+
mkdirSync(routesPath, { recursive: true });
|
|
847
|
+
}
|
|
848
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
849
|
+
}
|
|
330
850
|
continue;
|
|
331
851
|
}
|
|
332
852
|
const cucumberStep = getCucumberStep({ step });
|
|
@@ -334,7 +854,14 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
334
854
|
const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
|
|
335
855
|
// path.join(stepDefinitionFolderPath, pageName + "_page.mjs");
|
|
336
856
|
let codePage = getCodePage(stepDefsFilePath);
|
|
337
|
-
codePage = await saveRecording({
|
|
857
|
+
codePage = await saveRecording({
|
|
858
|
+
step,
|
|
859
|
+
cucumberStep,
|
|
860
|
+
codePage,
|
|
861
|
+
projectDir,
|
|
862
|
+
stepsDefinitions,
|
|
863
|
+
parametersMap: scenario.parametersMap,
|
|
864
|
+
});
|
|
338
865
|
if (!codePage) {
|
|
339
866
|
continue;
|
|
340
867
|
}
|
|
@@ -345,3 +872,45 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
345
872
|
}
|
|
346
873
|
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
347
874
|
}
|
|
875
|
+
|
|
876
|
+
export function saveRoutes({ step, folderPath }) {
|
|
877
|
+
const routeItems = step.routeItems;
|
|
878
|
+
if (!routeItems || routeItems.length === 0) {
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
const cucumberStep = getCucumberStep({ step });
|
|
882
|
+
const template = cucumberStep.getTemplate();
|
|
883
|
+
const stepNameHash = createHash("sha256").update(template).digest("hex");
|
|
884
|
+
console.log("Saving routes for step:", step.text, "with hash:", stepNameHash);
|
|
885
|
+
|
|
886
|
+
const routeItemsWithFilters = routeItems.map((routeItem) => {
|
|
887
|
+
const oldFilters = routeItem.filters;
|
|
888
|
+
const queryParamsObject = {};
|
|
889
|
+
oldFilters.queryParams.forEach((queryParam) => {
|
|
890
|
+
queryParamsObject[queryParam.key] = queryParam.value;
|
|
891
|
+
});
|
|
892
|
+
const newFilters = { path: oldFilters.path, method: oldFilters.method, queryParams: queryParamsObject };
|
|
893
|
+
return {
|
|
894
|
+
...routeItem,
|
|
895
|
+
filters: newFilters,
|
|
896
|
+
};
|
|
897
|
+
});
|
|
898
|
+
|
|
899
|
+
const routesFilePath = path.join(folderPath, stepNameHash + ".json");
|
|
900
|
+
console.log("Routes file path:", routesFilePath);
|
|
901
|
+
const routesData = {
|
|
902
|
+
template,
|
|
903
|
+
routes: routeItemsWithFilters,
|
|
904
|
+
};
|
|
905
|
+
console.log("Routes data to save:", routesData);
|
|
906
|
+
|
|
907
|
+
if (!existsSync(folderPath)) {
|
|
908
|
+
mkdirSync(folderPath, { recursive: true });
|
|
909
|
+
}
|
|
910
|
+
try {
|
|
911
|
+
writeFileSync(routesFilePath, JSON.stringify(routesData, null, 2), "utf8");
|
|
912
|
+
console.log("Saved routes to", routesFilePath);
|
|
913
|
+
} catch (error) {
|
|
914
|
+
console.error("Failed to save routes to", routesFilePath, "Error:", error);
|
|
915
|
+
}
|
|
916
|
+
}
|