@dev-blinq/cucumber_client 1.0.1283-dev → 1.0.1283-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 -170
- package/bin/assets/scripts/event_utils.js +94 -94
- package/bin/assets/scripts/pw.js +2050 -1949
- package/bin/assets/scripts/recorder.js +7 -4
- package/bin/assets/scripts/snapshot_capturer.js +153 -146
- package/bin/assets/scripts/unique_locators.js +830 -815
- package/bin/assets/scripts/yaml.js +796 -783
- package/bin/assets/templates/_hooks_template.txt +37 -0
- package/bin/assets/templates/page_template.txt +2 -16
- 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 -902
- package/bin/client/code_gen/playwright_codeget.js +43 -12
- 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 -84
- 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 +170 -60
- package/bin/client/recorderv3/implemented_steps.js +74 -16
- package/bin/client/recorderv3/index.js +57 -25
- 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 +331 -68
- package/bin/client/recorderv3/step_utils.js +574 -7
- 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 +22 -13
|
@@ -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,420 @@ 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
|
+
const isValueVariable = isVariable(cmd.value);
|
|
371
|
+
const isTextVariable = isVariable(cmd.text);
|
|
372
|
+
const allStrategyLocators = JSON.parse(JSON.stringify(cmd?.allStrategyLocators ?? null));
|
|
373
|
+
step.locators = locatorsObject;
|
|
374
|
+
step.allStrategyLocators = allStrategyLocators;
|
|
375
|
+
step.isLocatorsAssigned = true;
|
|
376
|
+
|
|
377
|
+
if (!isValueVariable && !isTextVariable) {
|
|
378
|
+
return step;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (isValueVariable) {
|
|
382
|
+
step.dataSource = "parameters";
|
|
383
|
+
step.dataKey = convertToIdentifier(cmd.value.slice(1, -1));
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (!allStrategyLocators) {
|
|
387
|
+
let locs = locatorsObject.locators;
|
|
388
|
+
locs = parameterizeLocators({
|
|
389
|
+
cmd,
|
|
390
|
+
locs,
|
|
391
|
+
isValueVariable,
|
|
392
|
+
isTextVariable,
|
|
393
|
+
parametersMap,
|
|
394
|
+
});
|
|
395
|
+
locatorsObject.locators = locs;
|
|
396
|
+
return {
|
|
397
|
+
...step,
|
|
398
|
+
locators: locatorsObject,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
for (const key in allStrategyLocators) {
|
|
403
|
+
if (key === "strategy") continue;
|
|
404
|
+
if (key === "no_text" || key === "custom") continue;
|
|
405
|
+
const locators = allStrategyLocators[key];
|
|
406
|
+
if (locators.length === 0) continue;
|
|
407
|
+
parameterizeLocators({
|
|
408
|
+
cmd,
|
|
409
|
+
locs: locators,
|
|
410
|
+
isValueVariable,
|
|
411
|
+
isTextVariable,
|
|
412
|
+
parametersMap,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
locatorsObject.locators = allStrategyLocators[allStrategyLocators.strategy] ?? locatorsObject.locators;
|
|
417
|
+
|
|
418
|
+
return {
|
|
419
|
+
...step,
|
|
420
|
+
locators: locatorsObject,
|
|
421
|
+
allStrategyLocators,
|
|
422
|
+
isLocatorsAssigned: true,
|
|
423
|
+
};
|
|
424
|
+
};
|
|
425
|
+
|
|
15
426
|
export const toMethodName = (str) => {
|
|
16
427
|
// Remove any non-word characters (excluding underscore) and trim spaces
|
|
17
428
|
let cleanStr = str.trim().replace(/[^\w\s]/gi, "");
|
|
@@ -68,22 +479,79 @@ function makeStepTextUnique(step, stepsDefinitions) {
|
|
|
68
479
|
step.text = stepText;
|
|
69
480
|
}
|
|
70
481
|
|
|
71
|
-
export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions }) {
|
|
72
|
-
|
|
482
|
+
export async function saveRecording({ step, cucumberStep, codePage, projectDir, stepsDefinitions, parametersMap }) {
|
|
483
|
+
let routesPath = path.join(tmpdir(), "blinq_temp_routes");
|
|
484
|
+
|
|
485
|
+
if (process.env.TEMP_RUN === "true") {
|
|
486
|
+
if (existsSync(routesPath)) {
|
|
487
|
+
rmSync(routesPath, { recursive: true });
|
|
488
|
+
}
|
|
489
|
+
mkdirSync(routesPath, { recursive: true });
|
|
490
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
491
|
+
} else {
|
|
492
|
+
if (existsSync(routesPath)) {
|
|
493
|
+
// remove the folder
|
|
494
|
+
try {
|
|
495
|
+
rmSync(routesPath, { recursive: true });
|
|
496
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
497
|
+
} catch (error) {
|
|
498
|
+
console.error("Error removing temp_routes folder", error);
|
|
499
|
+
}
|
|
500
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
501
|
+
if (!existsSync(routesPath)) {
|
|
502
|
+
mkdirSync(routesPath, { recursive: true });
|
|
503
|
+
}
|
|
504
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
73
508
|
if (step.isImplementedWhileRecording && !process.env.TEMP_RUN) {
|
|
74
509
|
return;
|
|
75
510
|
}
|
|
511
|
+
|
|
76
512
|
if (step.isImplemented && step.shouldOverride) {
|
|
77
513
|
let stepDef = stepsDefinitions.findMatchingStep(step.text);
|
|
78
514
|
codePage = getCodePage(stepDef.file);
|
|
79
515
|
} else {
|
|
80
516
|
const isUtilStep = makeStepTextUnique(step, stepsDefinitions);
|
|
517
|
+
|
|
81
518
|
if (isUtilStep) {
|
|
82
519
|
return;
|
|
83
520
|
}
|
|
84
521
|
}
|
|
522
|
+
|
|
523
|
+
routesPath = path.join(tmpdir(), "blinq_temp_routes");
|
|
524
|
+
if (process.env.TEMP_RUN === "true") {
|
|
525
|
+
console.log("Save routes in temp folder for running:", routesPath);
|
|
526
|
+
if (existsSync(routesPath)) {
|
|
527
|
+
console.log("Removing existing temp_routes_folder:", routesPath);
|
|
528
|
+
rmSync(routesPath, { recursive: true });
|
|
529
|
+
}
|
|
530
|
+
mkdirSync(routesPath, { recursive: true });
|
|
531
|
+
console.log("Created temp_routes_folder:", routesPath);
|
|
532
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
533
|
+
} else {
|
|
534
|
+
console.log("Saving routes in project directory:", projectDir);
|
|
535
|
+
if (existsSync(routesPath)) {
|
|
536
|
+
// remove the folder
|
|
537
|
+
try {
|
|
538
|
+
rmSync(routesPath, { recursive: true });
|
|
539
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
console.error("Error removing temp_routes folder", error);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
545
|
+
console.log("Saving routes to:", routesPath);
|
|
546
|
+
if (!existsSync(routesPath)) {
|
|
547
|
+
mkdirSync(routesPath, { recursive: true });
|
|
548
|
+
}
|
|
549
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
550
|
+
}
|
|
551
|
+
|
|
85
552
|
cucumberStep.text = step.text;
|
|
86
553
|
const recording = new Recording();
|
|
554
|
+
step.commands = step.commands.map((cmd) => toRecordingStep(cmd, parametersMap));
|
|
87
555
|
const steps = step.commands;
|
|
88
556
|
|
|
89
557
|
recording.loadFromObject({ steps, step: cucumberStep });
|
|
@@ -108,6 +576,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
108
576
|
isStaticToken,
|
|
109
577
|
status,
|
|
110
578
|
} = step.commands[0].value;
|
|
579
|
+
|
|
111
580
|
const result = await generateApiCode(
|
|
112
581
|
{
|
|
113
582
|
url,
|
|
@@ -132,6 +601,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
132
601
|
step.keyword,
|
|
133
602
|
stepsDefinitions
|
|
134
603
|
);
|
|
604
|
+
|
|
135
605
|
if (!step.isImplemented) {
|
|
136
606
|
stepsDefinitions.addStep({
|
|
137
607
|
name: step.text,
|
|
@@ -139,6 +609,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
139
609
|
source: "recorder",
|
|
140
610
|
});
|
|
141
611
|
}
|
|
612
|
+
|
|
142
613
|
cucumberStep.methodName = result.methodName;
|
|
143
614
|
return result.codePage;
|
|
144
615
|
} else {
|
|
@@ -156,17 +627,29 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
156
627
|
if (step.commands && step.commands.length > 0 && step.commands[0]) {
|
|
157
628
|
path = step.commands[0].lastKnownUrlPath;
|
|
158
629
|
}
|
|
630
|
+
let protect = false;
|
|
631
|
+
if (step.commands && step.commands.length > 0 && step.commands[0].type) {
|
|
632
|
+
if (step.commands[0].type === "verify_element_property" || step.commands[0].type === "conditional_wait") {
|
|
633
|
+
protect = true;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
159
636
|
const infraResult = codePage.addInfraCommand(
|
|
160
637
|
methodName,
|
|
161
638
|
description,
|
|
162
639
|
cucumberStep.getVariablesList(),
|
|
163
640
|
generateCodeResult.codeLines,
|
|
164
|
-
|
|
641
|
+
protect,
|
|
165
642
|
"recorder",
|
|
166
643
|
path
|
|
167
644
|
);
|
|
168
645
|
const keyword = (cucumberStep.keywordAlias ?? cucumberStep.keyword).trim();
|
|
169
|
-
const stepResult = codePage.addCucumberStep(
|
|
646
|
+
const stepResult = codePage.addCucumberStep(
|
|
647
|
+
keyword,
|
|
648
|
+
cucumberStep.getTemplate(),
|
|
649
|
+
methodName,
|
|
650
|
+
steps.length,
|
|
651
|
+
step.finalTimeout
|
|
652
|
+
);
|
|
170
653
|
|
|
171
654
|
if (!step.isImplemented) {
|
|
172
655
|
stepsDefinitions.addStep({
|
|
@@ -177,6 +660,7 @@ export async function saveRecording({ step, cucumberStep, codePage, projectDir,
|
|
|
177
660
|
}
|
|
178
661
|
|
|
179
662
|
codePage.removeUnusedElements();
|
|
663
|
+
codePage.mergeSimilarElements();
|
|
180
664
|
cucumberStep.methodName = methodName;
|
|
181
665
|
if (generateCodeResult.locatorsMetadata) {
|
|
182
666
|
codePage.addLocatorsMetadata(generateCodeResult.locatorsMetadata);
|
|
@@ -306,6 +790,12 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
306
790
|
const utilsTemplateFilePath = path.join(__dirname, "../../assets", "templates", "utils_template.txt");
|
|
307
791
|
const utilsContent = readFileSync(utilsTemplateFilePath, "utf8");
|
|
308
792
|
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
793
|
+
const hooksTemplateFilePath = path.join(__dirname, "../../assets", "templates", "_hooks_template.txt");
|
|
794
|
+
if (existsSync(hooksTemplateFilePath)) {
|
|
795
|
+
const hooksFilePath = path.join(stepDefinitionFolderPath, "_hooks.mjs");
|
|
796
|
+
const hooksContent = readFileSync(hooksTemplateFilePath, "utf8");
|
|
797
|
+
writeFileSync(hooksFilePath, hooksContent, "utf8");
|
|
798
|
+
}
|
|
309
799
|
const steps = scenario.steps;
|
|
310
800
|
|
|
311
801
|
const stepsDefinitions = new StepsDefinitions(projectDir);
|
|
@@ -321,6 +811,35 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
321
811
|
}
|
|
322
812
|
}
|
|
323
813
|
if ((step.isImplemented && !step.shouldOverride) || step.commands.length === 0) {
|
|
814
|
+
let routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
815
|
+
if (process.env.TEMP_RUN === "true") {
|
|
816
|
+
console.log("Save routes in temp folder for running:", routesPath);
|
|
817
|
+
if (existsSync(routesPath)) {
|
|
818
|
+
console.log("Removing existing temp_routes_folder:", routesPath);
|
|
819
|
+
routesPath = path.join(tmpdir(), `blinq_temp_routes`);
|
|
820
|
+
rmSync(routesPath, { recursive: true });
|
|
821
|
+
}
|
|
822
|
+
mkdirSync(routesPath, { recursive: true });
|
|
823
|
+
console.log("Created temp_routes_folder:", routesPath);
|
|
824
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
825
|
+
} else {
|
|
826
|
+
console.log("Saving routes in project directory:", projectDir);
|
|
827
|
+
if (existsSync(routesPath)) {
|
|
828
|
+
// remove the folder
|
|
829
|
+
try {
|
|
830
|
+
rmSync(routesPath, { recursive: true });
|
|
831
|
+
console.log("Removed temp_routes_folder:", routesPath);
|
|
832
|
+
} catch (error) {
|
|
833
|
+
console.error("Error removing temp_routes folder", error);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
routesPath = path.join(projectDir, "data", "routes");
|
|
837
|
+
console.log("Saving routes to:", routesPath);
|
|
838
|
+
if (!existsSync(routesPath)) {
|
|
839
|
+
mkdirSync(routesPath, { recursive: true });
|
|
840
|
+
}
|
|
841
|
+
saveRoutes({ step, folderPath: routesPath });
|
|
842
|
+
}
|
|
324
843
|
continue;
|
|
325
844
|
}
|
|
326
845
|
const cucumberStep = getCucumberStep({ step });
|
|
@@ -328,8 +847,14 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
328
847
|
const stepDefsFilePath = locateDefinitionPath(featureFolder, pageName);
|
|
329
848
|
// path.join(stepDefinitionFolderPath, pageName + "_page.mjs");
|
|
330
849
|
let codePage = getCodePage(stepDefsFilePath);
|
|
331
|
-
|
|
332
|
-
|
|
850
|
+
codePage = await saveRecording({
|
|
851
|
+
step,
|
|
852
|
+
cucumberStep,
|
|
853
|
+
codePage,
|
|
854
|
+
projectDir,
|
|
855
|
+
stepsDefinitions,
|
|
856
|
+
parametersMap: scenario.parametersMap,
|
|
857
|
+
});
|
|
333
858
|
if (!codePage) {
|
|
334
859
|
continue;
|
|
335
860
|
}
|
|
@@ -340,3 +865,45 @@ export async function updateStepDefinitions({ scenario, featureName, projectDir
|
|
|
340
865
|
}
|
|
341
866
|
writeFileSync(utilsFilePath, utilsContent, "utf8");
|
|
342
867
|
}
|
|
868
|
+
|
|
869
|
+
export function saveRoutes({ step, folderPath }) {
|
|
870
|
+
const routeItems = step.routeItems;
|
|
871
|
+
if (!routeItems || routeItems.length === 0) {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const cucumberStep = getCucumberStep({ step });
|
|
875
|
+
const template = cucumberStep.getTemplate();
|
|
876
|
+
const stepNameHash = createHash("sha256").update(template).digest("hex");
|
|
877
|
+
console.log("Saving routes for step:", step.text, "with hash:", stepNameHash);
|
|
878
|
+
|
|
879
|
+
const routeItemsWithFilters = routeItems.map((routeItem) => {
|
|
880
|
+
const oldFilters = routeItem.filters;
|
|
881
|
+
const queryParamsObject = {};
|
|
882
|
+
oldFilters.queryParams.forEach((queryParam) => {
|
|
883
|
+
queryParamsObject[queryParam.key] = queryParam.value;
|
|
884
|
+
});
|
|
885
|
+
const newFilters = { path: oldFilters.path, method: oldFilters.method, queryParams: queryParamsObject };
|
|
886
|
+
return {
|
|
887
|
+
...routeItem,
|
|
888
|
+
filters: newFilters,
|
|
889
|
+
};
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
const routesFilePath = path.join(folderPath, stepNameHash + ".json");
|
|
893
|
+
console.log("Routes file path:", routesFilePath);
|
|
894
|
+
const routesData = {
|
|
895
|
+
template,
|
|
896
|
+
routes: routeItemsWithFilters,
|
|
897
|
+
};
|
|
898
|
+
console.log("Routes data to save:", routesData);
|
|
899
|
+
|
|
900
|
+
if (!existsSync(folderPath)) {
|
|
901
|
+
mkdirSync(folderPath, { recursive: true });
|
|
902
|
+
}
|
|
903
|
+
try {
|
|
904
|
+
writeFileSync(routesFilePath, JSON.stringify(routesData, null, 2), "utf8");
|
|
905
|
+
console.log("Saved routes to", routesFilePath);
|
|
906
|
+
} catch (error) {
|
|
907
|
+
console.error("Failed to save routes to", routesFilePath, "Error:", error);
|
|
908
|
+
}
|
|
909
|
+
}
|