@dev-blinq/cucumber_client 1.0.1347-dev → 1.0.1347-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 (53) hide show
  1. package/bin/assets/bundled_scripts/recorder.js +107 -107
  2. package/bin/assets/preload/css_gen.js +10 -10
  3. package/bin/assets/preload/recorderv3.js +3 -1
  4. package/bin/assets/preload/toolbar.js +27 -29
  5. package/bin/assets/preload/unique_locators.js +1 -1
  6. package/bin/assets/preload/yaml.js +288 -275
  7. package/bin/assets/scripts/aria_snapshot.js +223 -220
  8. package/bin/assets/scripts/dom_attr.js +329 -329
  9. package/bin/assets/scripts/dom_parent.js +169 -174
  10. package/bin/assets/scripts/event_utils.js +94 -94
  11. package/bin/assets/scripts/pw.js +2050 -1949
  12. package/bin/assets/scripts/recorder.js +12 -22
  13. package/bin/assets/scripts/snapshot_capturer.js +153 -146
  14. package/bin/assets/scripts/unique_locators.js +941 -815
  15. package/bin/assets/scripts/yaml.js +796 -783
  16. package/bin/assets/templates/_hooks_template.txt +41 -0
  17. package/bin/assets/templates/utils_template.txt +2 -45
  18. package/bin/client/apiTest/apiTest.js +6 -0
  19. package/bin/client/cli_helpers.js +11 -13
  20. package/bin/client/code_cleanup/utils.js +5 -1
  21. package/bin/client/code_gen/api_codegen.js +2 -2
  22. package/bin/client/code_gen/code_inversion.js +112 -4
  23. package/bin/client/code_gen/page_reflection.js +839 -906
  24. package/bin/client/code_gen/playwright_codeget.js +25 -11
  25. package/bin/client/cucumber/feature.js +89 -27
  26. package/bin/client/cucumber/feature_data.js +2 -2
  27. package/bin/client/cucumber/project_to_document.js +9 -3
  28. package/bin/client/cucumber/steps_definitions.js +6 -3
  29. package/bin/client/cucumber_selector.js +17 -1
  30. package/bin/client/local_agent.js +6 -5
  31. package/bin/client/parse_feature_file.js +23 -26
  32. package/bin/client/playground/projects/env.json +2 -2
  33. package/bin/client/project.js +186 -196
  34. package/bin/client/recorderv3/bvt_recorder.js +202 -89
  35. package/bin/client/recorderv3/implemented_steps.js +22 -12
  36. package/bin/client/recorderv3/index.js +59 -54
  37. package/bin/client/recorderv3/network.js +22 -5
  38. package/bin/client/recorderv3/scriptTest.js +1 -1
  39. package/bin/client/recorderv3/services.js +4 -16
  40. package/bin/client/recorderv3/step_runner.js +318 -209
  41. package/bin/client/recorderv3/step_utils.js +475 -16
  42. package/bin/client/recorderv3/update_feature.js +32 -30
  43. package/bin/client/recording.js +1 -0
  44. package/bin/client/run_cucumber.js +1 -1
  45. package/bin/client/scenario_report.js +0 -5
  46. package/bin/client/test_scenario.js +0 -1
  47. package/bin/client/upload-service.js +3 -2
  48. package/bin/client/utils/socket_logger.js +132 -0
  49. package/bin/index.js +2 -0
  50. package/bin/logger.js +3 -2
  51. package/bin/min/consoleApi.min.cjs +2 -3
  52. package/bin/min/injectedScript.min.cjs +16 -16
  53. package/package.json +21 -12
@@ -4,10 +4,23 @@ import { BVTRecorder } from "./bvt_recorder.js";
4
4
  import { compareWithScenario } from "../code_gen/duplication_analysis.js";
5
5
  import { getAppDataDir } from "./app_dir.js";
6
6
  import { readdir } from "fs/promises";
7
+ import socketLogger from "../utils/socket_logger.js";
7
8
 
8
9
  let port = process.env.EDITOR_PORT || 3003;
9
10
  const WS_URL = "http://localhost:" + port;
10
11
 
