ftmocks-utils 1.4.5 → 1.4.7
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 +117 -8
- 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,10 +40,56 @@ 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();
|
|
43
|
-
|
|
91
|
+
position.windowWidth = page.viewportSize().width;
|
|
92
|
+
position.windowHeight = page.viewportSize().height;
|
|
44
93
|
return position;
|
|
45
94
|
};
|
|
46
95
|
|
|
@@ -50,6 +99,7 @@ const runEvent = async ({
|
|
|
50
99
|
delay = 0,
|
|
51
100
|
screenshots = false,
|
|
52
101
|
screenshotsDir = null,
|
|
102
|
+
healSelectors = false,
|
|
53
103
|
}) => {
|
|
54
104
|
try {
|
|
55
105
|
console.log("➡ Running event", event);
|
|
@@ -67,6 +117,38 @@ const runEvent = async ({
|
|
|
67
117
|
fullPage: false,
|
|
68
118
|
});
|
|
69
119
|
}
|
|
120
|
+
if (healSelectors) {
|
|
121
|
+
const locator = await getLocator(page, event);
|
|
122
|
+
const position = await getSelectorPosition(page, locator);
|
|
123
|
+
const healedTarget = await healSelector(
|
|
124
|
+
page,
|
|
125
|
+
event,
|
|
126
|
+
event.target,
|
|
127
|
+
position
|
|
128
|
+
);
|
|
129
|
+
event.target = healedTarget.value;
|
|
130
|
+
const selectors = [];
|
|
131
|
+
const laterToBeAdded = [];
|
|
132
|
+
for (let i = 0; i < event.selectors.length; i++) {
|
|
133
|
+
const healedSelector = await healSelector(
|
|
134
|
+
page,
|
|
135
|
+
event,
|
|
136
|
+
event.selectors[i].value,
|
|
137
|
+
position
|
|
138
|
+
);
|
|
139
|
+
event.selectors[i].value = healedSelector.value;
|
|
140
|
+
if (healedSelector.count !== 1) {
|
|
141
|
+
laterToBeAdded.push(event.selectors[i]);
|
|
142
|
+
} else {
|
|
143
|
+
selectors.push(event.selectors[i]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
selectors.push(...laterToBeAdded);
|
|
147
|
+
if (healedTarget.count !== 1) {
|
|
148
|
+
event.target = selectors[0].value;
|
|
149
|
+
}
|
|
150
|
+
event.selectors = selectors;
|
|
151
|
+
}
|
|
70
152
|
};
|
|
71
153
|
switch (event.type) {
|
|
72
154
|
case "url":
|
|
@@ -163,9 +245,17 @@ const runEvents = async ({
|
|
|
163
245
|
delay = 1000,
|
|
164
246
|
screenshots = false,
|
|
165
247
|
screenshotsDir = null,
|
|
248
|
+
healSelectors = false,
|
|
166
249
|
}) => {
|
|
167
250
|
for (const event of events) {
|
|
168
|
-
await runEvent({
|
|
251
|
+
await runEvent({
|
|
252
|
+
page,
|
|
253
|
+
event,
|
|
254
|
+
delay,
|
|
255
|
+
screenshots,
|
|
256
|
+
screenshotsDir,
|
|
257
|
+
healSelectors,
|
|
258
|
+
});
|
|
169
259
|
}
|
|
170
260
|
};
|
|
171
261
|
|
|
@@ -504,11 +594,30 @@ const runEventsForScreenshots = async (page, ftmocksConifg, testName) => {
|
|
|
504
594
|
await page.close();
|
|
505
595
|
};
|
|
506
596
|
|
|
597
|
+
const runEventsForHealingSelectors = async (page, ftmocksConifg, testName) => {
|
|
598
|
+
const eventsFile = path.join(
|
|
599
|
+
getMockDir(ftmocksConifg),
|
|
600
|
+
`test_${nameToFolder(testName)}`,
|
|
601
|
+
`_events.json`
|
|
602
|
+
);
|
|
603
|
+
const events = JSON.parse(fs.readFileSync(eventsFile, "utf8"));
|
|
604
|
+
await runEvents({
|
|
605
|
+
page,
|
|
606
|
+
events,
|
|
607
|
+
delay: ftmocksConifg.delay || 1000,
|
|
608
|
+
healSelectors: true,
|
|
609
|
+
});
|
|
610
|
+
fs.writeFileSync(eventsFile, JSON.stringify(events, null, 2));
|
|
611
|
+
await page.waitForTimeout(1000);
|
|
612
|
+
await page.close();
|
|
613
|
+
};
|
|
614
|
+
|
|
507
615
|
module.exports = {
|
|
508
616
|
runEvents,
|
|
509
617
|
runEventsForTest,
|
|
510
618
|
runEventsInPresentationMode,
|
|
511
619
|
runEventsInTrainingMode,
|
|
512
620
|
runEventsForScreenshots,
|
|
621
|
+
runEventsForHealingSelectors,
|
|
513
622
|
runEvent,
|
|
514
623
|
};
|
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
|
};
|