@dev-blinq/cucumber_client 1.0.1459-dev → 1.0.1459-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.
Files changed (36) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +73 -73
  2. package/bin/assets/scripts/recorder.js +87 -49
  3. package/bin/assets/scripts/snapshot_capturer.js +10 -17
  4. package/bin/assets/scripts/unique_locators.js +169 -47
  5. package/bin/assets/templates/_hooks_template.txt +6 -2
  6. package/bin/assets/templates/utils_template.txt +16 -16
  7. package/bin/client/code_cleanup/utils.js +16 -7
  8. package/bin/client/code_gen/code_inversion.js +127 -2
  9. package/bin/client/code_gen/duplication_analysis.js +2 -1
  10. package/bin/client/code_gen/function_signature.js +8 -0
  11. package/bin/client/code_gen/index.js +4 -0
  12. package/bin/client/code_gen/page_reflection.js +101 -15
  13. package/bin/client/code_gen/playwright_codeget.js +168 -76
  14. package/bin/client/cucumber/feature.js +4 -17
  15. package/bin/client/cucumber/steps_definitions.js +13 -0
  16. package/bin/client/local_agent.js +1 -1
  17. package/bin/client/recorderv3/bvt_init.js +305 -0
  18. package/bin/client/recorderv3/bvt_recorder.js +1556 -1183
  19. package/bin/client/recorderv3/implemented_steps.js +2 -0
  20. package/bin/client/recorderv3/index.js +3 -293
  21. package/bin/client/recorderv3/services.js +838 -142
  22. package/bin/client/recorderv3/step_runner.js +35 -6
  23. package/bin/client/recorderv3/step_utils.js +170 -94
  24. package/bin/client/recorderv3/update_feature.js +87 -39
  25. package/bin/client/recorderv3/wbr_entry.js +61 -0
  26. package/bin/client/recording.js +1 -0
  27. package/bin/client/types/locators.js +2 -0
  28. package/bin/client/upload-service.js +2 -0
  29. package/bin/client/utils/app_dir.js +21 -0
  30. package/bin/client/utils/socket_logger.js +100 -125
  31. package/bin/index.js +4 -1
  32. package/package.json +11 -5
  33. package/bin/client/recorderv3/app_dir.js +0 -23
  34. package/bin/client/recorderv3/network.js +0 -299
  35. package/bin/client/recorderv3/scriptTest.js +0 -5
  36. package/bin/client/recorderv3/ws_server.js +0 -72
