automation_model 1.0.406-dev → 1.0.406-stage

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.
@@ -2,9 +2,9 @@
2
2
  import { expect } from "@playwright/test";
3
3
  import dayjs from "dayjs";
4
4
  import fs from "fs";
5
+ import { Jimp } from "jimp";
5
6
  import path from "path";
6
7
  import reg_parser from "regex-parser";
7
- import sharp from "sharp";
8
8
  import { findDateAlternatives, findNumberAlternatives } from "./analyze_helper.js";
9
9
  import { getDateTimeValue } from "./date_time.js";
10
10
  import drawRectangle from "./drawRect.js";
@@ -14,6 +14,8 @@ import objectPath from "object-path";
14
14
  import { decrypt } from "./utils.js";
15
15
  import csv from "csv-parser";
16
16
  import { Readable } from "node:stream";
17
+ import readline from "readline";
18
+ import { getContext } from "./init_browser.js";
17
19
  const Types = {
18
20
  CLICK: "click_element",
19
21
  NAVIGATE: "navigate",
@@ -39,16 +41,21 @@ const Types = {
39
41
  SET_VIEWPORT: "set_viewport",
40
42
  VERIFY_VISUAL: "verify_visual",
41
43
  LOAD_DATA: "load_data",
44
+ SET_INPUT: "set_input",
42
45
  };
46
+ export const apps = {};
43
47
  class StableBrowser {
44
- constructor(browser, page, logger = null, context = null) {
48
+ constructor(browser, page, logger = null, context = null, world = null) {
45
49
  this.browser = browser;
46
50
  this.page = page;
47
51
  this.logger = logger;
48
52
  this.context = context;
53
+ this.world = world;
49
54
  this.project_path = null;
50
55
  this.webLogFile = null;
56
+ this.networkLogger = null;
51
57
  this.configuration = null;
58
+ this.appName = "main";
52
59
  if (!this.logger) {
53
60
  this.logger = console;
54
61
  }
@@ -74,23 +81,34 @@ class StableBrowser {
74
81
  this.logger.error("unable to read ai_config.json");
75
82
  }
76
83
  const logFolder = path.join(this.project_path, "logs", "web");
77
- this.webLogFile = this.getWebLogFile(logFolder);
78
- this.registerConsoleLogListener(page, context, this.webLogFile);
79
- this.registerRequestListener();
84
+ this.world = world;
80
85
  context.pages = [this.page];
81
86
  context.pageLoading = { status: false };
87
+ this.registerEventListeners(this.context);
88
+ }
89
+ registerEventListeners(context) {
90
+ this.registerConsoleLogListener(this.page, context);
91
+ this.registerRequestListener(this.page, context, this.webLogFile);
92
+ if (!context.pageLoading) {
93
+ context.pageLoading = { status: false };
94
+ }
82
95
  context.playContext.on("page", async function (page) {
83
96
  context.pageLoading.status = true;
84
97
  this.page = page;
85
98
  context.page = page;
86
99
  context.pages.push(page);
87
100
  page.on("close", async () => {
88
- if (this.context && this.context.pages && this.context.pages.length > 0) {
101
+ if (this.context && this.context.pages && this.context.pages.length > 1) {
89
102
  this.context.pages.pop();
90
103
  this.page = this.context.pages[this.context.pages.length - 1];
91
104
  this.context.page = this.page;
92
- let title = await this.page.title();
93
- console.log("Switched to page " + title);
105
+ try {
106
+ let title = await this.page.title();
107
+ console.log("Switched to page " + title);
108
+ }
109
+ catch (error) {
110
+ console.error("Error on page close", error);
111
+ }
94
112
  }
95
113
  });
96
114
  try {
@@ -103,6 +121,36 @@ class StableBrowser {
103
121
  context.pageLoading.status = false;
104
122
  }.bind(this));
105
123
  }
124
+ async switchApp(appName) {
125
+ // check if the current app (this.appName) is the same as the new app
126
+ if (this.appName === appName) {
127
+ return;
128
+ }
129
+ let navigate = false;
130
+ if (!apps[appName]) {
131
+ let newContext = await getContext(null, false, this.logger, appName, false, this);
132
+ navigate = true;
133
+ apps[appName] = {
134
+ context: newContext,
135
+ browser: newContext.browser,
136
+ page: newContext.page,
137
+ };
138
+ }
139
+ const tempContext = {};
140
+ this._copyContext(this, tempContext);
141
+ this._copyContext(apps[appName], this);
142
+ apps[this.appName] = tempContext;
143
+ this.appName = appName;
144
+ if (navigate) {
145
+ await this.goto(this.context.environment.baseUrl);
146
+ await this.waitForPageLoad();
147
+ }
148
+ }
149
+ _copyContext(from, to) {
150
+ to.browser = from.browser;
151
+ to.page = from.page;
152
+ to.context = from.context;
153
+ }
106
154
  getWebLogFile(logFolder) {
107
155
  if (!fs.existsSync(logFolder)) {
108
156
  fs.mkdirSync(logFolder, { recursive: true });
@@ -114,37 +162,63 @@ class StableBrowser {
114
162
  const fileName = nextIndex + ".json";
115
163
  return path.join(logFolder, fileName);
116
164
  }
117
- registerConsoleLogListener(page, context, logFile) {
165
+ registerConsoleLogListener(page, context) {
118
166
  if (!this.context.webLogger) {
119
167
  this.context.webLogger = [];
120
168
  }
121
169
  page.on("console", async (msg) => {
122
- this.context.webLogger.push({
170
+ var _a;
171
+ const obj = {
123
172
  type: msg.type(),
124
173
  text: msg.text(),
125
174
  location: msg.location(),
126
175
  time: new Date().toISOString(),
127
- });
128
- await fs.promises.writeFile(logFile, JSON.stringify(this.context.webLogger, null, 2));
176
+ };
177
+ this.context.webLogger.push(obj);
178
+ (_a = this.world) === null || _a === void 0 ? void 0 : _a.attach(JSON.stringify(obj), { mediaType: "application/json+log" });
129
179
  });
130
180
  }
131
- registerRequestListener() {
132
- this.page.on("request", async (data) => {
181
+ registerRequestListener(page, context, logFile) {
182
+ if (!this.context.networkLogger) {
183
+ this.context.networkLogger = [];
184
+ }
185
+ page.on("request", async (data) => {
186
+ var _a;
187
+ const startTime = new Date().getTime();
133
188
  try {
134
- const pageUrl = new URL(this.page.url());
189
+ const pageUrl = new URL(page.url());
135
190
  const requestUrl = new URL(data.url());
136
191
  if (pageUrl.hostname === requestUrl.hostname) {
137
192
  const method = data.method();
138
- if (method === "POST" || method === "GET" || method === "PUT" || method === "DELETE" || method === "PATCH") {
193
+ if (["POST", "GET", "PUT", "DELETE", "PATCH"].includes(method)) {
139
194
  const token = await data.headerValue("Authorization");
140
195
  if (token) {
141
- this.context.authtoken = token;
196
+ context.authtoken = token;
142
197
  }
143
198
  }
144
199
  }
200
+ const response = await data.response();
201
+ const endTime = new Date().getTime();
202
+ const obj = {
203
+ url: data.url(),
204
+ method: data.method(),
205
+ postData: data.postData(),
206
+ error: data.failure() ? data.failure().errorText : null,
207
+ duration: endTime - startTime,
208
+ startTime,
209
+ };
210
+ context.networkLogger.push(obj);
211
+ (_a = this.world) === null || _a === void 0 ? void 0 : _a.attach(JSON.stringify(obj), { mediaType: "application/json+network" });
145
212
  }
146
213
  catch (error) {
147
214
  console.error("Error in request listener", error);
215
+ context.networkLogger.push({
216
+ error: "not able to listen",
217
+ message: error.message,
218
+ stack: error.stack,
219
+ time: new Date().toISOString(),
220
+ });
221
+ // await fs.promises.writeFile(logFile, JSON.stringify(context.networkLogger, null, 2));
148
222
  }
149
223
  });
150
224
  }
@@ -214,9 +288,7 @@ class StableBrowser {
214
288
  }
215
289
  _getLocator(locator, scope, _params) {
216
290
  locator = this._fixLocatorUsingParams(locator, _params);
217
- if (locator.type === "pw_selector") {
218
- return scope.locator(locator.selector);
219
- }
291
+ let locatorReturn;
220
292
  if (locator.role) {
221
293
  if (locator.role[1].nameReg) {
222
294
  locator.role[1].name = reg_parser(locator.role[1].nameReg);
@@ -225,20 +297,42 @@ class StableBrowser {
225
297
  // if (locator.role[1].name) {
226
298
  // locator.role[1].name = this._fixUsingParams(locator.role[1].name, _params);
227
299
  // }
228
- return scope.getByRole(locator.role[0], locator.role[1]);
300
+ locatorReturn = scope.getByRole(locator.role[0], locator.role[1]);
229
301
  }
230
302
  if (locator.css) {
231
- return scope.locator(locator.css);
303
+ locatorReturn = scope.locator(locator.css);
232
304
  }
233
- if ((locator === null || locator === void 0 ? void 0 : locator.engine) && (locator === null || locator === void 0 ? void 0 : locator.score) <= 520) {
234
- let selector = locator.selector.replace(/"/g, '\\"');
235
- if (locator.engine === "internal:att") {
236
- selector = `[${selector}]`;
305
+ // handle role/name locators
306
+ // locator.selector will be something like: textbox[name="Username"i]
307
+ if (locator.engine === "internal:role") {
308
+ // extract the role, name and the i/s flags using regex
309
+ const match = locator.selector.match(/(.*)\[(.*)="(.*)"(.*)\]/);
310
+ if (match) {
311
+ const role = match[1];
312
+ const name = match[3];
313
+ const flags = match[4];
314
+ locatorReturn = scope.getByRole(role, { name }, { exact: flags === "i" });
237
315
  }
238
- const locator = scope.locator(`${locator.engine}="${selector}"`);
239
- return locator;
240
316
  }
241
- throw new Error("unknown locator type");
317
+ if (locator === null || locator === void 0 ? void 0 : locator.engine) {
318
+ if (locator.engine === "css") {
319
+ locatorReturn = scope.locator(locator.selector);
320
+ }
321
+ else {
322
+ let selector = locator.selector;
323
+ if (locator.engine === "internal:attr") {
324
+ if (!selector.startsWith("[")) {
325
+ selector = `[${selector}]`;
326
+ }
327
+ }
328
+ locatorReturn = scope.locator(`${locator.engine}=${selector}`);
329
+ }
330
+ }
331
+ if (!locatorReturn) {
332
+ console.error(locator);
333
+ throw new Error("Locator undefined");
334
+ }
335
+ return locatorReturn;
242
336
  }
243
337
  async _locateElmentByTextClimbCss(scope, text, climb, css, _params) {
244
338
  let result = await this._locateElementByText(scope, this._fixUsingParams(text, _params), "*", false, true, _params);
@@ -449,6 +543,8 @@ class StableBrowser {
449
543
  if (result.foundElements.length > 0) {
450
544
  let dialogCloseLocator = result.foundElements[0].locator;
451
545
  await dialogCloseLocator.click();
546
+ // wait for the dialog to close
547
+ await dialogCloseLocator.waitFor({ state: "hidden" });
452
548
  return { rerun: true };
453
549
  }
454
550
  }
@@ -457,7 +553,7 @@ class StableBrowser {
457
553
  }
458
554
  async _locate(selectors, info, _params, timeout = 30000) {
459
555
  for (let i = 0; i < 3; i++) {
460
- info.log += "attempt " + i + ": totoal locators " + selectors.locators.length + "\n";
556
+ info.log += "attempt " + i + ": total locators " + selectors.locators.length + "\n";
461
557
  for (let j = 0; j < selectors.locators.length; j++) {
462
558
  let selector = selectors.locators[j];
463
559
  info.log += "searching for locator " + j + ":" + JSON.stringify(selector) + "\n";
@@ -477,9 +573,30 @@ class StableBrowser {
477
573
  //let arrayMode = Array.isArray(selectors);
478
574
  let scope = this.page;
479
575
  if (selectors.iframe_src || selectors.frameLocators) {
576
+ const findFrame = (frame, framescope) => {
577
+ for (let i = 0; i < frame.selectors.length; i++) {
578
+ let frameLocator = frame.selectors[i];
579
+ if (frameLocator.css) {
580
+ framescope = framescope.frameLocator(frameLocator.css);
581
+ if (frameLocator.index) {
582
+ framescope = framescope.nth(frameLocator.index);
583
+ }
584
+ break;
585
+ }
586
+ }
587
+ if (frame.children) {
588
+ return findFrame(frame.children, framescope);
589
+ }
590
+ return framescope;
591
+ };
480
592
  info.log += "searching for iframe " + selectors.iframe_src + "/" + selectors.frameLocators + "\n";
481
593
  while (true) {
482
594
  let frameFound = false;
595
+ if (selectors.nestFrmLoc) {
596
+ scope = findFrame(selectors.nestFrmLoc, scope);
597
+ frameFound = true;
598
+ break;
599
+ }
483
600
  if (selectors.frameLocators) {
484
601
  for (let i = 0; i < selectors.frameLocators.length; i++) {
485
602
  let frameLocator = selectors.frameLocators[i];
@@ -643,6 +760,9 @@ class StableBrowser {
643
760
  async click(selectors, _params, options = {}, world = null) {
644
761
  this._validateSelectors(selectors);
645
762
  const startTime = Date.now();
763
+ if (options && options.context) {
764
+ selectors.locators[0].text = options.context;
765
+ }
646
766
  const info = {};
647
767
  info.log = "***** click on " + selectors.element_name + " *****\n";
648
768
  info.operation = "click";
@@ -656,14 +776,14 @@ class StableBrowser {
656
776
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
657
777
  try {
658
778
  await this._highlightElements(element);
659
- await element.click({ timeout: 5000 });
779
+ await element.click();
660
780
  await new Promise((resolve) => setTimeout(resolve, 1000));
661
781
  }
662
782
  catch (e) {
663
783
  // await this.closeUnexpectedPopups();
664
784
  info.log += "click failed, will try again" + "\n";
665
785
  element = await this._locate(selectors, info, _params);
666
- await element.click({ timeout: 10000, force: true });
786
+ await element.dispatchEvent("click");
667
787
  await new Promise((resolve) => setTimeout(resolve, 1000));
668
788
  }
669
789
  await this.waitForPageLoad();
@@ -716,7 +836,7 @@ class StableBrowser {
716
836
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
717
837
  try {
718
838
  await this._highlightElements(element);
719
- await element.setChecked(checked, { timeout: 5000 });
839
+ await element.setChecked(checked);
720
840
  await new Promise((resolve) => setTimeout(resolve, 1000));
721
841
  }
722
842
  catch (e) {
@@ -780,7 +900,7 @@ class StableBrowser {
780
900
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
781
901
  try {
782
902
  await this._highlightElements(element);
783
- await element.hover({ timeout: 10000 });
903
+ await element.hover();
784
904
  await new Promise((resolve) => setTimeout(resolve, 1000));
785
905
  }
786
906
  catch (e) {
@@ -842,7 +962,7 @@ class StableBrowser {
842
962
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
843
963
  try {
844
964
  await this._highlightElements(element);
845
- await element.selectOption(values, { timeout: 5000 });
965
+ await element.selectOption(values);
846
966
  }
847
967
  catch (e) {
848
968
  //await this.closeUnexpectedPopups();
@@ -951,6 +1071,72 @@ class StableBrowser {
951
1071
  });
952
1072
  }
953
1073
  }
1074
+ async setInputValue(selectors, value, _params = null, options = {}, world = null) {
1075
+ // set input value for non fillable inputs like date, time, range, color, etc.
1076
+ this._validateSelectors(selectors);
1077
+ const startTime = Date.now();
1078
+ const info = {};
1079
+ info.log = "***** set input value " + selectors.element_name + " *****\n";
1080
+ info.operation = "setInputValue";
1081
+ info.selectors = selectors;
1082
+ value = this._fixUsingParams(value, _params);
1083
+ info.value = value;
1084
+ let error = null;
1085
+ let screenshotId = null;
1086
+ let screenshotPath = null;
1087
+ try {
1088
+ value = await this._replaceWithLocalData(value, this);
1089
+ let element = await this._locate(selectors, info, _params);
1090
+ await this.scrollIfNeeded(element, info);
1091
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1092
+ await this._highlightElements(element);
1093
+ try {
1094
+ await element.evaluateHandle((el, value) => {
1095
+ el.value = value;
1096
+ }, value);
1097
+ }
1098
+ catch (error) {
1099
+ this.logger.error("setInputValue failed, will try again");
1100
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1101
+ info.screenshotPath = screenshotPath;
1102
+ Object.assign(error, { info: info });
1103
+ await element.evaluateHandle((el, value) => {
1104
+ el.value = value;
1105
+ });
1106
+ }
1107
+ }
1108
+ catch (e) {
1109
+ this.logger.error("setInputValue failed " + info.log);
1110
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1111
+ info.screenshotPath = screenshotPath;
1112
+ Object.assign(e, { info: info });
1113
+ error = e;
1114
+ throw e;
1115
+ }
1116
+ finally {
1117
+ const endTime = Date.now();
1118
+ this._reportToWorld(world, {
1119
+ element_name: selectors.element_name,
1120
+ type: Types.SET_INPUT,
1121
+ text: `Set input value`,
1122
+ value: value,
1123
+ screenshotId,
1124
+ result: error
1125
+ ? {
1126
+ status: "FAILED",
1127
+ startTime,
1128
+ endTime,
1129
+ message: error === null || error === void 0 ? void 0 : error.message,
1130
+ }
1131
+ : {
1132
+ status: "PASSED",
1133
+ startTime,
1134
+ endTime,
1135
+ },
1136
+ info: info,
1137
+ });
1138
+ }
1139
+ }
954
1140
  async setDateTime(selectors, value, format = null, enter = false, _params = null, options = {}, world = null) {
955
1141
  this._validateSelectors(selectors);
956
1142
  const startTime = Date.now();
@@ -992,7 +1178,8 @@ class StableBrowser {
992
1178
  catch (err) {
993
1179
  //await this.closeUnexpectedPopups();
994
1180
  this.logger.error("setting date time input failed " + JSON.stringify(info));
995
- this.logger.info("Trying again")(({ screenshotId, screenshotPath } = await this._screenShot(options, world, info)));
1181
+ this.logger.info("Trying again");
1182
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
996
1183
  info.screenshotPath = screenshotPath;
997
1184
  Object.assign(err, { info: info });
998
1185
  await element.click();
@@ -1178,7 +1365,7 @@ class StableBrowser {
1178
1365
  let element = await this._locate(selectors, info, _params);
1179
1366
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1180
1367
  await this._highlightElements(element);
1181
- await element.fill(value, { timeout: 10000 });
1368
+ await element.fill(value);
1182
1369
  await element.dispatchEvent("change");
1183
1370
  if (enter) {
1184
1371
  await new Promise((resolve) => setTimeout(resolve, 2000));
@@ -1397,7 +1584,7 @@ class StableBrowser {
1397
1584
  return info;
1398
1585
  }
1399
1586
  catch (e) {
1400
- //await this.closeUnexpectedPopups();
1587
+ await this.closeUnexpectedPopups();
1401
1588
  this.logger.error("verify element contains text failed " + info.log);
1402
1589
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1403
1590
  info.screenshotPath = screenshotPath;
@@ -1445,6 +1632,29 @@ class StableBrowser {
1445
1632
  }
1446
1633
  return dataFile;
1447
1634
  }
1635
+ async waitForUserInput(message, world = null) {
1636
+ if (!message) {
1637
+ message = "# Wait for user input. Press any key to continue";
1638
+ }
1639
+ else {
1640
+ message = "# Wait for user input. " + message;
1641
+ }
1642
+ message += "\n";
1643
+ const value = await new Promise((resolve) => {
1644
+ const rl = readline.createInterface({
1645
+ input: process.stdin,
1646
+ output: process.stdout,
1647
+ });
1648
+ rl.question(message, (answer) => {
1649
+ rl.close();
1650
+ resolve(answer);
1651
+ });
1652
+ });
1653
+ if (value) {
1654
+ this.logger.info(`{{userInput}} was set to: ${value}`);
1655
+ }
1656
+ this.setTestData({ userInput: value }, world);
1657
+ }
1448
1658
  setTestData(testData, world = null) {
1449
1659
  if (!testData) {
1450
1660
  return;
@@ -1652,30 +1862,29 @@ class StableBrowser {
1652
1862
  ])));
1653
1863
  const { data } = await client.send("Page.captureScreenshot", {
1654
1864
  format: "png",
1655
- clip: {
1656
- x: 0,
1657
- y: 0,
1658
- width: viewportWidth,
1659
- height: viewportHeight,
1660
- scale: 1,
1661
- },
1865
+ // clip: {
1866
+ // x: 0,
1867
+ // y: 0,
1868
+ // width: viewportWidth,
1869
+ // height: viewportHeight,
1870
+ // scale: 1,
1871
+ // },
1662
1872
  });
1663
1873
  if (!screenshotPath) {
1664
1874
  return data;
1665
1875
  }
1666
1876
  let screenshotBuffer = Buffer.from(data, "base64");
1667
- const sharpBuffer = sharp(screenshotBuffer);
1668
- const metadata = await sharpBuffer.metadata();
1669
- //check if you are on retina display and reduce the quality of the image
1670
- if (metadata.width > viewportWidth || metadata.height > viewportHeight) {
1671
- screenshotBuffer = await sharpBuffer
1672
- .resize(viewportWidth, viewportHeight, {
1673
- fit: sharp.fit.inside,
1674
- withoutEnlargement: true,
1675
- })
1676
- .toBuffer();
1677
- }
1678
- fs.writeFileSync(screenshotPath, screenshotBuffer);
1877
+ let image = await Jimp.read(screenshotBuffer);
1878
+ // Get the image dimensions
1879
+ const { width, height } = image.bitmap;
1880
+ // Resize the image to fit within the viewport dimensions without enlarging
1881
+ if (width > viewportWidth || height > viewportHeight) {
1882
+ image = image.resize({ w: viewportWidth, h: viewportHeight }); // Resize the image while maintaining aspect ratio
1883
+ await image.write(screenshotPath);
1884
+ }
1885
+ else {
1886
+ fs.writeFileSync(screenshotPath, screenshotBuffer);
1887
+ }
1679
1888
  await client.detach();
1680
1889
  }
1681
1890
  async verifyElementExistInPage(selectors, _params = null, options = {}, world = null) {
@@ -2484,13 +2693,13 @@ class StableBrowser {
2484
2693
  }
2485
2694
  catch (e) {
2486
2695
  if (e.label === "networkidle") {
2487
- console.log("waitted for the network to be idle timeout");
2696
+ console.log("waited for the network to be idle timeout");
2488
2697
  }
2489
2698
  else if (e.label === "load") {
2490
- console.log("waitted for the load timeout");
2699
+ console.log("waited for the load timeout");
2491
2700
  }
2492
2701
  else if (e.label === "domcontentloaded") {
2493
- console.log("waitted for the domcontent loaded timeout");
2702
+ console.log("waited for the domcontent loaded timeout");
2494
2703
  }
2495
2704
  console.log(".");
2496
2705
  }
@@ -2633,33 +2842,18 @@ class StableBrowser {
2633
2842
  }
2634
2843
  async scrollIfNeeded(element, info) {
2635
2844
  try {
2636
- let didScroll = await element.evaluate((node) => {
2637
- const rect = node.getBoundingClientRect();
2638
- if (rect &&
2639
- rect.top >= 0 &&
2640
- rect.left >= 0 &&
2641
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2642
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
2643
- return false;
2644
- }
2645
- else {
2646
- node.scrollIntoView({
2647
- behavior: "smooth",
2648
- block: "center",
2649
- inline: "center",
2650
- });
2651
- return true;
2652
- }
2845
+ await element.scrollIntoViewIfNeeded({
2846
+ timeout: 2000,
2653
2847
  });
2654
- if (didScroll) {
2655
- await new Promise((resolve) => setTimeout(resolve, 500));
2656
- if (info) {
2657
- info.box = await element.boundingBox();
2658
- }
2848
+ await new Promise((resolve) => setTimeout(resolve, 500));
2849
+ if (info) {
2850
+ info.box = await element.boundingBox({
2851
+ timeout: 1000,
2852
+ });
2659
2853
  }
2660
2854
  }
2661
2855
  catch (e) {
2662
- console.log("scroll failed");
2856
+ console.log("#-#");
2663
2857
  }
2664
2858
  }
2665
2859
  _reportToWorld(world, properties) {