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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ftmocks-utils",
3
- "version": "1.4.5",
3
+ "version": "1.4.7",
4
4
  "description": "Util functions for FtMocks",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -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 = event.target.startsWith("/")
12
- ? `xpath=${event.target}`
13
- : event.target;
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 = event.selectors[i].value.startsWith("/")
21
- ? `xpath=${event.selectors[i].value}`
22
- : event.selectors[i].value;
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
- console.log("position", position);
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({ page, event, delay, screenshots, screenshotsDir });
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
  };