ftmocks-utils 1.4.0 → 1.4.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftmocks-utils",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Util functions for FtMocks",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -79,6 +79,42 @@ const runEvent = async (page, event, delay = 0) => {
79
79
  }
80
80
  };
81
81
 
82
+ const isValidEvent = (event) => {
83
+ try {
84
+ console.log("➡ Validating event", event);
85
+ switch (event?.type) {
86
+ case "url":
87
+ return true;
88
+ case "click":
89
+ return true;
90
+ case "input":
91
+ return true;
92
+ case "keypress":
93
+ return true;
94
+ case "change":
95
+ return true;
96
+ case "dblclick":
97
+ return true;
98
+ case "contextmenu":
99
+ return true;
100
+ case "hover":
101
+ return true;
102
+ case "keydown":
103
+ return true;
104
+ case "keyup":
105
+ return true;
106
+ default:
107
+ return false;
108
+ }
109
+ } catch (error) {
110
+ console.error("Error running event", {
111
+ error: error.message,
112
+ stack: error.stack,
113
+ });
114
+ }
115
+ return false;
116
+ };
117
+
82
118
  const runEvents = async (page, events, delay = 1000) => {
83
119
  for (const event of events) {
84
120
  await runEvent(page, event, delay);
@@ -95,6 +131,13 @@ const runEventsForTest = async (page, ftmocksConifg, testName) => {
95
131
  await runEvents(page, events, ftmocksConifg.delay || 1000);
96
132
  };
97
133
 
134
+ const getSelectorPosition = async (page, selector) => {
135
+ const element = await page.locator(selector).elementHandle();
136
+ const position = await element.boundingBox();
137
+ console.log("position", position);
138
+ return position;
139
+ };
140
+
98
141
  const runEventsInPresentationMode = async (page, ftmocksConifg, testName) => {
99
142
  let currentEventIndex = 1;
100
143
  const eventsFile = path.join(
@@ -132,9 +175,169 @@ const runEventsInPresentationMode = async (page, ftmocksConifg, testName) => {
132
175
  await runEvent(page, events[0]);
133
176
  };
134
177
 
178
+ const runEventsInTrainingMode = async (page, ftmocksConifg, testName) => {
179
+ let currentEventIndex = 0;
180
+ const eventsFile = path.join(
181
+ getMockDir(ftmocksConifg),
182
+ `test_${nameToFolder(testName)}`,
183
+ `_events.json`
184
+ );
185
+ const events = JSON.parse(fs.readFileSync(eventsFile, "utf8"));
186
+
187
+ // Expose Node function
188
+ await page.exposeFunction("getNextEvent", async () => {
189
+ let result = false;
190
+ while (!result) {
191
+ currentEventIndex = currentEventIndex + 1;
192
+ if (currentEventIndex === events.length) {
193
+ console.log("➡ No more events to validate!");
194
+ return;
195
+ }
196
+ result = isValidEvent(events[currentEventIndex]);
197
+ }
198
+ if (events[currentEventIndex]) {
199
+ const selector = await getLocator(page, events[currentEventIndex]);
200
+ const position = await getSelectorPosition(page, selector);
201
+ const element = await page.locator(selector).elementHandle();
202
+ return {
203
+ event: events[currentEventIndex],
204
+ selector,
205
+ position,
206
+ element,
207
+ };
208
+ }
209
+ return null;
210
+ });
211
+
212
+ // Inject keyboard listener into browser
213
+ await page.addInitScript(async () => {
214
+ let currentEventInfo = null;
215
+ // Create and style the popover
216
+ const popover = document.createElement("div");
217
+ popover.id = "ftmocks-popover-training-mode";
218
+ popover.style.position = "absolute";
219
+ popover.style.top = "0";
220
+ popover.style.left = "0";
221
+ popover.style.minWidth = "100px";
222
+ popover.style.height = "58px";
223
+ popover.style.background = "rgba(40,40,40,0.97)";
224
+ popover.style.color = "#fff";
225
+ popover.style.display = "none";
226
+ popover.style.zIndex = "99999";
227
+ popover.style.fontFamily = "sans-serif";
228
+ popover.style.fontSize = "16px";
229
+ popover.style.textAlign = "center";
230
+ popover.style.lineHeight = "1.5";
231
+ popover.style.padding = "16px 24px";
232
+ popover.style.borderRadius = "8px";
233
+ popover.style.boxShadow = "0 2px 12px rgba(0,0,0,0.25)";
234
+
235
+ function showPopover(message, position = { x: 0, y: 0 }) {
236
+ if (!document.getElementById("ftmocks-popover-training-mode")) {
237
+ document.body.appendChild(popover);
238
+ }
239
+ popover.textContent = message;
240
+ popover.style.display = "block";
241
+ popover.style.left = position.x + position.width / 2 + "px";
242
+ popover.style.top = position.y + position.height + "px";
243
+ }
244
+
245
+ function hidePopover() {
246
+ popover.style.display = "none";
247
+ }
248
+
249
+ const initialEventRun = async () => {
250
+ currentEventInfo = await window.getNextEvent();
251
+ if (currentEventInfo) {
252
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
253
+ }
254
+ };
255
+
256
+ window.addEventListener("click", async (event) => {
257
+ if (
258
+ currentEventInfo?.type === "click" &&
259
+ event.target.isEqualNode(currentEventInfo?.element) &&
260
+ currentEventInfo?.element?.contains(event.target)
261
+ ) {
262
+ currentEventInfo = await window.getNextEvent();
263
+ if (currentEventInfo) {
264
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
265
+ } else {
266
+ hidePopover();
267
+ }
268
+ } else {
269
+ initialEventRun();
270
+ }
271
+ });
272
+ window.addEventListener("dblclick", async (event) => {
273
+ if (
274
+ currentEventInfo?.type === "dblclick" &&
275
+ event.target.isEqualNode(currentEventInfo?.element) &&
276
+ currentEventInfo?.element?.contains(event.target)
277
+ ) {
278
+ currentEventInfo = await window.getNextEvent();
279
+ if (currentEventInfo) {
280
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
281
+ } else {
282
+ hidePopover();
283
+ }
284
+ } else {
285
+ initialEventRun();
286
+ }
287
+ });
288
+ window.addEventListener("contextmenu", async (event) => {
289
+ if (
290
+ currentEventInfo?.type === "contextmenu" &&
291
+ event.target.isEqualNode(currentEventInfo?.element) &&
292
+ currentEventInfo?.element?.contains(event.target)
293
+ ) {
294
+ currentEventInfo = await window.getNextEvent();
295
+ if (currentEventInfo) {
296
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
297
+ } else {
298
+ hidePopover();
299
+ }
300
+ } else {
301
+ initialEventRun();
302
+ }
303
+ });
304
+ window.addEventListener("input", async (event) => {
305
+ if (
306
+ currentEventInfo?.type === "input" &&
307
+ event.target.isEqualNode(currentEventInfo?.element) &&
308
+ currentEventInfo?.element?.contains(event.target)
309
+ ) {
310
+ currentEventInfo = await window.getNextEvent();
311
+ if (currentEventInfo) {
312
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
313
+ }
314
+ } else {
315
+ initialEventRun();
316
+ }
317
+ });
318
+ window.addEventListener("keypress", async (event) => {
319
+ if (
320
+ currentEventInfo?.type === "keypress" &&
321
+ event.target.isEqualNode(currentEventInfo?.element) &&
322
+ currentEventInfo?.element?.contains(event.target)
323
+ ) {
324
+ currentEventInfo = await window.getNextEvent();
325
+ if (currentEventInfo) {
326
+ showPopover(currentEventInfo.event.type, currentEventInfo.position);
327
+ }
328
+ } else {
329
+ initialEventRun();
330
+ }
331
+ });
332
+ });
333
+
334
+ await runEvent(page, events[0]);
335
+ };
336
+
135
337
  module.exports = {
136
338
  runEvents,
137
339
  runEventsForTest,
138
340
  runEventsInPresentationMode,
341
+ runEventsInTrainingMode,
139
342
  runEvent,
140
343
  };
package/src/index.js CHANGED
@@ -26,6 +26,7 @@ const {
26
26
  runEventsForTest,
27
27
  runEvent,
28
28
  runEventsInPresentationMode,
29
+ runEventsInTrainingMode,
29
30
  } = require("./event-run-utils");
30
31
 
31
32
  // Export functions as a module
@@ -52,4 +53,5 @@ module.exports = {
52
53
  runEventsForTest,
53
54
  runEvent,
54
55
  runEventsInPresentationMode,
56
+ runEventsInTrainingMode,
55
57
  };