automation_model 1.0.405-dev → 1.0.405-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";
@@ -13,6 +13,9 @@ import { getTableCells, getTableData } from "./table_analyze.js";
13
13
  import objectPath from "object-path";
14
14
  import { decrypt } from "./utils.js";
15
15
  import csv from "csv-parser";
16
+ import { Readable } from "node:stream";
17
+ import readline from "readline";
18
+ import { getContext } from "./init_browser.js";
16
19
  const Types = {
17
20
  CLICK: "click_element",
18
21
  NAVIGATE: "navigate",
@@ -37,16 +40,22 @@ const Types = {
37
40
  SET_DATE_TIME: "set_date_time",
38
41
  SET_VIEWPORT: "set_viewport",
39
42
  VERIFY_VISUAL: "verify_visual",
43
+ LOAD_DATA: "load_data",
44
+ SET_INPUT: "set_input",
40
45
  };
46
+ export const apps = {};
41
47
  class StableBrowser {
42
- constructor(browser, page, logger = null, context = null) {
48
+ constructor(browser, page, logger = null, context = null, world = null) {
43
49
  this.browser = browser;
44
50
  this.page = page;
45
51
  this.logger = logger;
46
52
  this.context = context;
53
+ this.world = world;
47
54
  this.project_path = null;
48
55
  this.webLogFile = null;
56
+ this.networkLogger = null;
49
57
  this.configuration = null;
58
+ this.appName = "main";
50
59
  if (!this.logger) {
51
60
  this.logger = console;
52
61
  }
@@ -72,23 +81,34 @@ class StableBrowser {
72
81
  this.logger.error("unable to read ai_config.json");
73
82
  }
74
83
  const logFolder = path.join(this.project_path, "logs", "web");
75
- this.webLogFile = this.getWebLogFile(logFolder);
76
- this.registerConsoleLogListener(page, context, this.webLogFile);
77
- this.registerRequestListener();
84
+ this.world = world;
78
85
  context.pages = [this.page];
79
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
+ }
80
95
  context.playContext.on("page", async function (page) {
81
96
  context.pageLoading.status = true;
82
97
  this.page = page;
83
98
  context.page = page;
84
99
  context.pages.push(page);
85
100
  page.on("close", async () => {
86
- if (this.context && this.context.pages && this.context.pages.length > 0) {
101
+ if (this.context && this.context.pages && this.context.pages.length > 1) {
87
102
  this.context.pages.pop();
88
103
  this.page = this.context.pages[this.context.pages.length - 1];
89
104
  this.context.page = this.page;
90
- let title = await this.page.title();
91
- 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
+ }
92
112
  }
93
113
  });
94
114
  try {
@@ -101,6 +121,36 @@ class StableBrowser {
101
121
  context.pageLoading.status = false;
102
122
  }.bind(this));
103
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
+ }
104
154
  getWebLogFile(logFolder) {
105
155
  if (!fs.existsSync(logFolder)) {
106
156
  fs.mkdirSync(logFolder, { recursive: true });
@@ -112,37 +162,63 @@ class StableBrowser {
112
162
  const fileName = nextIndex + ".json";
113
163
  return path.join(logFolder, fileName);
114
164
  }
115
- registerConsoleLogListener(page, context, logFile) {
165
+ registerConsoleLogListener(page, context) {
116
166
  if (!this.context.webLogger) {
117
167
  this.context.webLogger = [];
118
168
  }
119
169
  page.on("console", async (msg) => {
120
- this.context.webLogger.push({
170
+ var _a;
171
+ const obj = {
121
172
  type: msg.type(),
122
173
  text: msg.text(),
123
174
  location: msg.location(),
124
175
  time: new Date().toISOString(),
125
- });
126
- 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" });
127
179
  });
128
180
  }
129
- registerRequestListener() {
130
- 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();
131
188
  try {
132
- const pageUrl = new URL(this.page.url());
189
+ const pageUrl = new URL(page.url());
133
190
  const requestUrl = new URL(data.url());
134
191
  if (pageUrl.hostname === requestUrl.hostname) {
135
192
  const method = data.method();
136
- if (method === "POST" || method === "GET" || method === "PUT" || method === "DELETE" || method === "PATCH") {
193
+ if (["POST", "GET", "PUT", "DELETE", "PATCH"].includes(method)) {
137
194
  const token = await data.headerValue("Authorization");
138
195
  if (token) {
139
- this.context.authtoken = token;
196
+ context.authtoken = token;
140
197
  }
141
198
  }
142
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" });
143
212
  }
144
213
  catch (error) {
145
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));
146
222
  }
147
223
  });
148
224
  }
@@ -212,9 +288,7 @@ class StableBrowser {
212
288
  }
213
289
  _getLocator(locator, scope, _params) {
214
290
  locator = this._fixLocatorUsingParams(locator, _params);
215
- if (locator.type === "pw_selector") {
216
- return scope.locator(locator.selector);
217
- }
291
+ let locatorReturn;
218
292
  if (locator.role) {
219
293
  if (locator.role[1].nameReg) {
220
294
  locator.role[1].name = reg_parser(locator.role[1].nameReg);
@@ -223,20 +297,42 @@ class StableBrowser {
223
297
  // if (locator.role[1].name) {
224
298
  // locator.role[1].name = this._fixUsingParams(locator.role[1].name, _params);
225
299
  // }
226
- return scope.getByRole(locator.role[0], locator.role[1]);
300
+ locatorReturn = scope.getByRole(locator.role[0], locator.role[1]);
227
301
  }
228
302
  if (locator.css) {
229
- return scope.locator(locator.css);
303
+ locatorReturn = scope.locator(locator.css);
230
304
  }
231
- if ((locator === null || locator === void 0 ? void 0 : locator.engine) && (locator === null || locator === void 0 ? void 0 : locator.score) <= 520) {
232
- let selector = locator.selector.replace(/"/g, '\\"');
233
- if (locator.engine === "internal:att") {
234
- 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" });
235
315
  }
236
- const locator = scope.locator(`${locator.engine}="${selector}"`);
237
- return locator;
238
316
  }
239
- 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;
240
336
  }
241
337
  async _locateElmentByTextClimbCss(scope, text, climb, css, _params) {
242
338
  let result = await this._locateElementByText(scope, this._fixUsingParams(text, _params), "*", false, true, _params);
@@ -447,6 +543,8 @@ class StableBrowser {
447
543
  if (result.foundElements.length > 0) {
448
544
  let dialogCloseLocator = result.foundElements[0].locator;
449
545
  await dialogCloseLocator.click();
546
+ // wait for the dialog to close
547
+ await dialogCloseLocator.waitFor({ state: "hidden" });
450
548
  return { rerun: true };
451
549
  }
452
550
  }
@@ -455,7 +553,7 @@ class StableBrowser {
455
553
  }
456
554
  async _locate(selectors, info, _params, timeout = 30000) {
457
555
  for (let i = 0; i < 3; i++) {
458
- info.log += "attempt " + i + ": totoal locators " + selectors.locators.length + "\n";
556
+ info.log += "attempt " + i + ": total locators " + selectors.locators.length + "\n";
459
557
  for (let j = 0; j < selectors.locators.length; j++) {
460
558
  let selector = selectors.locators[j];
461
559
  info.log += "searching for locator " + j + ":" + JSON.stringify(selector) + "\n";
@@ -475,9 +573,30 @@ class StableBrowser {
475
573
  //let arrayMode = Array.isArray(selectors);
476
574
  let scope = this.page;
477
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
+ };
478
592
  info.log += "searching for iframe " + selectors.iframe_src + "/" + selectors.frameLocators + "\n";
479
593
  while (true) {
480
594
  let frameFound = false;
595
+ if (selectors.nestFrmLoc) {
596
+ scope = findFrame(selectors.nestFrmLoc, scope);
597
+ frameFound = true;
598
+ break;
599
+ }
481
600
  if (selectors.frameLocators) {
482
601
  for (let i = 0; i < selectors.frameLocators.length; i++) {
483
602
  let frameLocator = selectors.frameLocators[i];
@@ -641,6 +760,9 @@ class StableBrowser {
641
760
  async click(selectors, _params, options = {}, world = null) {
642
761
  this._validateSelectors(selectors);
643
762
  const startTime = Date.now();
763
+ if (options && options.context) {
764
+ selectors.locators[0].text = options.context;
765
+ }
644
766
  const info = {};
645
767
  info.log = "***** click on " + selectors.element_name + " *****\n";
646
768
  info.operation = "click";
@@ -654,14 +776,14 @@ class StableBrowser {
654
776
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
655
777
  try {
656
778
  await this._highlightElements(element);
657
- await element.click({ timeout: 5000 });
779
+ await element.click();
658
780
  await new Promise((resolve) => setTimeout(resolve, 1000));
659
781
  }
660
782
  catch (e) {
661
783
  // await this.closeUnexpectedPopups();
662
784
  info.log += "click failed, will try again" + "\n";
663
785
  element = await this._locate(selectors, info, _params);
664
- await element.click({ timeout: 10000, force: true });
786
+ await element.dispatchEvent("click");
665
787
  await new Promise((resolve) => setTimeout(resolve, 1000));
666
788
  }
667
789
  await this.waitForPageLoad();
@@ -714,7 +836,7 @@ class StableBrowser {
714
836
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
715
837
  try {
716
838
  await this._highlightElements(element);
717
- await element.setChecked(checked, { timeout: 5000 });
839
+ await element.setChecked(checked);
718
840
  await new Promise((resolve) => setTimeout(resolve, 1000));
719
841
  }
720
842
  catch (e) {
@@ -778,7 +900,7 @@ class StableBrowser {
778
900
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
779
901
  try {
780
902
  await this._highlightElements(element);
781
- await element.hover({ timeout: 10000 });
903
+ await element.hover();
782
904
  await new Promise((resolve) => setTimeout(resolve, 1000));
783
905
  }
784
906
  catch (e) {
@@ -840,7 +962,7 @@ class StableBrowser {
840
962
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
841
963
  try {
842
964
  await this._highlightElements(element);
843
- await element.selectOption(values, { timeout: 5000 });
965
+ await element.selectOption(values);
844
966
  }
845
967
  catch (e) {
846
968
  //await this.closeUnexpectedPopups();
@@ -949,6 +1071,72 @@ class StableBrowser {
949
1071
  });
950
1072
  }
951
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
+ }
952
1140
  async setDateTime(selectors, value, format = null, enter = false, _params = null, options = {}, world = null) {
953
1141
  this._validateSelectors(selectors);
954
1142
  const startTime = Date.now();
@@ -990,7 +1178,8 @@ class StableBrowser {
990
1178
  catch (err) {
991
1179
  //await this.closeUnexpectedPopups();
992
1180
  this.logger.error("setting date time input failed " + JSON.stringify(info));
993
- 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));
994
1183
  info.screenshotPath = screenshotPath;
995
1184
  Object.assign(err, { info: info });
996
1185
  await element.click();
@@ -1176,7 +1365,7 @@ class StableBrowser {
1176
1365
  let element = await this._locate(selectors, info, _params);
1177
1366
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1178
1367
  await this._highlightElements(element);
1179
- await element.fill(value, { timeout: 10000 });
1368
+ await element.fill(value);
1180
1369
  await element.dispatchEvent("change");
1181
1370
  if (enter) {
1182
1371
  await new Promise((resolve) => setTimeout(resolve, 2000));
@@ -1395,7 +1584,7 @@ class StableBrowser {
1395
1584
  return info;
1396
1585
  }
1397
1586
  catch (e) {
1398
- //await this.closeUnexpectedPopups();
1587
+ await this.closeUnexpectedPopups();
1399
1588
  this.logger.error("verify element contains text failed " + info.log);
1400
1589
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1401
1590
  info.screenshotPath = screenshotPath;
@@ -1443,6 +1632,29 @@ class StableBrowser {
1443
1632
  }
1444
1633
  return dataFile;
1445
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
+ }
1446
1658
  setTestData(testData, world = null) {
1447
1659
  if (!testData) {
1448
1660
  return;
@@ -1470,7 +1682,7 @@ class StableBrowser {
1470
1682
  const data = fs.readFileSync(filePath, "utf8");
1471
1683
  const results = [];
1472
1684
  return new Promise((resolve, reject) => {
1473
- const readableStream = new stream.Readable();
1685
+ const readableStream = new Readable();
1474
1686
  readableStream._read = () => { }; // _read is required but you can noop it
1475
1687
  readableStream.push(data);
1476
1688
  readableStream.push(null);
@@ -1650,30 +1862,29 @@ class StableBrowser {
1650
1862
  ])));
1651
1863
  const { data } = await client.send("Page.captureScreenshot", {
1652
1864
  format: "png",
1653
- clip: {
1654
- x: 0,
1655
- y: 0,
1656
- width: viewportWidth,
1657
- height: viewportHeight,
1658
- scale: 1,
1659
- },
1865
+ // clip: {
1866
+ // x: 0,
1867
+ // y: 0,
1868
+ // width: viewportWidth,
1869
+ // height: viewportHeight,
1870
+ // scale: 1,
1871
+ // },
1660
1872
  });
1661
1873
  if (!screenshotPath) {
1662
1874
  return data;
1663
1875
  }
1664
1876
  let screenshotBuffer = Buffer.from(data, "base64");
1665
- const sharpBuffer = sharp(screenshotBuffer);
1666
- const metadata = await sharpBuffer.metadata();
1667
- //check if you are on retina display and reduce the quality of the image
1668
- if (metadata.width > viewportWidth || metadata.height > viewportHeight) {
1669
- screenshotBuffer = await sharpBuffer
1670
- .resize(viewportWidth, viewportHeight, {
1671
- fit: sharp.fit.inside,
1672
- withoutEnlargement: true,
1673
- })
1674
- .toBuffer();
1675
- }
1676
- 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
+ }
1677
1888
  await client.detach();
1678
1889
  }
1679
1890
  async verifyElementExistInPage(selectors, _params = null, options = {}, world = null) {
@@ -2482,13 +2693,13 @@ class StableBrowser {
2482
2693
  }
2483
2694
  catch (e) {
2484
2695
  if (e.label === "networkidle") {
2485
- console.log("waitted for the network to be idle timeout");
2696
+ console.log("waited for the network to be idle timeout");
2486
2697
  }
2487
2698
  else if (e.label === "load") {
2488
- console.log("waitted for the load timeout");
2699
+ console.log("waited for the load timeout");
2489
2700
  }
2490
2701
  else if (e.label === "domcontentloaded") {
2491
- console.log("waitted for the domcontent loaded timeout");
2702
+ console.log("waited for the domcontent loaded timeout");
2492
2703
  }
2493
2704
  console.log(".");
2494
2705
  }
@@ -2631,33 +2842,18 @@ class StableBrowser {
2631
2842
  }
2632
2843
  async scrollIfNeeded(element, info) {
2633
2844
  try {
2634
- let didScroll = await element.evaluate((node) => {
2635
- const rect = node.getBoundingClientRect();
2636
- if (rect &&
2637
- rect.top >= 0 &&
2638
- rect.left >= 0 &&
2639
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2640
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
2641
- return false;
2642
- }
2643
- else {
2644
- node.scrollIntoView({
2645
- behavior: "smooth",
2646
- block: "center",
2647
- inline: "center",
2648
- });
2649
- return true;
2650
- }
2845
+ await element.scrollIntoViewIfNeeded({
2846
+ timeout: 2000,
2651
2847
  });
2652
- if (didScroll) {
2653
- await new Promise((resolve) => setTimeout(resolve, 500));
2654
- if (info) {
2655
- info.box = await element.boundingBox();
2656
- }
2848
+ await new Promise((resolve) => setTimeout(resolve, 500));
2849
+ if (info) {
2850
+ info.box = await element.boundingBox({
2851
+ timeout: 1000,
2852
+ });
2657
2853
  }
2658
2854
  }
2659
2855
  catch (e) {
2660
- console.log("scroll failed");
2856
+ console.log("#-#");
2661
2857
  }
2662
2858
  }
2663
2859
  _reportToWorld(world, properties) {