ftmocks-utils 1.4.5 → 1.4.6
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 +115 -7
- package/src/index.js +2 -0
package/package.json
CHANGED
package/src/event-run-utils.js
CHANGED
|
@@ -8,18 +8,21 @@ const getLocator = async (page, event) => {
|
|
|
8
8
|
if (event && event.target && typeof page !== "undefined" && page.locator) {
|
|
9
9
|
let locator = null;
|
|
10
10
|
while (!locator) {
|
|
11
|
-
const selector =
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const selector =
|
|
12
|
+
event.target.startsWith("/") || event.target.startsWith("(/")
|
|
13
|
+
? `xpath=${event.target}`
|
|
14
|
+
: event.target;
|
|
14
15
|
try {
|
|
15
16
|
const count = await page.locator(selector).count();
|
|
16
17
|
if (count === 1) {
|
|
17
18
|
locator = selector;
|
|
18
19
|
} else {
|
|
19
20
|
for (let i = 0; i < event.selectors.length; i++) {
|
|
20
|
-
const selector =
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const selector =
|
|
22
|
+
event.selectors[i].value.startsWith("/") ||
|
|
23
|
+
event.selectors[i].value.startsWith("(/")
|
|
24
|
+
? `xpath=${event.selectors[i].value}`
|
|
25
|
+
: event.selectors[i].value;
|
|
23
26
|
const count = await page.locator(selector).count();
|
|
24
27
|
if (count === 1) {
|
|
25
28
|
locator = selector;
|
|
@@ -37,6 +40,51 @@ const getLocator = async (page, event) => {
|
|
|
37
40
|
return event.target;
|
|
38
41
|
};
|
|
39
42
|
|
|
43
|
+
const healSelector = async (page, event, selector, position) => {
|
|
44
|
+
console.log("➡ Healing selector for event", event);
|
|
45
|
+
let locator = selector;
|
|
46
|
+
if (locator.startsWith("/") || locator.startsWith("(/")) {
|
|
47
|
+
locator = `xpath=${locator}`;
|
|
48
|
+
try {
|
|
49
|
+
// INSERT_YOUR_CODE
|
|
50
|
+
// Get all elements that match the given locator
|
|
51
|
+
const elements = await page.locator(locator).elementHandles();
|
|
52
|
+
if (elements.length > 1) {
|
|
53
|
+
let index = 0;
|
|
54
|
+
for (let i = 0; i < elements.length; i++) {
|
|
55
|
+
const element = elements[i];
|
|
56
|
+
const currPosition = await element.boundingBox();
|
|
57
|
+
if (
|
|
58
|
+
currPosition.x >= position.x &&
|
|
59
|
+
currPosition.y >= position.y &&
|
|
60
|
+
currPosition.x + currPosition.width <=
|
|
61
|
+
position.x + position.width &&
|
|
62
|
+
currPosition.y + currPosition.height <= position.y + position.height
|
|
63
|
+
) {
|
|
64
|
+
index = i;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
value: `(${selector})[${index + 1}]`,
|
|
70
|
+
count: 1,
|
|
71
|
+
};
|
|
72
|
+
} else {
|
|
73
|
+
return {
|
|
74
|
+
value: selector,
|
|
75
|
+
count: elements.length,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error("Error getting locator", error, selector);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
value: selector,
|
|
84
|
+
count: 1,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
40
88
|
const getSelectorPosition = async (page, selector) => {
|
|
41
89
|
const element = await page.locator(selector).elementHandle();
|
|
42
90
|
const position = await element.boundingBox();
|
|
@@ -50,6 +98,7 @@ const runEvent = async ({
|
|
|
50
98
|
delay = 0,
|
|
51
99
|
screenshots = false,
|
|
52
100
|
screenshotsDir = null,
|
|
101
|
+
healSelectors = false,
|
|
53
102
|
}) => {
|
|
54
103
|
try {
|
|
55
104
|
console.log("➡ Running event", event);
|
|
@@ -67,6 +116,38 @@ const runEvent = async ({
|
|
|
67
116
|
fullPage: false,
|
|
68
117
|
});
|
|
69
118
|
}
|
|
119
|
+
if (healSelectors) {
|
|
120
|
+
const locator = await getLocator(page, event);
|
|
121
|
+
const position = await getSelectorPosition(page, locator);
|
|
122
|
+
const healedTarget = await healSelector(
|
|
123
|
+
page,
|
|
124
|
+
event,
|
|
125
|
+
event.target,
|
|
126
|
+
position
|
|
127
|
+
);
|
|
128
|
+
event.target = healedTarget.value;
|
|
129
|
+
const selectors = [];
|
|
130
|
+
const laterToBeAdded = [];
|
|
131
|
+
for (let i = 0; i < event.selectors.length; i++) {
|
|
132
|
+
const healedSelector = await healSelector(
|
|
133
|
+
page,
|
|
134
|
+
event,
|
|
135
|
+
event.selectors[i].value,
|
|
136
|
+
position
|
|
137
|
+
);
|
|
138
|
+
event.selectors[i].value = healedSelector.value;
|
|
139
|
+
if (healedSelector.count !== 1) {
|
|
140
|
+
laterToBeAdded.push(event.selectors[i]);
|
|
141
|
+
} else {
|
|
142
|
+
selectors.push(event.selectors[i]);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
selectors.push(...laterToBeAdded);
|
|
146
|
+
if (healedTarget.count !== 1) {
|
|
147
|
+
event.target = selectors[0].value;
|
|
148
|
+
}
|
|
149
|
+
event.selectors = selectors;
|
|
150
|
+
}
|
|
70
151
|
};
|
|
71
152
|
switch (event.type) {
|
|
72
153
|
case "url":
|
|
@@ -163,9 +244,17 @@ const runEvents = async ({
|
|
|
163
244
|
delay = 1000,
|
|
164
245
|
screenshots = false,
|
|
165
246
|
screenshotsDir = null,
|
|
247
|
+
healSelectors = false,
|
|
166
248
|
}) => {
|
|
167
249
|
for (const event of events) {
|
|
168
|
-
await runEvent({
|
|
250
|
+
await runEvent({
|
|
251
|
+
page,
|
|
252
|
+
event,
|
|
253
|
+
delay,
|
|
254
|
+
screenshots,
|
|
255
|
+
screenshotsDir,
|
|
256
|
+
healSelectors,
|
|
257
|
+
});
|
|
169
258
|
}
|
|
170
259
|
};
|
|
171
260
|
|
|
@@ -504,11 +593,30 @@ const runEventsForScreenshots = async (page, ftmocksConifg, testName) => {
|
|
|
504
593
|
await page.close();
|
|
505
594
|
};
|
|
506
595
|
|
|
596
|
+
const runEventsForHealingSelectors = async (page, ftmocksConifg, testName) => {
|
|
597
|
+
const eventsFile = path.join(
|
|
598
|
+
getMockDir(ftmocksConifg),
|
|
599
|
+
`test_${nameToFolder(testName)}`,
|
|
600
|
+
`_events.json`
|
|
601
|
+
);
|
|
602
|
+
const events = JSON.parse(fs.readFileSync(eventsFile, "utf8"));
|
|
603
|
+
await runEvents({
|
|
604
|
+
page,
|
|
605
|
+
events,
|
|
606
|
+
delay: ftmocksConifg.delay || 1000,
|
|
607
|
+
healSelectors: true,
|
|
608
|
+
});
|
|
609
|
+
fs.writeFileSync(eventsFile, JSON.stringify(events, null, 2));
|
|
610
|
+
await page.waitForTimeout(1000);
|
|
611
|
+
await page.close();
|
|
612
|
+
};
|
|
613
|
+
|
|
507
614
|
module.exports = {
|
|
508
615
|
runEvents,
|
|
509
616
|
runEventsForTest,
|
|
510
617
|
runEventsInPresentationMode,
|
|
511
618
|
runEventsInTrainingMode,
|
|
512
619
|
runEventsForScreenshots,
|
|
620
|
+
runEventsForHealingSelectors,
|
|
513
621
|
runEvent,
|
|
514
622
|
};
|
package/src/index.js
CHANGED
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
runEventsInPresentationMode,
|
|
29
29
|
runEventsInTrainingMode,
|
|
30
30
|
runEventsForScreenshots,
|
|
31
|
+
runEventsForHealingSelectors,
|
|
31
32
|
} = require("./event-run-utils");
|
|
32
33
|
|
|
33
34
|
// Export functions as a module
|
|
@@ -56,4 +57,5 @@ module.exports = {
|
|
|
56
57
|
runEventsInPresentationMode,
|
|
57
58
|
runEventsInTrainingMode,
|
|
58
59
|
runEventsForScreenshots,
|
|
60
|
+
runEventsForHealingSelectors,
|
|
59
61
|
};
|