@@ -36,6 +36,19 @@ class StepsDefinitions {
36
36
  // }
37
37
  // });
38
38
  const { expressions, methods } = codePage;
39
+
40
+ if (codePage.fileContent.includes('from "./utils.mjs"')) {
41
+ const filePath = path.join(
42
+ this.baseFolder,
43
+ this.isTemp ? (process.env.tempFeaturesFolderPath ?? "__temp_features") : "features",
44
+ "step_definitions",
45
+ "utils.mjs"
46
+ );
47
+ const utilsCodePage = new CodePage(filePath);
48
+ utilsCodePage.generateModel();
49
+ methods.push(...utilsCodePage.methods);
50
+ }
51
+
39
52
  for (let i = 0; i < expressions.length; i++) {
40
53
  const expression = expressions[i];
41
54
  const pattern = expression.pattern;
@@ -1100,7 +1100,7 @@ class LocalAgent {
1100
1100
  if (this.context && this.context.web) {
1101
1101
  await this.context.web.afterStep(
1102
1102
  {
1103
- attach: (data, mimeType) => { },
1103
+ attach: (data, mimeType) => {},
1104
1104
  },
1105
1105
  this.cucumberStep
1106
1106
  );
@@ -0,0 +1,305 @@
1
+ import { io } from "socket.io-client";
2
+ import { BVTRecorder } from "./bvt_recorder.js";
3
+ import { compareWithScenario } from "../code_gen/duplication_analysis.js";
4
+ import { getAppDataDir } from "../utils/app_dir.js";
5
+ import { readdir } from "fs/promises";
6
+ import socketLogger, { getErrorMessage, responseSize } from "../utils/socket_logger.js";
7
+ const port = process.env.EDITOR_PORT || 3003;
8
+ const WS_URL = process.env.WORKER_WS_SERVER_URL || "http://localhost:" + port;
9
+ const SocketIOEvents = {
10
+ REQUEST: "request",
11
+ RESPONSE: "response",
12
+ CONNECT: "connect",
13
+ DISCONNECT: "disconnect",
14
+ CREATE_ROOM: "createRoom",
15
+ JOIN_ROOM: "joinRoom",
16
+ };
17
+ class PromisifiedSocketServer {
18
+ socket;
19
+ routes;
20
+ constructor(socket, routes) {
21
+ this.socket = socket;
22
+ this.routes = routes;
23
+ }
24
+ init() {
25
+ this.socket.on(SocketIOEvents.REQUEST, async (data) => {
26
+ const { event, input, id, roomId, socketId } = data;
27
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
28
+ socketLogger.info("Received request", { event, input, id, roomId, socketId });
29
+ }
30
+ try {
31
+ const handler = this.routes[event];
32
+ if (!handler) {
33
+ socketLogger.error(`No handler found for event: ${event}`, undefined, event);
34
+ return;
35
+ }
36
+ const response = await handler(input);
37
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
38
+ socketLogger.info(`Sending response for ${event}, ${responseSize(response)} bytes`);
39
+ }
40
+ this.socket.emit(SocketIOEvents.RESPONSE, { id, value: response, roomId, socketId });
41
+ }
42
+ catch (error) {
43
+ socketLogger.error("Error handling request", {
44
+ input,
45
+ id,
46
+ roomId,
47
+ socketId,
48
+ error: error instanceof Error ? `${error.message}\n${error.stack}` : error,
49
+ }, event);
50
+ this.socket.emit(SocketIOEvents.RESPONSE, {
51
+ id,
52
+ error: {
53
+ message: error?.message,
54
+ code: error?.code,
55
+ info: error?.info,
56
+ stack: error?.stack,
57
+ },
58
+ roomId,
59
+ socketId,
60
+ });
61
+ }
62
+ });
63
+ }
64
+ }
65
+ const timeOutForFunction = async (promise, timeout = 5000) => {
66
+ const timeoutPromise = new Promise((resolve) => setTimeout(() => resolve(), timeout));
67
+ try {
68
+ const res = await Promise.race([promise, timeoutPromise]);
69
+ return res;
70
+ }
71
+ catch (error) {
72
+ socketLogger.error(error, undefined, "timeOutForFunction");
73
+ throw error;
74
+ }
75
+ };
76
+ const CLIENT_IDENTIFIER = "cucumber_client/bvt_recorder";
77
+ async function BVTRecorderInit({ envName, projectDir, roomId, TOKEN, socket = null }) {
78
+ console.log(`Connecting to ${WS_URL}`);
79
+ socket = socket || io(WS_URL);
80
+ socketLogger.init(socket, { context: "BVTRecorder", eventName: "BVTRecorder.log" });
81
+ socket.on(SocketIOEvents.CONNECT, () => {
82
+ socketLogger.info(`${roomId} Connected to BVTRecorder server`);
83
+ });
84
+ socket.on(SocketIOEvents.DISCONNECT, (reason) => {
85
+ socketLogger.info(`${roomId} Disconnected from server: ${reason}`);
86
+ });
87
+ socket.emit(SocketIOEvents.JOIN_ROOM, { id: roomId, window: CLIENT_IDENTIFIER });
88
+ const recorder = new BVTRecorder({
89
+ envName,
90
+ projectDir,
91
+ TOKEN,
92
+ sendEvent: (event, data) => {
93
+ socketLogger.info("Sending event", { event, data, roomId });
94
+ socket.emit(event, data, roomId);
95
+ },
96
+ logger: socketLogger,
97
+ });
98
+ // emit connected event for every 50 ms until connection_ack message is recieved
99
+ let connected = false;
100
+ const interval = setInterval(() => {
101
+ if (connected) {
102
+ clearInterval(interval);
103
+ return;
104
+ }
105
+ socket.emit("BVTRecorder.connected", { roomId, window: "cucumber_client/bvt_recorder" }, roomId);
106
+ }, 50);
107
+ const promisifiedSocketServer = new PromisifiedSocketServer(socket, {
108
+ "recorderWindow.connectionAck": async (input) => {
109
+ connected = true;
110
+ clearInterval(interval);
111
+ },
112
+ "recorderWindow.openBrowser": async (input) => {
113
+ return recorder
114
+ .openBrowser(input)
115
+ .then(() => {
116
+ socketLogger.info("BVTRecorder.browserOpened");
117
+ socket.emit("BVTRecorder.browserOpened", { roomId, window: "cucumber_client/bvt_recorder" });
118
+ })
119
+ .catch((e) => {
120
+ socketLogger.error(`Error opening browser: ${getErrorMessage(e)}`, undefined, "recorderWindow.openBrowser");
121
+ socket.emit("BVTRecorder.browserLaunchFailed", { roomId, window: "cucumber_client/bvt_recorder" });
122
+ });
123
+ },
124
+ "recorderWindow.closeBrowser": async (input) => {
125
+ return recorder.closeBrowser(input);
126
+ },
127
+ "recorderWindow.reOpenBrowser": async (input) => {
128
+ return recorder
129
+ .reOpenBrowser(input)
130
+ .then(() => {
131
+ socketLogger.info("BVTRecorder.browserOpened");
132
+ socket.emit("BVTRecorder.browserOpened", null, roomId);
133
+ })
134
+ .catch((e) => {
135
+ socketLogger.error(`Error reopening browser: ${getErrorMessage(e)}`, undefined, "recorderWindow.reOpenBrowser");
136
+ socket.emit("BVTRecorder.browserLaunchFailed", null, roomId);
137
+ });
138
+ },
139
+ "recorderWindow.startRecordingInput": async (input) => {
140
+ return timeOutForFunction(recorder.startRecordingInput(input));
141
+ },
142
+ "recorderWindow.stopRecordingInput": async (input) => {
143
+ return timeOutForFunction(recorder.stopRecordingInput(input));
144
+ },
145
+ "recorderWindow.startRecordingText": async (input) => {
146
+ // console.log("--- {{ }} -- : recorderWindow.startRecordingText", input);
147
+ return timeOutForFunction(recorder.startRecordingText(input));
148
+ },
149
+ "recorderWindow.stopRecordingText": async (input) => {
150
+ return timeOutForFunction(recorder.stopRecordingText(input));
151
+ },
152
+ "recorderWindow.startRecordingContext": async (input) => {
153
+ return timeOutForFunction(recorder.startRecordingContext(input));
154
+ },
155
+ "recorderWindow.stopRecordingContext": async (input) => {
156
+ return timeOutForFunction(recorder.stopRecordingContext(input));
157
+ },
158
+ "recorderWindow.runStep": async (input) => {
159
+ return recorder.runStep(input);
160
+ },
161
+ "recorderWindow.saveScenario": async (input) => {
162
+ return recorder.saveScenario(input);
163
+ },
164
+ "recorderWindow.getImplementedSteps": async (input) => {
165
+ return (await recorder.getImplementedSteps(input)).implementedSteps;
166
+ },
167
+ "recorderWindow.getImplementedScenarios": async (input) => {
168
+ return (await recorder.getImplementedSteps(input)).scenarios;
169
+ },
170
+ "recorderWindow.getCurrentChromiumPath": async () => {
171
+ return recorder.getCurrentChromiumPath();
172
+ },
173
+ "recorderWindow.overwriteTestData": async (input) => {
174
+ return await recorder.overwriteTestData(input);
175
+ },
176
+ "recorderWindow.generateStepName": async (input) => {
177
+ return recorder.generateStepName(input);
178
+ },
179
+ "recorderWindow.getFeatureAndScenario": async (input) => {
180
+ return recorder.generateScenarioAndFeatureNames(input);
181
+ },
182
+ "recorderWindow.generateCommandName": async (input) => {
183
+ return recorder.generateCommandName(input);
184
+ },
185
+ "recorderWindow.loadTestData": async (input) => {
186
+ return recorder.loadTestData(input);
187
+ },
188
+ "recorderWindow.discard": async (input) => {
189
+ return await recorder.discardTestData(input);
190
+ },
191
+ "recorderWindow.addToTestData": async (input) => {
192
+ return await recorder.addToTestData(input);
193
+ },
194
+ "recorderWindow.getScenarios": async () => {
195
+ return recorder.getScenarios();
196
+ },
197
+ "recorderWindow.setShouldTakeScreenshot": async (input) => {
198
+ return recorder.setShouldTakeScreenshot(input);
199
+ },
200
+ "recorderWindow.compareWithScenario": async ({ projectDir, scenario }, roomId) => {
201
+ return await compareWithScenario(getAppDataDir(projectDir), scenario);
202
+ },
203
+ "recorderWindow.getCommandsForImplementedStep": async (input) => {
204
+ return recorder.getCommandsForImplementedStep(input);
205
+ },
206
+ "recorderWindow.getNumberOfOccurrences": async (input) => {
207
+ return recorder.getNumberOfOccurrences(input);
208
+ },
209
+ "recorderWindow.getFakeParams": async ({ parametersMap }) => {
210
+ return recorder.fakeParams(parametersMap);
211
+ },
212
+ "recorderWindow.abortExecution": async (_) => {
213
+ return recorder.abortExecution();
214
+ },
215
+ "recorderWindow.pauseExecution": async (input) => {
216
+ return recorder.pauseExecution(input);
217
+ },
218
+ "recorderWindow.resumeExecution": async (input) => {
219
+ return recorder.resumeExecution(input);
220
+ },
221
+ "recorderWindow.loadExistingScenario": async (input) => {
222
+ return recorder.loadExistingScenario(input);
223
+ },
224
+ "recorderWindow.findRelatedTextInAllFrames": async (input) => {
225
+ return recorder.findRelatedTextInAllFrames(input);
226
+ },
227
+ "recorderWindow.getReportFolder": async (input) => {
228
+ return recorder.getReportFolder();
229
+ },
230
+ "recorderWindow.getSnapshotFiles": async (input) => {
231
+ const snapshotFolder = recorder.getSnapshotFolder();
232
+ if (snapshotFolder) {
233
+ const files = await readdir(snapshotFolder);
234
+ const ymlFiles = files.filter((file) => file.endsWith(".yml") || file.endsWith(".yaml"));
235
+ return { folder: snapshotFolder, files: ymlFiles };
236
+ }
237
+ else
238
+ return { folder: null, files: [] };
239
+ },
240
+ "recorderWindow.getCurrentPageTitle": async () => {
241
+ return await recorder.getCurrentPageTitle();
242
+ },
243
+ "recorderWindow.getCurrentPageUrl": async () => {
244
+ return recorder.getCurrentPageUrl();
245
+ },
246
+ "recorderWindow.sendAriaSnapshot": async (input) => {
247
+ const snapshot = input?.snapshot;
248
+ const deselect = input?.deselect;
249
+ if (deselect === true) {
250
+ return await recorder.deselectAriaElements();
251
+ }
252
+ if (snapshot !== null) {
253
+ return await recorder.processAriaSnapshot(snapshot);
254
+ }
255
+ },
256
+ "recorderWindow.revertMode": async () => {
257
+ await recorder.revertMode();
258
+ },
259
+ "recorderWindow.setMode": async (input) => {
260
+ const mode = input?.mode;
261
+ return recorder.setMode(mode);
262
+ },
263
+ "recorderWindow.getStepsAndCommandsForScenario": async (input) => {
264
+ return await recorder.getStepsAndCommandsForScenario(input);
265
+ },
266
+ "recorderWindow.initExecution": async (input) => {
267
+ return await recorder.initExecution(input);
268
+ },
269
+ "recorderWindow.cleanupExecution": async (input) => {
270
+ return await recorder.cleanupExecution(input);
271
+ },
272
+ "recorderWindow.resetExecution": async (input) => {
273
+ return await recorder.resetExecution(input);
274
+ },
275
+ "recorderWindow.stopRecordingNetwork": async (input) => {
276
+ return recorder.stopRecordingNetwork(input);
277
+ },
278
+ "recorderWindow.cleanup": async (input) => {
279
+ return recorder.cleanup(input);
280
+ },
281
+ "recorderWindow.getStepCodeByScenario": async (input) => {
282
+ return await recorder.getStepCodeByScenario(input);
283
+ },
284
+ "recorderWindow.setStepCodeByScenario": async (input) => {
285
+ return await recorder.setStepCodeByScenario(input);
286
+ },
287
+ "recorderWindow.getRecorderContext": async (input) => {
288
+ return await recorder.getContext();
289
+ },
290
+ "recorderWindow.addCommandToStepCode": async (input) => {
291
+ return await recorder.addCommandToStepCode(input);
292
+ },
293
+ "recorderWindow.deleteCommandFromStepCode": async (input) => {
294
+ return await recorder.deleteCommandFromStepCode(input);
295
+ },
296
+ "recorderWindow.generateLocatorSummaries": async (input) => {
297
+ return await recorder.generateLocatorSummaries(input);
298
+ }
299
+ });
300
+ socket.on("targetBrowser.command.event", async (input) => {
301
+ return recorder.onAction(input);
302
+ });
303
+ promisifiedSocketServer.init();
304
+ }
305
+ export { BVTRecorderInit };