@dev-blinq/cucumber_client 1.0.1324-dev → 1.0.1324-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 +108 -108
- 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 +156 -48
- 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 -44
- 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 +26 -18
- 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 +6 -3
- 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 +190 -127
- package/bin/client/recorderv3/implemented_steps.js +74 -16
- package/bin/client/recorderv3/index.js +68 -54
- package/bin/client/recorderv3/network.js +22 -5
- package/bin/client/recorderv3/scriptTest.js +1 -1
- package/bin/client/recorderv3/services.js +4 -16
- package/bin/client/recorderv3/step_runner.js +303 -220
- package/bin/client/recorderv3/step_utils.js +484 -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 +3 -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 +21 -12
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// define the jsdoc type for the input
|
|
2
2
|
import { closeContext, initContext, _getDataFile, resetTestData } from "automation_model";
|
|
3
|
-
import { existsSync,
|
|
3
|
+
import { existsSync, readdirSync, readFileSync, rmSync } from "fs";
|
|
4
4
|
import path from "path";
|
|
5
5
|
import url from "url";
|
|
6
|
-
import { getImplementedSteps,
|
|
6
|
+
import { getImplementedSteps, parseRouteFiles } from "./implemented_steps.js";
|
|
7
7
|
import { NamesService } from "./services.js";
|
|
8
8
|
import { BVTStepRunner } from "./step_runner.js";
|
|
9
9
|
import { readFile, writeFile } from "fs/promises";
|
|
@@ -12,11 +12,11 @@ import { updateFeatureFile } from "./update_feature.js";
|
|
|
12
12
|
import { parseStepTextParameters } from "../cucumber/utils.js";
|
|
13
13
|
import { AstBuilder, GherkinClassicTokenMatcher, Parser } from "@cucumber/gherkin";
|
|
14
14
|
import chokidar from "chokidar";
|
|
15
|
-
import logger from "../../logger.js";
|
|
16
15
|
import { unEscapeNonPrintables } from "../cucumber/utils.js";
|
|
17
16
|
import { findAvailablePort } from "../utils/index.js";
|
|
18
|
-
import
|
|
19
|
-
|
|
17
|
+
import socketLogger from "../utils/socket_logger.js";
|
|
18
|
+
import { tmpdir } from "os";
|
|
19
|
+
import { faker } from "@faker-js/faker";
|
|
20
20
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
21
21
|
|
|
22
22
|
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -45,15 +45,15 @@ async function evaluate(frame, script) {
|
|
|
45
45
|
async function findNestedFrameSelector(frame, obj) {
|
|
46
46
|
try {
|
|
47
47
|
const parent = frame.parentFrame();
|
|
48
|
-
if (parent) console.log(`Parent frame: ${JSON.stringify(parent)}`);
|
|
49
48
|
if (!parent) return { children: obj };
|
|
50
49
|
const frameElement = await frame.frameElement();
|
|
51
50
|
if (!frameElement) return;
|
|
52
51
|
const selectors = await parent.evaluate((element) => {
|
|
53
|
-
return window.
|
|
52
|
+
return window.__bvt_Recorder.locatorGenerator.getElementLocators(element, { excludeText: true }).locators;
|
|
54
53
|
}, frameElement);
|
|
55
54
|
return findNestedFrameSelector(parent, { children: obj, selectors });
|
|
56
55
|
} catch (e) {
|
|
56
|
+
socketLogger.error(`Error in findNestedFrameSelector: ${e}`);
|
|
57
57
|
console.error(e);
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -150,6 +150,7 @@ const transformAction = (action, el, isVerify, isPopupCloseClick, isInHoverMode,
|
|
|
150
150
|
};
|
|
151
151
|
}
|
|
152
152
|
default: {
|
|
153
|
+
socketLogger.error(`Action not supported: ${action.name}`);
|
|
153
154
|
console.log("action not supported", action);
|
|
154
155
|
throw new Error("action not supported");
|
|
155
156
|
}
|
|
@@ -161,6 +162,7 @@ const transformAction = (action, el, isVerify, isPopupCloseClick, isInHoverMode,
|
|
|
161
162
|
* @property {string} projectDir
|
|
162
163
|
* @property {string} TOKEN
|
|
163
164
|
* @property {(name:string, data:any)=> void} sendEvent
|
|
165
|
+
* @property {Object} logger
|
|
164
166
|
*/
|
|
165
167
|
export class BVTRecorder {
|
|
166
168
|
#currentURL = "";
|
|
@@ -174,7 +176,6 @@ export class BVTRecorder {
|
|
|
174
176
|
*/
|
|
175
177
|
constructor(initialState) {
|
|
176
178
|
Object.assign(this, initialState);
|
|
177
|
-
this.logger = logger;
|
|
178
179
|
this.screenshotMap = new Map();
|
|
179
180
|
this.snapshotMap = new Map();
|
|
180
181
|
this.scenariosStepsMap = new Map();
|
|
@@ -184,36 +185,16 @@ export class BVTRecorder {
|
|
|
184
185
|
projectDir: this.projectDir,
|
|
185
186
|
logger: this.logger,
|
|
186
187
|
});
|
|
187
|
-
this.stepRunner = new BVTStepRunner({
|
|
188
|
-
projectDir: this.projectDir,
|
|
189
|
-
sendExecutionStatus: (data) => {
|
|
190
|
-
if (data && data.type) {
|
|
191
|
-
switch (data.type) {
|
|
192
|
-
case "cmdExecutionStart":
|
|
193
|
-
console.log("Sending cmdExecutionStart event for cmdId:", data);
|
|
194
|
-
this.sendEvent(this.events.cmdExecutionStart, data);
|
|
195
|
-
break;
|
|
196
|
-
case "cmdExecutionSuccess":
|
|
197
|
-
console.log("Sending cmdExecutionSuccess event for cmdId:", data);
|
|
198
|
-
this.sendEvent(this.events.cmdExecutionSuccess, data);
|
|
199
|
-
break;
|
|
200
|
-
case "cmdExecutionFailure":
|
|
201
|
-
console.log("Sending cmdExecutionFailure event for cmdId:", data);
|
|
202
|
-
this.sendEvent(this.events.cmdExecutionFailure, data);
|
|
203
|
-
break;
|
|
204
|
-
default:
|
|
205
|
-
console.warn("Unknown command execution status type:", data.type);
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
},
|
|
210
|
-
});
|
|
211
188
|
this.pageSet = new Set();
|
|
189
|
+
this.pageMetaDataSet = new Set();
|
|
212
190
|
this.lastKnownUrlPath = "";
|
|
213
|
-
|
|
214
|
-
this.world = { attach: () => { } };
|
|
191
|
+
this.world = { attach: () => {} };
|
|
215
192
|
this.shouldTakeScreenshot = true;
|
|
216
193
|
this.watcher = null;
|
|
194
|
+
this.networkEventsFolder = path.join(tmpdir(), "blinq_network_events");
|
|
195
|
+
if (existsSync(this.networkEventsFolder)) {
|
|
196
|
+
rmSync(this.networkEventsFolder, { recursive: true, force: true });
|
|
197
|
+
}
|
|
217
198
|
}
|
|
218
199
|
events = {
|
|
219
200
|
onFrameNavigate: "BVTRecorder.onFrameNavigate",
|
|
@@ -226,13 +207,14 @@ export class BVTRecorder {
|
|
|
226
207
|
onGoto: "BVTRecorder.onGoto",
|
|
227
208
|
cmdExecutionStart: "BVTRecorder.cmdExecutionStart",
|
|
228
209
|
cmdExecutionSuccess: "BVTRecorder.cmdExecutionSuccess",
|
|
229
|
-
|
|
210
|
+
cmdExecutionError: "BVTRecorder.cmdExecutionError",
|
|
211
|
+
interceptResults: "BVTRecorder.interceptResults",
|
|
230
212
|
};
|
|
231
213
|
bindings = {
|
|
232
214
|
__bvt_recordCommand: async ({ frame, page, context }, event) => {
|
|
233
215
|
this.#activeFrame = frame;
|
|
234
216
|
const nestFrmLoc = await findNestedFrameSelector(frame);
|
|
235
|
-
|
|
217
|
+
this.logger.info(`Time taken for action: ${event.statistics.time}`);
|
|
236
218
|
await this.onAction({ ...event, nestFrmLoc });
|
|
237
219
|
},
|
|
238
220
|
__bvt_getMode: async () => {
|
|
@@ -251,8 +233,7 @@ export class BVTRecorder {
|
|
|
251
233
|
await this.onClosePopup();
|
|
252
234
|
},
|
|
253
235
|
__bvt_log: async (src, message) => {
|
|
254
|
-
|
|
255
|
-
console.log(`Inside Browser: ${message}`);
|
|
236
|
+
this.logger.info(`Inside Browser: ${message}`);
|
|
256
237
|
},
|
|
257
238
|
__bvt_getObject: (_src, obj) => {
|
|
258
239
|
this.processObject(obj);
|
|
@@ -264,7 +245,6 @@ export class BVTRecorder {
|
|
|
264
245
|
const locator = await this.web.page.locator(selector);
|
|
265
246
|
const snapshot = await locator.ariaSnapshot();
|
|
266
247
|
return snapshot;
|
|
267
|
-
// Triggering workflow
|
|
268
248
|
};
|
|
269
249
|
|
|
270
250
|
processObject = async ({ type, action, value }) => {
|
|
@@ -315,11 +295,12 @@ export class BVTRecorder {
|
|
|
315
295
|
}
|
|
316
296
|
|
|
317
297
|
async _initBrowser({ url }) {
|
|
298
|
+
socketLogger.info("Only present in 1.0.1293-stage");
|
|
318
299
|
this.#remoteDebuggerPort = await findAvailablePort();
|
|
319
300
|
process.env.CDP_LISTEN_PORT = this.#remoteDebuggerPort;
|
|
320
301
|
|
|
321
|
-
this.stepRunner.setRemoteDebugPort(this.#remoteDebuggerPort);
|
|
322
|
-
this.world = { attach: () => {
|
|
302
|
+
// this.stepRunner.setRemoteDebugPort(this.#remoteDebuggerPort);
|
|
303
|
+
this.world = { attach: () => {} };
|
|
323
304
|
|
|
324
305
|
const ai_config_file = path.join(this.projectDir, "ai_config.json");
|
|
325
306
|
let ai_config = {};
|
|
@@ -327,9 +308,10 @@ export class BVTRecorder {
|
|
|
327
308
|
try {
|
|
328
309
|
ai_config = JSON.parse(readFileSync(ai_config_file, "utf8"));
|
|
329
310
|
} catch (error) {
|
|
330
|
-
|
|
311
|
+
this.logger.error("Error reading ai_config.json", error);
|
|
331
312
|
}
|
|
332
313
|
}
|
|
314
|
+
this.config = ai_config;
|
|
333
315
|
const initScripts = {
|
|
334
316
|
// recorderCjs: injectedScriptSource,
|
|
335
317
|
scripts: [
|
|
@@ -338,16 +320,37 @@ export class BVTRecorder {
|
|
|
338
320
|
],
|
|
339
321
|
};
|
|
340
322
|
|
|
341
|
-
let startTime = Date.now();
|
|
342
323
|
const bvtContext = await initContext(url, false, false, this.world, 450, initScripts, this.envName);
|
|
343
|
-
let stopTime = Date.now();
|
|
344
|
-
this.logger.info(`Browser launched in ${(stopTime - startTime) / 1000} s`);
|
|
345
324
|
this.bvtContext = bvtContext;
|
|
325
|
+
this.stepRunner = new BVTStepRunner({
|
|
326
|
+
projectDir: this.projectDir,
|
|
327
|
+
sendExecutionStatus: (data) => {
|
|
328
|
+
if (data && data.type) {
|
|
329
|
+
switch (data.type) {
|
|
330
|
+
case "cmdExecutionStart":
|
|
331
|
+
this.sendEvent(this.events.cmdExecutionStart, data);
|
|
332
|
+
break;
|
|
333
|
+
case "cmdExecutionSuccess":
|
|
334
|
+
this.sendEvent(this.events.cmdExecutionSuccess, data);
|
|
335
|
+
break;
|
|
336
|
+
case "cmdExecutionError":
|
|
337
|
+
this.sendEvent(this.events.cmdExecutionError, data);
|
|
338
|
+
break;
|
|
339
|
+
case "interceptResults":
|
|
340
|
+
this.sendEvent(this.events.interceptResults, data);
|
|
341
|
+
break;
|
|
342
|
+
default:
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
bvtContext: this.bvtContext,
|
|
348
|
+
});
|
|
346
349
|
const context = bvtContext.playContext;
|
|
347
350
|
this.context = context;
|
|
348
351
|
this.web = bvtContext.stable || bvtContext.web;
|
|
352
|
+
this.web.tryAllStrategies = true;
|
|
349
353
|
this.page = bvtContext.page;
|
|
350
|
-
|
|
351
354
|
this.pageSet.add(this.page);
|
|
352
355
|
this.lastKnownUrlPath = this._updateUrlPath();
|
|
353
356
|
const browser = await this.context.browser();
|
|
@@ -375,13 +378,15 @@ export class BVTRecorder {
|
|
|
375
378
|
}
|
|
376
379
|
return;
|
|
377
380
|
} catch (error) {
|
|
378
|
-
console.error("Error evaluting in context:", error);
|
|
381
|
+
// console.error("Error evaluting in context:", error);
|
|
382
|
+
this.logger.error("Error evaluating in context:", error);
|
|
379
383
|
}
|
|
380
384
|
}
|
|
381
385
|
}
|
|
382
386
|
|
|
383
387
|
getMode() {
|
|
384
|
-
console.log("getMode", this.#mode);
|
|
388
|
+
// console.log("getMode", this.#mode);
|
|
389
|
+
this.logger.info("Current mode:", this.#mode);
|
|
385
390
|
return this.#mode;
|
|
386
391
|
}
|
|
387
392
|
|
|
@@ -423,6 +428,8 @@ export class BVTRecorder {
|
|
|
423
428
|
this.sendEvent(this.events.onBrowserClose);
|
|
424
429
|
}
|
|
425
430
|
} catch (error) {
|
|
431
|
+
this.logger.error("Error in page close event");
|
|
432
|
+
this.logger.error(error);
|
|
426
433
|
console.error("Error in page close event");
|
|
427
434
|
console.error(error);
|
|
428
435
|
}
|
|
@@ -433,8 +440,10 @@ export class BVTRecorder {
|
|
|
433
440
|
if (frame !== page.mainFrame()) return;
|
|
434
441
|
this.handlePageTransition();
|
|
435
442
|
} catch (error) {
|
|
443
|
+
this.logger.error("Error in handlePageTransition event");
|
|
444
|
+
this.logger.error(error);
|
|
436
445
|
console.error("Error in handlePageTransition event");
|
|
437
|
-
|
|
446
|
+
console.error(error);
|
|
438
447
|
}
|
|
439
448
|
try {
|
|
440
449
|
if (frame !== this.#activeFrame) return;
|
|
@@ -453,6 +462,8 @@ export class BVTRecorder {
|
|
|
453
462
|
// await this._setRecordingMode(frame);
|
|
454
463
|
// await this._initPage(page);
|
|
455
464
|
} catch (error) {
|
|
465
|
+
this.logger.error("Error in frame navigate event");
|
|
466
|
+
this.logger.error(error);
|
|
456
467
|
console.error("Error in frame navigate event");
|
|
457
468
|
// console.error(error);
|
|
458
469
|
}
|
|
@@ -535,13 +546,9 @@ export class BVTRecorder {
|
|
|
535
546
|
|
|
536
547
|
try {
|
|
537
548
|
const result = await client.send("Page.getNavigationHistory");
|
|
538
|
-
// console.log("Navigation History:", result);
|
|
539
549
|
const entries = result.entries;
|
|
540
550
|
const currentIndex = result.currentIndex;
|
|
541
551
|
|
|
542
|
-
// ignore if currentIndex is not the last entry
|
|
543
|
-
// if (currentIndex !== entries.length - 1) return;
|
|
544
|
-
|
|
545
552
|
const currentEntry = entries[currentIndex];
|
|
546
553
|
const transitionInfo = this.analyzeTransitionType(entries, currentIndex, currentEntry);
|
|
547
554
|
this.previousIndex = currentIndex;
|
|
@@ -554,6 +561,8 @@ export class BVTRecorder {
|
|
|
554
561
|
navigationAction: transitionInfo.action,
|
|
555
562
|
};
|
|
556
563
|
} catch (error) {
|
|
564
|
+
this.logger.error("Error in getCurrentTransition event");
|
|
565
|
+
this.logger.error(error);
|
|
557
566
|
console.error("Error in getTransistionType event", error);
|
|
558
567
|
} finally {
|
|
559
568
|
await client.detach();
|
|
@@ -618,9 +627,12 @@ export class BVTRecorder {
|
|
|
618
627
|
this.pageSet.add(page);
|
|
619
628
|
|
|
620
629
|
await page.waitForLoadState("domcontentloaded");
|
|
630
|
+
|
|
621
631
|
// add listener for frame navigation on new tab
|
|
622
632
|
this._addFrameNavigateListener(page);
|
|
623
633
|
} catch (error) {
|
|
634
|
+
this.logger.error("Error in page event");
|
|
635
|
+
this.logger.error(error);
|
|
624
636
|
console.error("Error in page event");
|
|
625
637
|
console.error(error);
|
|
626
638
|
}
|
|
@@ -662,6 +674,7 @@ export class BVTRecorder {
|
|
|
662
674
|
const { data } = await client.send("Page.captureScreenshot", { format: "png" });
|
|
663
675
|
return data;
|
|
664
676
|
} catch (error) {
|
|
677
|
+
this.logger.error("Error in taking browser screenshot");
|
|
665
678
|
console.error("Error in taking browser screenshot", error);
|
|
666
679
|
} finally {
|
|
667
680
|
await client.detach();
|
|
@@ -707,7 +720,6 @@ export class BVTRecorder {
|
|
|
707
720
|
if (this.shouldTakeScreenshot) {
|
|
708
721
|
await this.storeScreenshot(event);
|
|
709
722
|
}
|
|
710
|
-
|
|
711
723
|
this.sendEvent(this.events.onNewCommand, cmdEvent);
|
|
712
724
|
this._updateUrlPath();
|
|
713
725
|
}
|
|
@@ -725,7 +737,7 @@ export class BVTRecorder {
|
|
|
725
737
|
}
|
|
726
738
|
async closeBrowser() {
|
|
727
739
|
delete process.env.TEMP_RUN;
|
|
728
|
-
await this.watcher.close().then(() => {
|
|
740
|
+
await this.watcher.close().then(() => {});
|
|
729
741
|
this.watcher = null;
|
|
730
742
|
this.previousIndex = null;
|
|
731
743
|
this.previousHistoryLength = null;
|
|
@@ -783,7 +795,6 @@ export class BVTRecorder {
|
|
|
783
795
|
}
|
|
784
796
|
|
|
785
797
|
async startRecordingInput() {
|
|
786
|
-
console.log("startRecordingInput");
|
|
787
798
|
await this.setMode("recordingInput");
|
|
788
799
|
}
|
|
789
800
|
async stopRecordingInput() {
|
|
@@ -809,6 +820,15 @@ export class BVTRecorder {
|
|
|
809
820
|
async abortExecution() {
|
|
810
821
|
await this.stepRunner.abortExecution();
|
|
811
822
|
}
|
|
823
|
+
|
|
824
|
+
async pauseExecution({ cmdId }) {
|
|
825
|
+
await this.stepRunner.pauseExecution(cmdId);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
async resumeExecution({ cmdId }) {
|
|
829
|
+
await this.stepRunner.resumeExecution(cmdId);
|
|
830
|
+
}
|
|
831
|
+
|
|
812
832
|
async dealyedRevertMode() {
|
|
813
833
|
const timerId = setTimeout(async () => {
|
|
814
834
|
await this.revertMode();
|
|
@@ -816,16 +836,21 @@ export class BVTRecorder {
|
|
|
816
836
|
this.timerId = timerId;
|
|
817
837
|
}
|
|
818
838
|
async runStep({ step, parametersMap, tags, isFirstStep, listenNetwork }, options) {
|
|
839
|
+
const { skipAfter = true, skipBefore = !isFirstStep } = options || {};
|
|
819
840
|
const _env = {
|
|
820
841
|
TOKEN: this.TOKEN,
|
|
821
842
|
TEMP_RUN: true,
|
|
822
843
|
REPORT_FOLDER: this.bvtContext.reportFolder,
|
|
823
844
|
BLINQ_ENV: this.envName,
|
|
824
|
-
STORE_DETAILED_NETWORK_DATA: listenNetwork ? "true" : "false",
|
|
825
|
-
CURRENT_STEP_ID: step.id,
|
|
826
845
|
};
|
|
827
846
|
|
|
828
847
|
this.bvtContext.navigate = true;
|
|
848
|
+
this.bvtContext.loadedRoutes = null;
|
|
849
|
+
if (listenNetwork) {
|
|
850
|
+
this.bvtContext.STORE_DETAILED_NETWORK_DATA = true;
|
|
851
|
+
} else {
|
|
852
|
+
this.bvtContext.STORE_DETAILED_NETWORK_DATA = false;
|
|
853
|
+
}
|
|
829
854
|
for (const [key, value] of Object.entries(_env)) {
|
|
830
855
|
process.env[key] = value;
|
|
831
856
|
}
|
|
@@ -843,9 +868,13 @@ export class BVTRecorder {
|
|
|
843
868
|
parametersMap,
|
|
844
869
|
envPath: this.envName,
|
|
845
870
|
tags,
|
|
871
|
+
config: this.config,
|
|
846
872
|
},
|
|
847
873
|
this.bvtContext,
|
|
848
|
-
|
|
874
|
+
{
|
|
875
|
+
skipAfter,
|
|
876
|
+
skipBefore,
|
|
877
|
+
}
|
|
849
878
|
);
|
|
850
879
|
await this.revertMode();
|
|
851
880
|
return { info };
|
|
@@ -886,6 +915,7 @@ export class BVTRecorder {
|
|
|
886
915
|
step.commands = [];
|
|
887
916
|
}
|
|
888
917
|
}
|
|
918
|
+
return steps;
|
|
889
919
|
// return getStepsAndCommandsForScenario({
|
|
890
920
|
// name,
|
|
891
921
|
// featureName,
|
|
@@ -893,6 +923,7 @@ export class BVTRecorder {
|
|
|
893
923
|
// map: this.scenariosStepsMap,
|
|
894
924
|
// });
|
|
895
925
|
}
|
|
926
|
+
|
|
896
927
|
async generateStepName({ commands, stepsNames, parameters, map }) {
|
|
897
928
|
return await this.namesService.generateStepName({ commands, stepsNames, parameters, map });
|
|
898
929
|
}
|
|
@@ -944,10 +975,11 @@ export class BVTRecorder {
|
|
|
944
975
|
if (existsSync(_getDataFile(this.world, this.bvtContext, this.web))) {
|
|
945
976
|
try {
|
|
946
977
|
const testData = JSON.parse(readFileSync(_getDataFile(this.world, this.bvtContext, this.web), "utf8"));
|
|
947
|
-
this.logger.info("Test data", testData);
|
|
978
|
+
// this.logger.info("Test data", testData);
|
|
948
979
|
this.sendEvent(this.events.getTestData, testData);
|
|
949
980
|
} catch (e) {
|
|
950
|
-
this.logger.error("Error reading test data file", e);
|
|
981
|
+
// this.logger.error("Error reading test data file", e);
|
|
982
|
+
console.log("Error reading test data file", e);
|
|
951
983
|
}
|
|
952
984
|
}
|
|
953
985
|
|
|
@@ -956,10 +988,12 @@ export class BVTRecorder {
|
|
|
956
988
|
this.watcher.on("all", async (event, path) => {
|
|
957
989
|
try {
|
|
958
990
|
const testData = JSON.parse(await readFile(_getDataFile(this.world, this.bvtContext, this.web), "utf8"));
|
|
959
|
-
this.logger.info("Test data", testData);
|
|
991
|
+
// this.logger.info("Test data", testData);
|
|
992
|
+
console.log("Test data changed", testData);
|
|
960
993
|
this.sendEvent(this.events.getTestData, testData);
|
|
961
994
|
} catch (e) {
|
|
962
|
-
this.logger.error("Error reading test data file", e);
|
|
995
|
+
// this.logger.error("Error reading test data file", e);
|
|
996
|
+
console.log("Error reading test data file", e);
|
|
963
997
|
}
|
|
964
998
|
});
|
|
965
999
|
}
|
|
@@ -992,7 +1026,7 @@ export class BVTRecorder {
|
|
|
992
1026
|
.filter((file) => file.endsWith(".feature"))
|
|
993
1027
|
.map((file) => path.join(this.projectDir, "features", file));
|
|
994
1028
|
try {
|
|
995
|
-
const parsedFiles = featureFiles.map((file) => parseFeatureFile(file));
|
|
1029
|
+
const parsedFiles = featureFiles.map((file) => this.parseFeatureFile(file));
|
|
996
1030
|
const output = {};
|
|
997
1031
|
parsedFiles.forEach((file) => {
|
|
998
1032
|
if (!file.feature) return;
|
|
@@ -1017,56 +1051,10 @@ export class BVTRecorder {
|
|
|
1017
1051
|
return getCommandsForImplementedStep(stepName, step_definitions, stepParams).commands;
|
|
1018
1052
|
}
|
|
1019
1053
|
|
|
1020
|
-
parseRouteFiles(step) {
|
|
1021
|
-
const routeFolder = path.join(this.projectDir, "data", "routes");
|
|
1022
|
-
const templateRouteMap = new Map();
|
|
1023
|
-
|
|
1024
|
-
// Go over all the files in the route folder and parse them
|
|
1025
|
-
const routeFiles = readdirSync(routeFolder).filter((file) => file.endsWith(".json"));
|
|
1026
|
-
for (const file of routeFiles) {
|
|
1027
|
-
const filePath = path.join(routeFolder, file);
|
|
1028
|
-
const routeData = JSON.parse(readFileSync(filePath, "utf8"));
|
|
1029
|
-
if (routeData && routeData.template) {
|
|
1030
|
-
const template = routeData.template;
|
|
1031
|
-
const routes = routeData.routes;
|
|
1032
|
-
|
|
1033
|
-
templateRouteMap.set(template, routes);
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
if (!existsSync(routeFolder)) {
|
|
1038
|
-
return null;
|
|
1039
|
-
} else if (step && step.text) {
|
|
1040
|
-
// Convert the step text to cucumber template
|
|
1041
|
-
const cucumberStep = new Step();
|
|
1042
|
-
cucumberStep.text = step.text;
|
|
1043
|
-
const template = cucumberStep.getTemplate();
|
|
1044
|
-
if (templateRouteMap.has(template)) {
|
|
1045
|
-
const routeItems = templateRouteMap.get(template);
|
|
1046
|
-
console.log("Route Items from template:", routeItems);
|
|
1047
|
-
routeItems.forEach((item) => {
|
|
1048
|
-
const filters = item.filters || {};
|
|
1049
|
-
const queryParams = filters?.queryParams || {};
|
|
1050
|
-
console.log("Query Params:", queryParams);
|
|
1051
|
-
const queryParamsArray = Object.keys(queryParams).map((key) => ({
|
|
1052
|
-
paramKey: key,
|
|
1053
|
-
paramValue: queryParams[key],
|
|
1054
|
-
}));
|
|
1055
|
-
console.log("Query Params Array:", queryParamsArray);
|
|
1056
|
-
filters.queryParams = queryParamsArray || [];
|
|
1057
|
-
});
|
|
1058
|
-
step.routeItems = routeItems;
|
|
1059
|
-
console.log("Route Items:", step.routeItems);
|
|
1060
|
-
} else {
|
|
1061
|
-
step.routeItems = null;
|
|
1062
|
-
}
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
1054
|
loadExistingScenario({ featureName, scenarioName }) {
|
|
1067
1055
|
const step_definitions = loadStepDefinitions(this.projectDir);
|
|
1068
1056
|
const featureFilePath = path.join(this.projectDir, "features", featureName);
|
|
1069
|
-
const gherkinDoc = parseFeatureFile(featureFilePath);
|
|
1057
|
+
const gherkinDoc = this.parseFeatureFile(featureFilePath);
|
|
1070
1058
|
const scenario = gherkinDoc.feature.children.find((child) => child.scenario.name === scenarioName)?.scenario;
|
|
1071
1059
|
|
|
1072
1060
|
const steps = [];
|
|
@@ -1091,7 +1079,7 @@ export class BVTRecorder {
|
|
|
1091
1079
|
..._s,
|
|
1092
1080
|
keyword: step.keyword.trim(),
|
|
1093
1081
|
};
|
|
1094
|
-
this.
|
|
1082
|
+
parseRouteFiles(this.projectDir, _step);
|
|
1095
1083
|
steps.push(_step);
|
|
1096
1084
|
}
|
|
1097
1085
|
return {
|
|
@@ -1184,20 +1172,95 @@ export class BVTRecorder {
|
|
|
1184
1172
|
return false;
|
|
1185
1173
|
}
|
|
1186
1174
|
}
|
|
1187
|
-
}
|
|
1175
|
+
async initExecution({ tags = [] }) {
|
|
1176
|
+
// run before hooks
|
|
1177
|
+
const noopStep = {
|
|
1178
|
+
text: "Noop",
|
|
1179
|
+
isImplemented: true,
|
|
1180
|
+
};
|
|
1181
|
+
await this.runStep(
|
|
1182
|
+
{
|
|
1183
|
+
step: noopStep,
|
|
1184
|
+
parametersMap: {},
|
|
1185
|
+
tags,
|
|
1186
|
+
},
|
|
1187
|
+
{
|
|
1188
|
+
skipBefore: false,
|
|
1189
|
+
skipAfter: true,
|
|
1190
|
+
}
|
|
1191
|
+
);
|
|
1192
|
+
}
|
|
1193
|
+
async cleanupExecution({ tags = [] }) {
|
|
1194
|
+
// run after hooks
|
|
1195
|
+
const noopStep = {
|
|
1196
|
+
text: "Noop",
|
|
1197
|
+
isImplemented: true,
|
|
1198
|
+
};
|
|
1199
|
+
await this.runStep(
|
|
1200
|
+
{
|
|
1201
|
+
step: noopStep,
|
|
1202
|
+
parametersMap: {},
|
|
1203
|
+
tags,
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
skipBefore: true,
|
|
1207
|
+
skipAfter: false,
|
|
1208
|
+
}
|
|
1209
|
+
);
|
|
1210
|
+
}
|
|
1211
|
+
async resetExecution({ tags = [] }) {
|
|
1212
|
+
// run after hooks followed by before hooks
|
|
1213
|
+
await this.cleanupExecution({ tags });
|
|
1214
|
+
await this.initExecution({ tags });
|
|
1215
|
+
}
|
|
1188
1216
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1217
|
+
parseFeatureFile(featureFilePath) {
|
|
1218
|
+
try {
|
|
1219
|
+
let id = 0;
|
|
1220
|
+
const uuidFn = () => (++id).toString(16);
|
|
1221
|
+
const builder = new AstBuilder(uuidFn);
|
|
1222
|
+
const matcher = new GherkinClassicTokenMatcher();
|
|
1223
|
+
const parser = new Parser(builder, matcher);
|
|
1224
|
+
const source = readFileSync(featureFilePath, "utf8");
|
|
1225
|
+
const gherkinDocument = parser.parse(source);
|
|
1226
|
+
return gherkinDocument;
|
|
1227
|
+
} catch (e) {
|
|
1228
|
+
this.logger.error(`Error parsing feature file: ${featureFilePath}`);
|
|
1229
|
+
console.log(e);
|
|
1230
|
+
}
|
|
1231
|
+
return {};
|
|
1201
1232
|
}
|
|
1202
|
-
|
|
1203
|
-
|
|
1233
|
+
|
|
1234
|
+
stopRecordingNetwork(input) {
|
|
1235
|
+
if (this.bvtContext) {
|
|
1236
|
+
this.bvtContext.STORE_DETAILED_NETWORK_DATA = false;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
async fakeParams(params) {
|
|
1241
|
+
const newFakeParams = {};
|
|
1242
|
+
Object.keys(params).forEach((key) => {
|
|
1243
|
+
if (!params[key].startsWith("{{") || !params[key].endsWith("}}")) {
|
|
1244
|
+
newFakeParams[key] = params[key];
|
|
1245
|
+
return;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
try {
|
|
1249
|
+
const value = params[key].substring(2, params[key].length - 2).trim();
|
|
1250
|
+
const faking = value.split("(")[0].split(".");
|
|
1251
|
+
let argument = value.substring(value.indexOf("(") + 1, value.lastIndexOf(")"));
|
|
1252
|
+
argument = isNaN(Number(argument)) || argument === "" ? argument : Number(argument);
|
|
1253
|
+
let fakeFunc = faker;
|
|
1254
|
+
faking.forEach((f) => {
|
|
1255
|
+
fakeFunc = fakeFunc[f];
|
|
1256
|
+
});
|
|
1257
|
+
const newValue = fakeFunc(argument);
|
|
1258
|
+
newFakeParams[key] = newValue;
|
|
1259
|
+
} catch (error) {
|
|
1260
|
+
newFakeParams[key] = params[key];
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
|
|
1264
|
+
return newFakeParams;
|
|
1265
|
+
}
|
|
1266
|
+
}
|