ftmocks-utils 1.4.0 → 1.4.2
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 +1 -1
- package/src/event-run-utils.js +243 -0
- package/src/index.js +2 -0
package/package.json
CHANGED
package/src/event-run-utils.js
CHANGED
|
@@ -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(
|
|
@@ -119,8 +162,18 @@ const runEventsInPresentationMode = async (page, ftmocksConifg, testName) => {
|
|
|
119
162
|
currentEventIndex = currentEventIndex + 1;
|
|
120
163
|
});
|
|
121
164
|
|
|
165
|
+
await page.exposeFunction("focusOnBodyForPresentationMode", async () => {
|
|
166
|
+
await page.bringToFront();
|
|
167
|
+
});
|
|
168
|
+
|
|
122
169
|
// Inject keyboard listener into browser
|
|
123
170
|
await page.addInitScript(() => {
|
|
171
|
+
window.addEventListener("load", async () => {
|
|
172
|
+
console.log("➡ focus on body for presentation mode");
|
|
173
|
+
await window.focusOnBodyForPresentationMode();
|
|
174
|
+
window.focus();
|
|
175
|
+
document.body.focus();
|
|
176
|
+
});
|
|
124
177
|
window.addEventListener("keydown", (e) => {
|
|
125
178
|
if (e.key === "ArrowRight") {
|
|
126
179
|
console.log("➡ ArrowRight key pressed!");
|
|
@@ -132,9 +185,199 @@ const runEventsInPresentationMode = async (page, ftmocksConifg, testName) => {
|
|
|
132
185
|
await runEvent(page, events[0]);
|
|
133
186
|
};
|
|
134
187
|
|
|
188
|
+
const runEventsInTrainingMode = async (page, ftmocksConifg, testName) => {
|
|
189
|
+
let currentEventIndex = 0;
|
|
190
|
+
const eventsFile = path.join(
|
|
191
|
+
getMockDir(ftmocksConifg),
|
|
192
|
+
`test_${nameToFolder(testName)}`,
|
|
193
|
+
`_events.json`
|
|
194
|
+
);
|
|
195
|
+
const events = JSON.parse(fs.readFileSync(eventsFile, "utf8"));
|
|
196
|
+
|
|
197
|
+
// Expose Node function
|
|
198
|
+
await page.exposeFunction("getNextEvent", async () => {
|
|
199
|
+
let result = false;
|
|
200
|
+
while (!result) {
|
|
201
|
+
currentEventIndex = currentEventIndex + 1;
|
|
202
|
+
if (currentEventIndex === events.length) {
|
|
203
|
+
console.log("➡ No more events to validate!");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
result = isValidEvent(events[currentEventIndex]);
|
|
207
|
+
}
|
|
208
|
+
if (events[currentEventIndex]) {
|
|
209
|
+
const selector = await getLocator(page, events[currentEventIndex]);
|
|
210
|
+
const position = await getSelectorPosition(page, selector);
|
|
211
|
+
const element = await page.locator(selector).elementHandle();
|
|
212
|
+
return {
|
|
213
|
+
event: events[currentEventIndex],
|
|
214
|
+
selector,
|
|
215
|
+
position,
|
|
216
|
+
element,
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// Inject keyboard listener into browser
|
|
223
|
+
await page.addInitScript(async () => {
|
|
224
|
+
let currentEventInfo = null;
|
|
225
|
+
// Create and style the popover
|
|
226
|
+
const popover = document.createElement("div");
|
|
227
|
+
popover.id = "ftmocks-popover-training-mode";
|
|
228
|
+
popover.style.position = "absolute";
|
|
229
|
+
popover.style.top = "0";
|
|
230
|
+
popover.style.left = "0";
|
|
231
|
+
popover.style.minWidth = "100px";
|
|
232
|
+
popover.style.height = "58px";
|
|
233
|
+
popover.style.background = "rgba(40,40,40,0.97)";
|
|
234
|
+
popover.style.color = "#fff";
|
|
235
|
+
popover.style.display = "none";
|
|
236
|
+
popover.style.zIndex = "99999";
|
|
237
|
+
popover.style.fontFamily = "sans-serif";
|
|
238
|
+
popover.style.fontSize = "16px";
|
|
239
|
+
popover.style.textAlign = "center";
|
|
240
|
+
popover.style.lineHeight = "1.5";
|
|
241
|
+
popover.style.padding = "16px 24px";
|
|
242
|
+
popover.style.borderRadius = "8px";
|
|
243
|
+
popover.style.boxShadow = "0 2px 12px rgba(0,0,0,0.25)";
|
|
244
|
+
|
|
245
|
+
const highlighter = document.createElement("div");
|
|
246
|
+
highlighter.id = "ftmocks-highlighter-training-mode";
|
|
247
|
+
highlighter.style.position = "absolute";
|
|
248
|
+
highlighter.style.top = "0";
|
|
249
|
+
highlighter.style.left = "0";
|
|
250
|
+
highlighter.style.width = "100%";
|
|
251
|
+
highlighter.style.height = "100%";
|
|
252
|
+
highlighter.style.background = "rgba(0,0,0,0.5)";
|
|
253
|
+
highlighter.style.border = "2px solid #3fa9f5";
|
|
254
|
+
highlighter.style.display = "none";
|
|
255
|
+
highlighter.style.pointerEvents = "none";
|
|
256
|
+
|
|
257
|
+
function showPopover(eventInfo) {
|
|
258
|
+
if (!document.getElementById("ftmocks-popover-training-mode")) {
|
|
259
|
+
document.body.appendChild(popover);
|
|
260
|
+
}
|
|
261
|
+
popover.textContent = eventInfo.event.type;
|
|
262
|
+
popover.style.display = "block";
|
|
263
|
+
popover.style.left =
|
|
264
|
+
eventInfo.position.x + eventInfo.position.width / 2 + "px";
|
|
265
|
+
popover.style.top =
|
|
266
|
+
eventInfo.position.y + eventInfo.position.height + "px";
|
|
267
|
+
|
|
268
|
+
// Show highlighter
|
|
269
|
+
if (!document.getElementById("ftmocks-highlighter-training-mode")) {
|
|
270
|
+
document.body.appendChild(highlighter);
|
|
271
|
+
}
|
|
272
|
+
highlighter.style.display = "block";
|
|
273
|
+
highlighter.style.left = eventInfo.position.x + "px";
|
|
274
|
+
highlighter.style.top = eventInfo.position.y + "px";
|
|
275
|
+
highlighter.style.width = eventInfo.position.width + "px";
|
|
276
|
+
highlighter.style.height = eventInfo.position.height + "px";
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function hidePopover() {
|
|
280
|
+
popover.style.display = "none";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const initialEventRun = async () => {
|
|
284
|
+
currentEventInfo = await window.getNextEvent();
|
|
285
|
+
if (currentEventInfo) {
|
|
286
|
+
showPopover(currentEventInfo);
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const matchElement = (event, currentEventInfo) => {
|
|
291
|
+
console.log(
|
|
292
|
+
"➡ Matching element!",
|
|
293
|
+
event.target.isEqualNode(currentEventInfo?.element),
|
|
294
|
+
currentEventInfo?.element?.contains(event.target)
|
|
295
|
+
);
|
|
296
|
+
return (
|
|
297
|
+
event.target.isEqualNode(currentEventInfo?.element) ||
|
|
298
|
+
currentEventInfo?.element?.contains(event.target)
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
window.addEventListener("load", async () => {
|
|
303
|
+
await initialEventRun();
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
window.addEventListener("click", async (event) => {
|
|
307
|
+
console.log(
|
|
308
|
+
"➡ Click event triggered!",
|
|
309
|
+
event.target.isEqualNode(currentEventInfo?.element),
|
|
310
|
+
currentEventInfo?.element?.contains(event.target)
|
|
311
|
+
);
|
|
312
|
+
if (
|
|
313
|
+
currentEventInfo?.event?.type === "click" &&
|
|
314
|
+
matchElement(event, currentEventInfo)
|
|
315
|
+
) {
|
|
316
|
+
currentEventInfo = await window.getNextEvent();
|
|
317
|
+
if (currentEventInfo) {
|
|
318
|
+
showPopover(currentEventInfo);
|
|
319
|
+
} else {
|
|
320
|
+
hidePopover();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
window.addEventListener("dblclick", async (event) => {
|
|
325
|
+
if (
|
|
326
|
+
currentEventInfo?.event?.type === "dblclick" &&
|
|
327
|
+
matchElement(event, currentEventInfo)
|
|
328
|
+
) {
|
|
329
|
+
currentEventInfo = await window.getNextEvent();
|
|
330
|
+
if (currentEventInfo) {
|
|
331
|
+
showPopover(currentEventInfo);
|
|
332
|
+
} else {
|
|
333
|
+
hidePopover();
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
window.addEventListener("contextmenu", async (event) => {
|
|
338
|
+
if (
|
|
339
|
+
currentEventInfo?.event?.type === "contextmenu" &&
|
|
340
|
+
matchElement(event, currentEventInfo)
|
|
341
|
+
) {
|
|
342
|
+
currentEventInfo = await window.getNextEvent();
|
|
343
|
+
if (currentEventInfo) {
|
|
344
|
+
showPopover(currentEventInfo);
|
|
345
|
+
} else {
|
|
346
|
+
hidePopover();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
window.addEventListener("input", async (event) => {
|
|
351
|
+
if (
|
|
352
|
+
currentEventInfo?.event?.type === "input" &&
|
|
353
|
+
matchElement(event, currentEventInfo)
|
|
354
|
+
) {
|
|
355
|
+
currentEventInfo = await window.getNextEvent();
|
|
356
|
+
if (currentEventInfo) {
|
|
357
|
+
showPopover(currentEventInfo);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
window.addEventListener("keypress", async (event) => {
|
|
362
|
+
if (
|
|
363
|
+
currentEventInfo?.event?.type === "keypress" &&
|
|
364
|
+
matchElement(event, currentEventInfo)
|
|
365
|
+
) {
|
|
366
|
+
currentEventInfo = await window.getNextEvent();
|
|
367
|
+
if (currentEventInfo) {
|
|
368
|
+
showPopover(currentEventInfo);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
await runEvent(page, events[0]);
|
|
375
|
+
};
|
|
376
|
+
|
|
135
377
|
module.exports = {
|
|
136
378
|
runEvents,
|
|
137
379
|
runEventsForTest,
|
|
138
380
|
runEventsInPresentationMode,
|
|
381
|
+
runEventsInTrainingMode,
|
|
139
382
|
runEvent,
|
|
140
383
|
};
|
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
|
};
|