automation_model 1.0.415-dev → 1.0.415-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",
@@ -41,15 +43,19 @@ const Types = {
41
43
  LOAD_DATA: "load_data",
42
44
  SET_INPUT: "set_input",
43
45
  };
46
+ export const apps = {};
44
47
  class StableBrowser {
45
- constructor(browser, page, logger = null, context = null) {
48
+ constructor(browser, page, logger = null, context = null, world = null) {
46
49
  this.browser = browser;
47
50
  this.page = page;
48
51
  this.logger = logger;
49
52
  this.context = context;
53
+ this.world = world;
50
54
  this.project_path = null;
51
55
  this.webLogFile = null;
56
+ this.networkLogger = null;
52
57
  this.configuration = null;
58
+ this.appName = "main";
53
59
  if (!this.logger) {
54
60
  this.logger = console;
55
61
  }
@@ -75,23 +81,34 @@ class StableBrowser {
75
81
  this.logger.error("unable to read ai_config.json");
76
82
  }
77
83
  const logFolder = path.join(this.project_path, "logs", "web");
78
- this.webLogFile = this.getWebLogFile(logFolder);
79
- this.registerConsoleLogListener(page, context, this.webLogFile);
80
- this.registerRequestListener();
84
+ this.world = world;
81
85
  context.pages = [this.page];
82
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
+ }
83
95
  context.playContext.on("page", async function (page) {
84
96
  context.pageLoading.status = true;
85
97
  this.page = page;
86
98
  context.page = page;
87
99
  context.pages.push(page);
88
100
  page.on("close", async () => {
89
- if (this.context && this.context.pages && this.context.pages.length > 0) {
101
+ if (this.context && this.context.pages && this.context.pages.length > 1) {
90
102
  this.context.pages.pop();
91
103
  this.page = this.context.pages[this.context.pages.length - 1];
92
104
  this.context.page = this.page;
93
- let title = await this.page.title();
94
- 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
+ }
95
112
  }
96
113
  });
97
114
  try {
@@ -104,6 +121,36 @@ class StableBrowser {
104
121
  context.pageLoading.status = false;
105
122
  }.bind(this));
106
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
+ }
107
154
  getWebLogFile(logFolder) {
108
155
  if (!fs.existsSync(logFolder)) {
109
156
  fs.mkdirSync(logFolder, { recursive: true });
@@ -115,37 +162,63 @@ class StableBrowser {
115
162
  const fileName = nextIndex + ".json";
116
163
  return path.join(logFolder, fileName);
117
164
  }
118
- registerConsoleLogListener(page, context, logFile) {
165
+ registerConsoleLogListener(page, context) {
119
166
  if (!this.context.webLogger) {
120
167
  this.context.webLogger = [];
121
168
  }
122
169
  page.on("console", async (msg) => {
123
- this.context.webLogger.push({
170
+ var _a;
171
+ const obj = {
124
172
  type: msg.type(),
125
173
  text: msg.text(),
126
174
  location: msg.location(),
127
175
  time: new Date().toISOString(),
128
- });
129
- 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" });
130
179
  });
131
180
  }
132
- registerRequestListener() {
133
- 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();
134
188
  try {
135
- const pageUrl = new URL(this.page.url());
189
+ const pageUrl = new URL(page.url());
136
190
  const requestUrl = new URL(data.url());
137
191
  if (pageUrl.hostname === requestUrl.hostname) {
138
192
  const method = data.method();
139
- if (method === "POST" || method === "GET" || method === "PUT" || method === "DELETE" || method === "PATCH") {
193
+ if (["POST", "GET", "PUT", "DELETE", "PATCH"].includes(method)) {
140
194
  const token = await data.headerValue("Authorization");
141
195
  if (token) {
142
- this.context.authtoken = token;
196
+ context.authtoken = token;
143
197
  }
144
198
  }
145
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" });
146
212
  }
147
213
  catch (error) {
148
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));
149
222
  }
150
223
  });
151
224
  }
@@ -226,7 +299,7 @@ class StableBrowser {
226
299
  // }
227
300
  locatorReturn = scope.getByRole(locator.role[0], locator.role[1]);
228
301
  }
229
- if (locator.css || locator.engine === "css") {
302
+ if (locator.css) {
230
303
  locatorReturn = scope.locator(locator.css);
231
304
  }
232
305
  // handle role/name locators
@@ -241,34 +314,30 @@ class StableBrowser {
241
314
  locatorReturn = scope.getByRole(role, { name }, { exact: flags === "i" });
242
315
  }
243
316
  }
244
- // locator object { engine: "internal:text", selector: '"Signup / Login"i', priority: 4 },
245
- if (locator.engine === "internal:text") {
246
- // extract the text and the i flag using regex
247
- const match = locator.selector.match(/"(.*)"(.*)/);
248
- if (match) {
249
- const text = match[1];
250
- const flags = match[2];
251
- locatorReturn = scope.locator(`text=${text}`, { exact: flags === "i" });
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}`);
252
329
  }
253
- }
254
- if (locator.engine === "internal:attr") {
255
- selector = `[${selector}]`;
256
- locatorReturn = scope.locator(`${locator.engine}=${selector}`);
257
330
  }
258
331
  if (!locatorReturn) {
259
332
  console.error(locator);
260
- throw new Error("Locator " + JSON.stringify(locator) + " not found");
261
- // } else {
262
- // const count = locatorReturn.count();
263
- // if (count === 0) {
264
- // throw new Error("Elements not found");
265
- // } else if (count > 1) {
266
- // throw new Error("Multiple elements found");
267
- // }
333
+ throw new Error("Locator undefined");
268
334
  }
269
335
  return locatorReturn;
270
336
  }
271
337
  async _locateElmentByTextClimbCss(scope, text, climb, css, _params) {
338
+ if (css && css.locator) {
339
+ css = css.locator;
340
+ }
272
341
  let result = await this._locateElementByText(scope, this._fixUsingParams(text, _params), "*", false, true, _params);
273
342
  if (result.elementCount === 0) {
274
343
  return;
@@ -296,6 +365,15 @@ class StableBrowser {
296
365
  return false;
297
366
  }
298
367
  document.isParent = isParent;
368
+ function getRegex(str) {
369
+ const match = str.match(/^\/(.*?)\/([gimuy]*)$/);
370
+ if (!match) {
371
+ return null;
372
+ }
373
+ let [_, pattern, flags] = match;
374
+ return new RegExp(pattern, flags);
375
+ }
376
+ document.getRegex = getRegex;
299
377
  function collectAllShadowDomElements(element, result = []) {
300
378
  // Check and add the element if it has a shadow root
301
379
  if (element.shadowRoot) {
@@ -314,6 +392,10 @@ class StableBrowser {
314
392
  if (!tag) {
315
393
  tag = "*";
316
394
  }
395
+ let regexpSearch = document.getRegex(text);
396
+ if (regexpSearch) {
397
+ regex = true;
398
+ }
317
399
  let elements = Array.from(document.querySelectorAll(tag));
318
400
  let shadowHosts = [];
319
401
  document.collectAllShadowDomElements(document, shadowHosts);
@@ -329,7 +411,9 @@ class StableBrowser {
329
411
  let randomToken = null;
330
412
  const foundElements = [];
331
413
  if (regex) {
332
- let regexpSearch = new RegExp(text, "im");
414
+ if (!regexpSearch) {
415
+ regexpSearch = new RegExp(text, "im");
416
+ }
333
417
  for (let i = 0; i < elements.length; i++) {
334
418
  const element = elements[i];
335
419
  if ((element.innerText && regexpSearch.test(element.innerText)) ||
@@ -343,8 +427,8 @@ class StableBrowser {
343
427
  for (let i = 0; i < elements.length; i++) {
344
428
  const element = elements[i];
345
429
  if (partial) {
346
- if ((element.innerText && element.innerText.trim().includes(text)) ||
347
- (element.value && element.value.includes(text))) {
430
+ if ((element.innerText && element.innerText.toLowerCase().trim().includes(text.toLowerCase())) ||
431
+ (element.value && element.value.toLowerCase().includes(text.toLowerCase()))) {
348
432
  foundElements.push(element);
349
433
  }
350
434
  }
@@ -389,6 +473,12 @@ class StableBrowser {
389
473
  }
390
474
  async _collectLocatorInformation(selectorHierarchy, index = 0, scope, foundLocators, _params, info, visibleOnly = true) {
391
475
  let locatorSearch = selectorHierarchy[index];
476
+ try {
477
+ locatorSearch = JSON.parse(this._fixUsingParams(JSON.stringify(locatorSearch), _params));
478
+ }
479
+ catch (e) {
480
+ console.error(e);
481
+ }
392
482
  //info.log += "searching for locator " + JSON.stringify(locatorSearch) + "\n";
393
483
  let locator = null;
394
484
  if (locatorSearch.climb && locatorSearch.climb >= 0) {
@@ -477,6 +567,8 @@ class StableBrowser {
477
567
  if (result.foundElements.length > 0) {
478
568
  let dialogCloseLocator = result.foundElements[0].locator;
479
569
  await dialogCloseLocator.click();
570
+ // wait for the dialog to close
571
+ await dialogCloseLocator.waitFor({ state: "hidden" });
480
572
  return { rerun: true };
481
573
  }
482
574
  }
@@ -485,7 +577,7 @@ class StableBrowser {
485
577
  }
486
578
  async _locate(selectors, info, _params, timeout = 30000) {
487
579
  for (let i = 0; i < 3; i++) {
488
- info.log += "attempt " + i + ": totoal locators " + selectors.locators.length + "\n";
580
+ info.log += "attempt " + i + ": total locators " + selectors.locators.length + "\n";
489
581
  for (let j = 0; j < selectors.locators.length; j++) {
490
582
  let selector = selectors.locators[j];
491
583
  info.log += "searching for locator " + j + ":" + JSON.stringify(selector) + "\n";
@@ -505,9 +597,39 @@ class StableBrowser {
505
597
  //let arrayMode = Array.isArray(selectors);
506
598
  let scope = this.page;
507
599
  if (selectors.iframe_src || selectors.frameLocators) {
600
+ const findFrame = async (frame, framescope) => {
601
+ for (let i = 0; i < frame.selectors.length; i++) {
602
+ let frameLocator = frame.selectors[i];
603
+ if (frameLocator.css) {
604
+ let testframescope = framescope.frameLocator(frameLocator.css);
605
+ if (frameLocator.index) {
606
+ testframescope = framescope.nth(frameLocator.index);
607
+ }
608
+ try {
609
+ await testframescope.owner().evaluateHandle(() => true, null, {
610
+ timeout: 5000,
611
+ });
612
+ framescope = testframescope;
613
+ break;
614
+ }
615
+ catch (error) {
616
+ console.error("frame not found " + frameLocator.css);
617
+ }
618
+ }
619
+ }
620
+ if (frame.children) {
621
+ return await findFrame(frame.children, framescope);
622
+ }
623
+ return framescope;
624
+ };
508
625
  info.log += "searching for iframe " + selectors.iframe_src + "/" + selectors.frameLocators + "\n";
509
626
  while (true) {
510
627
  let frameFound = false;
628
+ if (selectors.nestFrmLoc) {
629
+ scope = await findFrame(selectors.nestFrmLoc, scope);
630
+ frameFound = true;
631
+ break;
632
+ }
511
633
  if (selectors.frameLocators) {
512
634
  for (let i = 0; i < selectors.frameLocators.length; i++) {
513
635
  let frameLocator = selectors.frameLocators[i];
@@ -687,14 +809,14 @@ class StableBrowser {
687
809
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
688
810
  try {
689
811
  await this._highlightElements(element);
690
- await element.click({ timeout: 5000 });
812
+ await element.click();
691
813
  await new Promise((resolve) => setTimeout(resolve, 1000));
692
814
  }
693
815
  catch (e) {
694
816
  // await this.closeUnexpectedPopups();
695
817
  info.log += "click failed, will try again" + "\n";
696
818
  element = await this._locate(selectors, info, _params);
697
- await element.click({ timeout: 10000, force: true });
819
+ await element.dispatchEvent("click");
698
820
  await new Promise((resolve) => setTimeout(resolve, 1000));
699
821
  }
700
822
  await this.waitForPageLoad();
@@ -747,7 +869,7 @@ class StableBrowser {
747
869
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
748
870
  try {
749
871
  await this._highlightElements(element);
750
- await element.setChecked(checked, { timeout: 5000 });
872
+ await element.setChecked(checked);
751
873
  await new Promise((resolve) => setTimeout(resolve, 1000));
752
874
  }
753
875
  catch (e) {
@@ -811,7 +933,7 @@ class StableBrowser {
811
933
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
812
934
  try {
813
935
  await this._highlightElements(element);
814
- await element.hover({ timeout: 10000 });
936
+ await element.hover();
815
937
  await new Promise((resolve) => setTimeout(resolve, 1000));
816
938
  }
817
939
  catch (e) {
@@ -873,7 +995,7 @@ class StableBrowser {
873
995
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
874
996
  try {
875
997
  await this._highlightElements(element);
876
- await element.selectOption(values, { timeout: 5000 });
998
+ await element.selectOption(values);
877
999
  }
878
1000
  catch (e) {
879
1001
  //await this.closeUnexpectedPopups();
@@ -1161,7 +1283,6 @@ class StableBrowser {
1161
1283
  let element = await this._locate(selectors, info, _params);
1162
1284
  //insert red border around the element
1163
1285
  await this.scrollIfNeeded(element, info);
1164
- ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1165
1286
  await this._highlightElements(element);
1166
1287
  if (options === null || options === undefined || !options.press) {
1167
1288
  try {
@@ -1211,6 +1332,7 @@ class StableBrowser {
1211
1332
  await new Promise((resolve) => setTimeout(resolve, 500));
1212
1333
  }
1213
1334
  }
1335
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1214
1336
  if (enter === true) {
1215
1337
  await new Promise((resolve) => setTimeout(resolve, 2000));
1216
1338
  await this.page.keyboard.press("Enter");
@@ -1276,7 +1398,7 @@ class StableBrowser {
1276
1398
  let element = await this._locate(selectors, info, _params);
1277
1399
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1278
1400
  await this._highlightElements(element);
1279
- await element.fill(value, { timeout: 10000 });
1401
+ await element.fill(value);
1280
1402
  await element.dispatchEvent("change");
1281
1403
  if (enter) {
1282
1404
  await new Promise((resolve) => setTimeout(resolve, 2000));
@@ -1495,7 +1617,7 @@ class StableBrowser {
1495
1617
  return info;
1496
1618
  }
1497
1619
  catch (e) {
1498
- //await this.closeUnexpectedPopups();
1620
+ await this.closeUnexpectedPopups();
1499
1621
  this.logger.error("verify element contains text failed " + info.log);
1500
1622
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1501
1623
  info.screenshotPath = screenshotPath;
@@ -1543,6 +1665,29 @@ class StableBrowser {
1543
1665
  }
1544
1666
  return dataFile;
1545
1667
  }
1668
+ async waitForUserInput(message, world = null) {
1669
+ if (!message) {
1670
+ message = "# Wait for user input. Press any key to continue";
1671
+ }
1672
+ else {
1673
+ message = "# Wait for user input. " + message;
1674
+ }
1675
+ message += "\n";
1676
+ const value = await new Promise((resolve) => {
1677
+ const rl = readline.createInterface({
1678
+ input: process.stdin,
1679
+ output: process.stdout,
1680
+ });
1681
+ rl.question(message, (answer) => {
1682
+ rl.close();
1683
+ resolve(answer);
1684
+ });
1685
+ });
1686
+ if (value) {
1687
+ this.logger.info(`{{userInput}} was set to: ${value}`);
1688
+ }
1689
+ this.setTestData({ userInput: value }, world);
1690
+ }
1546
1691
  setTestData(testData, world = null) {
1547
1692
  if (!testData) {
1548
1693
  return;
@@ -1730,7 +1875,6 @@ class StableBrowser {
1730
1875
  }
1731
1876
  async takeScreenshot(screenshotPath) {
1732
1877
  const playContext = this.context.playContext;
1733
- const client = await playContext.newCDPSession(this.page);
1734
1878
  // Using CDP to capture the screenshot
1735
1879
  const viewportWidth = Math.max(...(await this.page.evaluate(() => [
1736
1880
  document.body.scrollWidth,
@@ -1740,41 +1884,40 @@ class StableBrowser {
1740
1884
  document.body.clientWidth,
1741
1885
  document.documentElement.clientWidth,
1742
1886
  ])));
1743
- const viewportHeight = Math.max(...(await this.page.evaluate(() => [
1744
- document.body.scrollHeight,
1745
- document.documentElement.scrollHeight,
1746
- document.body.offsetHeight,
1747
- document.documentElement.offsetHeight,
1748
- document.body.clientHeight,
1749
- document.documentElement.clientHeight,
1750
- ])));
1751
- const { data } = await client.send("Page.captureScreenshot", {
1752
- format: "png",
1753
- clip: {
1754
- x: 0,
1755
- y: 0,
1756
- width: viewportWidth,
1757
- height: viewportHeight,
1758
- scale: 1,
1759
- },
1760
- });
1761
- if (!screenshotPath) {
1762
- return data;
1763
- }
1764
- let screenshotBuffer = Buffer.from(data, "base64");
1765
- const sharpBuffer = sharp(screenshotBuffer);
1766
- const metadata = await sharpBuffer.metadata();
1767
- //check if you are on retina display and reduce the quality of the image
1768
- if (metadata.width > viewportWidth || metadata.height > viewportHeight) {
1769
- screenshotBuffer = await sharpBuffer
1770
- .resize(viewportWidth, viewportHeight, {
1771
- fit: sharp.fit.inside,
1772
- withoutEnlargement: true,
1773
- })
1774
- .toBuffer();
1775
- }
1776
- fs.writeFileSync(screenshotPath, screenshotBuffer);
1777
- await client.detach();
1887
+ let screenshotBuffer = null;
1888
+ if (this.context.browserName === "chromium") {
1889
+ const client = await playContext.newCDPSession(this.page);
1890
+ const { data } = await client.send("Page.captureScreenshot", {
1891
+ format: "png",
1892
+ // clip: {
1893
+ // x: 0,
1894
+ // y: 0,
1895
+ // width: viewportWidth,
1896
+ // height: viewportHeight,
1897
+ // scale: 1,
1898
+ // },
1899
+ });
1900
+ await client.detach();
1901
+ if (!screenshotPath) {
1902
+ return data;
1903
+ }
1904
+ screenshotBuffer = Buffer.from(data, "base64");
1905
+ }
1906
+ else {
1907
+ screenshotBuffer = await this.page.screenshot();
1908
+ }
1909
+ let image = await Jimp.read(screenshotBuffer);
1910
+ // Get the image dimensions
1911
+ const { width, height } = image.bitmap;
1912
+ const resizeRatio = viewportWidth / width;
1913
+ // Resize the image to fit within the viewport dimensions without enlarging
1914
+ if (width > viewportWidth) {
1915
+ image = image.resize({ w: viewportWidth, h: height * resizeRatio }); // Resize the image while maintaining aspect ratio
1916
+ await image.write(screenshotPath);
1917
+ }
1918
+ else {
1919
+ fs.writeFileSync(screenshotPath, screenshotBuffer);
1920
+ }
1778
1921
  }
1779
1922
  async verifyElementExistInPage(selectors, _params = null, options = {}, world = null) {
1780
1923
  this._validateSelectors(selectors);
@@ -2582,13 +2725,13 @@ class StableBrowser {
2582
2725
  }
2583
2726
  catch (e) {
2584
2727
  if (e.label === "networkidle") {
2585
- console.log("waitted for the network to be idle timeout");
2728
+ console.log("waited for the network to be idle timeout");
2586
2729
  }
2587
2730
  else if (e.label === "load") {
2588
- console.log("waitted for the load timeout");
2731
+ console.log("waited for the load timeout");
2589
2732
  }
2590
2733
  else if (e.label === "domcontentloaded") {
2591
- console.log("waitted for the domcontent loaded timeout");
2734
+ console.log("waited for the domcontent loaded timeout");
2592
2735
  }
2593
2736
  console.log(".");
2594
2737
  }
@@ -2731,33 +2874,18 @@ class StableBrowser {
2731
2874
  }
2732
2875
  async scrollIfNeeded(element, info) {
2733
2876
  try {
2734
- let didScroll = await element.evaluate((node) => {
2735
- const rect = node.getBoundingClientRect();
2736
- if (rect &&
2737
- rect.top >= 0 &&
2738
- rect.left >= 0 &&
2739
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2740
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
2741
- return false;
2742
- }
2743
- else {
2744
- node.scrollIntoView({
2745
- behavior: "smooth",
2746
- block: "center",
2747
- inline: "center",
2748
- });
2749
- return true;
2750
- }
2877
+ await element.scrollIntoViewIfNeeded({
2878
+ timeout: 2000,
2751
2879
  });
2752
- if (didScroll) {
2753
- await new Promise((resolve) => setTimeout(resolve, 500));
2754
- if (info) {
2755
- info.box = await element.boundingBox();
2756
- }
2880
+ await new Promise((resolve) => setTimeout(resolve, 500));
2881
+ if (info) {
2882
+ info.box = await element.boundingBox({
2883
+ timeout: 1000,
2884
+ });
2757
2885
  }
2758
2886
  }
2759
2887
  catch (e) {
2760
- console.log("scroll failed");
2888
+ console.log("#-#");
2761
2889
  }
2762
2890
  }
2763
2891
  _reportToWorld(world, properties) {