12
+ const responseSize = (response) => {
13
+ try {
14
+ if (typeof response !== "string") {
15
+ return new Blob([JSON.stringify(response)]).size;
16
+ } else {
17
+ return new Blob([response]).size;
18
+ }
19
+ } catch {
20
+ return -1;
21
+ }
22
+ };
23
+
11
24
  class PromisifiedSocketServer {
12
25
  constructor(socket, routes) {
13
26
  this.socket = socket;
@@ -16,7 +29,9 @@ class PromisifiedSocketServer {
16
29
  init() {
17
30
  this.socket.on("request", async (data) => {
18
31
  const { event, input, id, roomId, socketId } = data;
19
- console.log("request", { event, input, id, roomId, socketId });
32
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
33
+ socketLogger.info("Received request", { event, input, id, roomId, socketId });
34
+ }
20
35
  try {
21
36
  const handler = this.routes[event];
22
37
  if (!handler) {
@@ -24,17 +39,19 @@ class PromisifiedSocketServer {
24
39
  return;
25
40
  }
26
41
  const response = await handler(input);
27
- // console.log("response", { id, value: response, roomId, socketId });
42
+ if (event !== "recorderWindow.getCurrentChromiumPath") {
43
+ socketLogger.info(`Sending response for ${event}, ${responseSize(response)} bytes`);
44
+ }
28
45
  this.socket.emit("response", { id, value: response, roomId, socketId });
29
46
  } catch (error) {
30
- console.log("request", JSON.stringify({ event, input, id, roomId, socketId }));
31
- console.error("response", { id, error, roomId, socketId });
32
- // console.error({
33
- // message: error?.message,
34
- // code: error?.code,
35
- // info: error?.info,
36
- // stack: error?.stack,
37
- // })
47
+ socketLogger.error("Error handling request", {
48
+ event,
49
+ input,
50
+ id,
51
+ roomId,
52
+ socketId,
53
+ error: error instanceof Error ? `${error.message}\n${error.stack}` : error,
54
+ });
38
55
  this.socket.emit("response", {
39
56
  id,
40
57
  error: {
@@ -51,45 +68,17 @@ class PromisifiedSocketServer {
51
68
  }
52
69
  }
53
70
 
54
- function memorySizeOf(obj) {
55
- var bytes = 0;
56
-
57
- function sizeOf(obj) {
58
- if (obj !== null && obj !== undefined) {
59
- switch (typeof obj) {
60
- case "number":
61
- bytes += 8;
62
- break;
63
- case "string":
64
- bytes += obj.length * 2;
65
- break;
66
- case "boolean":
67
- bytes += 4;
68
- break;
69
- case "object":
70
- var objClass = Object.prototype.toString.call(obj).slice(8, -1);
71
- if (objClass === "Object" || objClass === "Array") {
72
- for (var key in obj) {
73
- if (!obj.hasOwnProperty(key)) continue;
74
- sizeOf(obj[key]);
75
- }
76
- } else bytes += obj.toString().length * 2;
77
- break;
78
- }
79
- }
80
- return bytes;
81
- }
82
- return sizeOf(obj);
83
- }
84
-
85
71
  const init = ({ envName, projectDir, roomId, TOKEN }) => {
86
- console.log("connecting to " + WS_URL);
72
+ console.log("Connecting to " + WS_URL);
87
73
  const socket = io(WS_URL);
74
+ socketLogger.init(socket, { context: "BVTRecorder", eventName: "BVTRecorder.log" });
88
75
  socket.on("connect", () => {
89
- console.log("connected to server");
76
+ socketLogger.info("Connected to BVTRecorder server");
77
+ console.log("Connected to BVTRecorder server");
90
78
  });
91
79
  socket.on("disconnect", () => {
92
- console.log("disconnected from server");
80
+ socketLogger.info("Disconnected from server");
81
+ console.log("Disconnected from server");
93
82
  });
94
83
  socket.emit("joinRoom", { id: roomId, window: "cucumber_client/bvt_recorder" });
95
84
  const recorder = new BVTRecorder({
@@ -97,19 +86,19 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
97
86
  projectDir,
98
87
  TOKEN,
99
88
  sendEvent: (event, data) => {
100
- console.log("Size of data", memorySizeOf(data), "bytes");
101
- console.log("----", event, data, "roomId", roomId);
89
+ socketLogger.info("Sending event", { event, data, roomId });
102
90
  socket.emit(event, data, roomId);
103
- console.log("Successfully sent event", event, "to room", roomId);
104
91
  },
92
+ logger: socketLogger,
105
93
  });
106
94
  recorder
107
95
  .openBrowser()
108
96
  .then(() => {
109
- // console.log("BVTRecorder.browserOpened");
97
+ socketLogger.info("BVTRecorder.browserOpened");
110
98
  socket.emit("BVTRecorder.browserOpened", null, roomId);
111
99
  })
112
100
  .catch((e) => {
101
+ socketLogger.error("BVTRecorder.browserLaunchFailed", e);
113
102
  socket.emit("BVTRecorder.browserLaunchFailed", e, roomId);
114
103
  });
115
104
  const timeOutForFunction = async (promise, timeout = 5000) => {
@@ -120,6 +109,7 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
120
109
  return res;
121
110
  } catch (error) {
122
111
  console.error(error);
112
+ socketLogger.error(error);
123
113
  throw error;
124
114
  }
125
115
  };
@@ -129,10 +119,13 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
129
119
  return recorder
130
120
  .openBrowser(input)
131
121
  .then(() => {
122
+ socketLogger.info("BVTRecorder.browserOpened");
123
+ console.info("BVTRecorder.browserOpened");
132
124
  socket.emit("BVTRecorder.browserOpened", { roomId, window: "cucumber_client/bvt_recorder" });
133
125
  })
134
126
  .catch((e) => {
135
- console.error(e);
127
+ socketLogger.error("Error opening browser", e);
128
+ console.error("BVTRecorder.browserLaunchFailed", e);
136
129
  socket.emit("BVTRecorder.browserLaunchFailed", { roomId, window: "cucumber_client/bvt_recorder" });
137
130
  });
138
131
  },
@@ -143,10 +136,13 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
143
136
  return recorder
144
137
  .reOpenBrowser(input)
145
138
  .then(() => {
146
- // console.log("BVTRecorder.browserOpened");
139
+ socketLogger.info("BVTRecorder.browserOpened");
140
+ console.log("BVTRecorder.browserOpened");
147
141
  socket.emit("BVTRecorder.browserOpened", null, roomId);
148
142
  })
149
- .catch(() => {
143
+ .catch((e) => {
144
+ socketLogger.info("BVTRecorder.browserLaunchFailed");
145
+ console.error("BVTRecorder.browserLaunchFailed", e);
150
146
  socket.emit("BVTRecorder.browserLaunchFailed", null, roomId);
151
147
  });
152
148
  },
@@ -224,9 +220,18 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
224
220
  "recorderWindow.getNumberOfOccurrences": async (input) => {
225
221
  return recorder.getNumberOfOccurrences(input);
226
222
  },
223
+ "recorderWindow.getFakeParams": async ({ parametersMap }) => {
224
+ return recorder.fakeParams(parametersMap);
225
+ },
227
226
  "recorderWindow.abortExecution": async (input) => {
228
227
  return recorder.abortExecution(input);
229
228
  },
229
+ "recorderWindow.pauseExecution": async (input) => {
230
+ return recorder.pauseExecution(input);
231
+ },
232
+ "recorderWindow.resumeExecution": async (input) => {
233
+ return recorder.resumeExecution(input);
234
+ },
230
235
  "recorderWindow.loadExistingScenario": async (input) => {
231
236
  return recorder.loadExistingScenario(input);
232
237
  },
@@ -239,9 +244,7 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
239
244
  "recorderWindow.getSnapshotFiles": async (input) => {
240
245
  const snapshotFolder = recorder.getSnapshotFolder();
241
246
  if (snapshotFolder) {
242
- // Get the list of filenames in the snapshot folder
243
247
  const files = await readdir(snapshotFolder);
244
- // Filter the files to only include .png files
245
248
  const ymlFiles = files.filter((file) => file.endsWith(".yml") || file.endsWith(".yaml"));
246
249
  return { folder: snapshotFolder, files: ymlFiles };
247
250
  } else return { folder: null, files: [] };
@@ -284,6 +287,9 @@ const init = ({ envName, projectDir, roomId, TOKEN }) => {
284
287
  "recorderWindow.resetExecution": async (input) => {
285
288
  return await recorder.resetExecution(input);
286
289
  },
290
+ "recorderWindow.stopRecordingNetwork": async (input) => {
291
+ return recorder.stopRecordingNetwork(input);
292
+ },
287
293
  });
288
294
  socket.on("targetBrowser.command.event", async (input) => {
289
295
  return recorder.onAction(input);
@@ -310,7 +316,6 @@ try {
310
316
  showUsage(error, usage);
311
317
  }
312
318
  try {
313
- // console.log({ envName, projectDir, featureName, scenarioName, stepIndex, roomId })
314
319
  init({
315
320
  envName,
316
321
  projectDir,
@@ -1,8 +1,18 @@
1
+ /**
2
+ * @typedef {Object} NetworkEvent
3
+ * @property {import('playwright').Request} request
4
+ * @property {import('playwright').Response|null} response
5
+ * @property {string} id
6
+ * @property {number} timestamp
7
+ * @property {string} status - 'completed', 'failed'
8
+ */
9
+
1
10
  class NetworkMonitor {
2
11
  constructor() {
3
12
  this.networkId = 0;
4
- this.networkEvents = new Map();
13
+ /** @type {Map<string, NetworkEvent>} */
5
14
  this.requestIdMap = new Map();
15
+ this.networkEvents = new Map();
6
16
  /** @type {Map<import('playwright').Page, {responseListener: Function, requestFailedListener: Function}>} */
7
17
  this.pageListeners = new Map();
8
18
  }
@@ -12,7 +22,6 @@ class NetworkMonitor {
12
22
  * @param {import('playwright').Page} page
13
23
  */
14
24
  addNetworkEventListener(page) {
15
-
16
25
  // Create the listener functions
17
26
  const responseListener = async (response) => {
18
27
  const request = response.request();
@@ -201,7 +210,6 @@ class NetworkMonitor {
201
210
  // Try to get response body safely (only for successful responses)
202
211
  if (response && networkEvent.status === "completed") {
203
212
  try {
204
-
205
213
  const isBinary =
206
214
  !response.headers()["content-type"]?.includes("application/json") &&
207
215
  !response.headers()["content-type"]?.includes("text");
@@ -229,7 +237,6 @@ class NetworkMonitor {
229
237
  marshalledEvent.failureReason = request.failure()?.errorText || "Unknown error";
230
238
  }
231
239
 
232
-
233
240
  console.log("Marshalled network event:", marshalledEvent);
234
241
 
235
242
  return marshalledEvent;
@@ -246,7 +253,18 @@ class NetworkMonitor {
246
253
  }
247
254
  }
248
255
 
256
+ /**
257
+ *@returns {Promise<Object[]>}
258
+ * Get all marshalled network events
259
+ * This is useful for sending to the server or saving to a file.
260
+ * */
261
+ async getAllMarshalledNetworkEvents() {
262
+ const events = this.getAllNetworkEvents();
263
+ const marshalledEvents = await Promise.all(events.map((event) => this.marshallNetworkEvent(event)));
264
+ return marshalledEvents;
265
+ }
249
266
 
267
+ /**
250
268
  * Get marshalled network events since this ID
251
269
  * @returns {Promise<Object[]>}
252
270
  * @param {number} sinceId
@@ -263,7 +281,6 @@ class NetworkMonitor {
263
281
  * @param {number} endId
264
282
  * @returns {Promise<Object[]>}
265
283
  */
266
-
267
284
  async getMarshalledNetworkEventsInRange(startId, endId) {
268
285
  const events = this.getNetworkEventsInRange(startId, endId);
269
286
  const marshalledEvents = await Promise.all(events.map((event) => this.marshallNetworkEvent(event)));
@@ -2,4 +2,4 @@
2
2
 
3
3
  // getImplementedSteps('/Users/yash/Library/Application Support/blinq.io/67d7c7ffb099a8da65d7e204').then((implementedSteps) => {
4
4
  // console.log(JSON.stringify(implementedSteps, null, 2));
5
- // });
5
+ // });
@@ -15,20 +15,7 @@ export class NamesService {
15
15
  if (!screenshot && commands.length > 1) {
16
16
  screenshot = this.screenshotMap.get(commands[commands.length - 2].inputID);
17
17
  }
18
- this.logger.info(
19
- "data: " +
20
- JSON.stringify(
21
- {
22
- commands,
23
- stepsNames,
24
- parameters,
25
- map,
26
- },
27
- null,
28
- 2
29
- )
30
- );
31
- // get screenshot for the last command
18
+
32
19
  const url = `${getRunsServiceBaseURL()}/generate-step-information/generate`;
33
20
  const TIMEOUT = 120; // 2 minutes
34
21
  const { data } = await axiosClient({
@@ -38,7 +25,7 @@ export class NamesService {
38
25
  commands,
39
26
  stepsNames,
40
27
  parameters,
41
- screenshot,
28
+ //screenshot,
42
29
  map,
43
30
  },
44
31
  headers: {
@@ -65,6 +52,7 @@ export class NamesService {
65
52
  }
66
53
  } catch (error) {
67
54
  if (i === TIMEOUT - 1) {
55
+ this.logger.error("Timeout while generating step details: ", error);
68
56
  console.error("Timeout while generating step details: ", error);
69
57
  }
70
58
  }
@@ -96,7 +84,6 @@ export class NamesService {
96
84
  scenario: scenarioAsText,
97
85
  };
98
86
 
99
- this.logger.info("data: " + JSON.stringify(genObject, null, 2));
100
87
  // get screenshot for the last command
101
88
  const url = `${getRunsServiceBaseURL()}/generate-step-information/generate_scenario_feature`;
102
89
  const TIMEOUT = 120; // 2 minutes
@@ -140,6 +127,7 @@ export class NamesService {
140
127
  if (result.status !== 200) {
141
128
  return { success: false, message: "Error while generating step details" };
142
129
  }
130
+
143
131
  return result.data;
144
132
  }
145
133