automation_model 1.0.399-dev → 1.0.399-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.
@@ -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,7 +40,10 @@ 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
48
  constructor(browser, page, logger = null, context = null) {
43
49
  this.browser = browser;
@@ -47,6 +53,7 @@ class StableBrowser {
47
53
  this.project_path = null;
48
54
  this.webLogFile = null;
49
55
  this.configuration = null;
56
+ this.appName = "main";
50
57
  if (!this.logger) {
51
58
  this.logger = console;
52
59
  }
@@ -77,14 +84,28 @@ class StableBrowser {
77
84
  this.registerRequestListener();
78
85
  context.pages = [this.page];
79
86
  context.pageLoading = { status: false };
87
+ this.registerPageEventListeners(context);
88
+ }
89
+ registerPageEventListeners(context) {
80
90
  context.playContext.on("page", async function (page) {
81
91
  context.pageLoading.status = true;
82
92
  this.page = page;
83
93
  context.page = page;
84
94
  context.pages.push(page);
85
- this.webLogFile = this.getWebLogFile(logFolder);
86
- this.registerConsoleLogListener(page, context, this.webLogFile);
87
- this.registerRequestListener();
95
+ page.on("close", async () => {
96
+ if (this.context && this.context.pages && this.context.pages.length > 1) {
97
+ this.context.pages.pop();
98
+ this.page = this.context.pages[this.context.pages.length - 1];
99
+ this.context.page = this.page;
100
+ try {
101
+ let title = await this.page.title();
102
+ console.log("Switched to page " + title);
103
+ }
104
+ catch (error) {
105
+ console.error("Error on page close", error);
106
+ }
107
+ }
108
+ });
88
109
  try {
89
110
  await this.waitForPageLoad();
90
111
  console.log("Switch page: " + (await page.title()));
@@ -95,6 +116,36 @@ class StableBrowser {
95
116
  context.pageLoading.status = false;
96
117
  }.bind(this));
97
118
  }
119
+ async switchApp(appName) {
120
+ // check if the current app (this.appName) is the same as the new app
121
+ if (this.appName === appName) {
122
+ return;
123
+ }
124
+ let navigate = false;
125
+ if (!apps[appName]) {
126
+ let newContext = await getContext(null, false, this.logger, appName, false, this);
127
+ navigate = true;
128
+ apps[appName] = {
129
+ context: newContext,
130
+ browser: newContext.browser,
131
+ page: newContext.page,
132
+ };
133
+ }
134
+ const tempContext = {};
135
+ this._copyContext(this, tempContext);
136
+ this._copyContext(apps[appName], this);
137
+ apps[this.appName] = tempContext;
138
+ this.appName = appName;
139
+ if (navigate) {
140
+ await this.goto(this.context.environment.baseUrl);
141
+ await this.waitForPageLoad();
142
+ }
143
+ }
144
+ _copyContext(from, to) {
145
+ to.browser = from.browser;
146
+ to.page = from.page;
147
+ to.context = from.context;
148
+ }
98
149
  getWebLogFile(logFolder) {
99
150
  if (!fs.existsSync(logFolder)) {
100
151
  fs.mkdirSync(logFolder, { recursive: true });
@@ -179,24 +230,78 @@ class StableBrowser {
179
230
  }
180
231
  return text;
181
232
  }
182
- _getLocator(locator, scope, _params) {
183
- if (locator.type === "pw_selector") {
184
- return scope.locator(locator.selector);
233
+ _fixLocatorUsingParams(locator, _params) {
234
+ // check if not null
235
+ if (!locator) {
236
+ return locator;
237
+ }
238
+ // clone the locator
239
+ locator = JSON.parse(JSON.stringify(locator));
240
+ this.scanAndManipulate(locator, _params);
241
+ return locator;
242
+ }
243
+ _isObject(value) {
244
+ return value && typeof value === "object" && value.constructor === Object;
245
+ }
246
+ scanAndManipulate(currentObj, _params) {
247
+ for (const key in currentObj) {
248
+ if (typeof currentObj[key] === "string") {
249
+ // Perform string manipulation
250
+ currentObj[key] = this._fixUsingParams(currentObj[key], _params);
251
+ }
252
+ else if (this._isObject(currentObj[key])) {
253
+ // Recursively scan nested objects
254
+ this.scanAndManipulate(currentObj[key], _params);
255
+ }
185
256
  }
257
+ }
258
+ _getLocator(locator, scope, _params) {
259
+ locator = this._fixLocatorUsingParams(locator, _params);
260
+ let locatorReturn;
186
261
  if (locator.role) {
187
262
  if (locator.role[1].nameReg) {
188
263
  locator.role[1].name = reg_parser(locator.role[1].nameReg);
189
264
  delete locator.role[1].nameReg;
190
265
  }
191
- if (locator.role[1].name) {
192
- locator.role[1].name = this._fixUsingParams(locator.role[1].name, _params);
193
- }
194
- return scope.getByRole(locator.role[0], locator.role[1]);
266
+ // if (locator.role[1].name) {
267
+ // locator.role[1].name = this._fixUsingParams(locator.role[1].name, _params);
268
+ // }
269
+ locatorReturn = scope.getByRole(locator.role[0], locator.role[1]);
195
270
  }
196
271
  if (locator.css) {
197
- return scope.locator(this._fixUsingParams(locator.css, _params));
272
+ locatorReturn = scope.locator(locator.css);
273
+ }
274
+ // handle role/name locators
275
+ // locator.selector will be something like: textbox[name="Username"i]
276
+ if (locator.engine === "internal:role") {
277
+ // extract the role, name and the i/s flags using regex
278
+ const match = locator.selector.match(/(.*)\[(.*)="(.*)"(.*)\]/);
279
+ if (match) {
280
+ const role = match[1];
281
+ const name = match[3];
282
+ const flags = match[4];
283
+ locatorReturn = scope.getByRole(role, { name }, { exact: flags === "i" });
284
+ }
285
+ }
286
+ if (locator === null || locator === void 0 ? void 0 : locator.engine) {
287
+ if (locator.engine === "css") {
288
+ locatorReturn = scope.locator(locator.selector);
289
+ }
290
+ else {
291
+ let selector = locator.selector;
292
+ if (locator.engine === "internal:attr") {
293
+ if (!selector.startsWith("[")) {
294
+ selector = `[${selector}]`;
295
+ }
296
+ }
297
+ locatorReturn = scope.locator(`${locator.engine}=${selector}`);
298
+ }
299
+ }
300
+ if (!locatorReturn) {
301
+ console.error(locator);
302
+ throw new Error("Locator undefined");
198
303
  }
199
- throw new Error("unknown locator type");
304
+ return locatorReturn;
200
305
  }
201
306
  async _locateElmentByTextClimbCss(scope, text, climb, css, _params) {
202
307
  let result = await this._locateElementByText(scope, this._fixUsingParams(text, _params), "*", false, true, _params);
@@ -407,6 +512,8 @@ class StableBrowser {
407
512
  if (result.foundElements.length > 0) {
408
513
  let dialogCloseLocator = result.foundElements[0].locator;
409
514
  await dialogCloseLocator.click();
515
+ // wait for the dialog to close
516
+ await dialogCloseLocator.waitFor({ state: "hidden" });
410
517
  return { rerun: true };
411
518
  }
412
519
  }
@@ -415,7 +522,7 @@ class StableBrowser {
415
522
  }
416
523
  async _locate(selectors, info, _params, timeout = 30000) {
417
524
  for (let i = 0; i < 3; i++) {
418
- info.log += "attempt " + i + ": totoal locators " + selectors.locators.length + "\n";
525
+ info.log += "attempt " + i + ": total locators " + selectors.locators.length + "\n";
419
526
  for (let j = 0; j < selectors.locators.length; j++) {
420
527
  let selector = selectors.locators[j];
421
528
  info.log += "searching for locator " + j + ":" + JSON.stringify(selector) + "\n";
@@ -435,9 +542,27 @@ class StableBrowser {
435
542
  //let arrayMode = Array.isArray(selectors);
436
543
  let scope = this.page;
437
544
  if (selectors.iframe_src || selectors.frameLocators) {
545
+ const findFrame = (frame, framescope) => {
546
+ for (let i = 0; i < frame.selectors.length; i++) {
547
+ let frameLocator = frame.selectors[i];
548
+ if (frameLocator.css) {
549
+ framescope = framescope.frameLocator(frameLocator.css);
550
+ break;
551
+ }
552
+ }
553
+ if (frame.children) {
554
+ return findFrame(frame.children, framescope);
555
+ }
556
+ return framescope;
557
+ };
438
558
  info.log += "searching for iframe " + selectors.iframe_src + "/" + selectors.frameLocators + "\n";
439
559
  while (true) {
440
560
  let frameFound = false;
561
+ if (selectors.nestFrmLoc) {
562
+ scope = findFrame(selectors.nestFrmLoc, scope);
563
+ frameFound = true;
564
+ break;
565
+ }
441
566
  if (selectors.frameLocators) {
442
567
  for (let i = 0; i < selectors.frameLocators.length; i++) {
443
568
  let frameLocator = selectors.frameLocators[i];
@@ -601,6 +726,9 @@ class StableBrowser {
601
726
  async click(selectors, _params, options = {}, world = null) {
602
727
  this._validateSelectors(selectors);
603
728
  const startTime = Date.now();
729
+ if (options && options.context) {
730
+ selectors.locators[0].text = options.context;
731
+ }
604
732
  const info = {};
605
733
  info.log = "***** click on " + selectors.element_name + " *****\n";
606
734
  info.operation = "click";
@@ -614,14 +742,14 @@ class StableBrowser {
614
742
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
615
743
  try {
616
744
  await this._highlightElements(element);
617
- await element.click({ timeout: 5000 });
745
+ await element.click();
618
746
  await new Promise((resolve) => setTimeout(resolve, 1000));
619
747
  }
620
748
  catch (e) {
621
749
  // await this.closeUnexpectedPopups();
622
750
  info.log += "click failed, will try again" + "\n";
623
751
  element = await this._locate(selectors, info, _params);
624
- await element.click({ timeout: 10000, force: true });
752
+ await element.dispatchEvent("click");
625
753
  await new Promise((resolve) => setTimeout(resolve, 1000));
626
754
  }
627
755
  await this.waitForPageLoad();
@@ -674,7 +802,7 @@ class StableBrowser {
674
802
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
675
803
  try {
676
804
  await this._highlightElements(element);
677
- await element.setChecked(checked, { timeout: 5000 });
805
+ await element.setChecked(checked);
678
806
  await new Promise((resolve) => setTimeout(resolve, 1000));
679
807
  }
680
808
  catch (e) {
@@ -738,7 +866,7 @@ class StableBrowser {
738
866
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
739
867
  try {
740
868
  await this._highlightElements(element);
741
- await element.hover({ timeout: 10000 });
869
+ await element.hover();
742
870
  await new Promise((resolve) => setTimeout(resolve, 1000));
743
871
  }
744
872
  catch (e) {
@@ -800,7 +928,7 @@ class StableBrowser {
800
928
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
801
929
  try {
802
930
  await this._highlightElements(element);
803
- await element.selectOption(values, { timeout: 5000 });
931
+ await element.selectOption(values);
804
932
  }
805
933
  catch (e) {
806
934
  //await this.closeUnexpectedPopups();
@@ -909,71 +1037,45 @@ class StableBrowser {
909
1037
  });
910
1038
  }
911
1039
  }
912
- async setDateTime(selectors, value, format = null, enter = false, _params = null, options = {}, world = null) {
1040
+ async setInputValue(selectors, value, _params = null, options = {}, world = null) {
1041
+ // set input value for non fillable inputs like date, time, range, color, etc.
913
1042
  this._validateSelectors(selectors);
914
1043
  const startTime = Date.now();
915
- let error = null;
916
- let screenshotId = null;
917
- let screenshotPath = null;
918
1044
  const info = {};
919
- info.log = "";
920
- info.operation = Types.SET_DATE_TIME;
1045
+ info.log = "***** set input value " + selectors.element_name + " *****\n";
1046
+ info.operation = "setInputValue";
921
1047
  info.selectors = selectors;
1048
+ value = this._fixUsingParams(value, _params);
922
1049
  info.value = value;
1050
+ let error = null;
1051
+ let screenshotId = null;
1052
+ let screenshotPath = null;
923
1053
  try {
924
1054
  value = await this._replaceWithLocalData(value, this);
925
1055
  let element = await this._locate(selectors, info, _params);
926
- //insert red border around the element
927
1056
  await this.scrollIfNeeded(element, info);
928
1057
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
929
1058
  await this._highlightElements(element);
930
1059
  try {
931
- await element.click();
932
- await new Promise((resolve) => setTimeout(resolve, 500));
933
- if (format) {
934
- value = dayjs(value).format(format);
935
- await element.fill(value);
936
- }
937
- else {
938
- const dateTimeValue = await getDateTimeValue({ value, element });
939
- await element.evaluateHandle((el, dateTimeValue) => {
940
- el.value = ""; // clear input
941
- el.value = dateTimeValue;
942
- }, dateTimeValue);
943
- }
944
- if (enter) {
945
- await new Promise((resolve) => setTimeout(resolve, 2000));
946
- await this.page.keyboard.press("Enter");
947
- await this.waitForPageLoad();
948
- }
1060
+ await element.evaluateHandle((el, value) => {
1061
+ el.value = value;
1062
+ }, value);
949
1063
  }
950
1064
  catch (error) {
951
- //await this.closeUnexpectedPopups();
952
- this.logger.error("setting date time input failed " + JSON.stringify(info));
953
- this.logger.info("Trying again")(({ screenshotId, screenshotPath } = await this._screenShot(options, world, info)));
1065
+ this.logger.error("setInputValue failed, will try again");
1066
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
954
1067
  info.screenshotPath = screenshotPath;
955
1068
  Object.assign(error, { info: info });
956
- await element.click();
957
- await new Promise((resolve) => setTimeout(resolve, 500));
958
- if (format) {
959
- value = dayjs(value).format(format);
960
- await element.fill(value);
961
- }
962
- else {
963
- const dateTimeValue = await getDateTimeValue({ value, element });
964
- await element.evaluateHandle((el, dateTimeValue) => {
965
- el.value = ""; // clear input
966
- el.value = dateTimeValue;
967
- }, dateTimeValue);
968
- }
969
- if (enter) {
970
- await new Promise((resolve) => setTimeout(resolve, 2000));
971
- await this.page.keyboard.press("Enter");
972
- await this.waitForPageLoad();
973
- }
1069
+ await element.evaluateHandle((el, value) => {
1070
+ el.value = value;
1071
+ });
974
1072
  }
975
1073
  }
976
- catch (error) {
1074
+ catch (e) {
1075
+ this.logger.error("setInputValue failed " + info.log);
1076
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1077
+ info.screenshotPath = screenshotPath;
1078
+ Object.assign(e, { info: info });
977
1079
  error = e;
978
1080
  throw e;
979
1081
  }
@@ -981,10 +1083,10 @@ class StableBrowser {
981
1083
  const endTime = Date.now();
982
1084
  this._reportToWorld(world, {
983
1085
  element_name: selectors.element_name,
984
- type: Types.SET_DATE_TIME,
985
- screenshotId,
1086
+ type: Types.SET_INPUT,
1087
+ text: `Set input value`,
986
1088
  value: value,
987
- text: `setDateTime input with value: ${value}`,
1089
+ screenshotId,
988
1090
  result: error
989
1091
  ? {
990
1092
  status: "FAILED",
@@ -1001,7 +1103,7 @@ class StableBrowser {
1001
1103
  });
1002
1104
  }
1003
1105
  }
1004
- async setDateTime(selectors, value, enter = false, _params = null, options = {}, world = null) {
1106
+ async setDateTime(selectors, value, format = null, enter = false, _params = null, options = {}, world = null) {
1005
1107
  this._validateSelectors(selectors);
1006
1108
  const startTime = Date.now();
1007
1109
  let error = null;
@@ -1013,6 +1115,7 @@ class StableBrowser {
1013
1115
  info.selectors = selectors;
1014
1116
  info.value = value;
1015
1117
  try {
1118
+ value = await this._replaceWithLocalData(value, this);
1016
1119
  let element = await this._locate(selectors, info, _params);
1017
1120
  //insert red border around the element
1018
1121
  await this.scrollIfNeeded(element, info);
@@ -1021,28 +1124,51 @@ class StableBrowser {
1021
1124
  try {
1022
1125
  await element.click();
1023
1126
  await new Promise((resolve) => setTimeout(resolve, 500));
1024
- const dateTimeValue = await getDateTimeValue({ value, element });
1025
- await element.evaluateHandle((el, dateTimeValue) => {
1026
- el.value = ""; // clear input
1027
- el.value = dateTimeValue;
1028
- }, dateTimeValue);
1127
+ if (format) {
1128
+ value = dayjs(value).format(format);
1129
+ await element.fill(value);
1130
+ }
1131
+ else {
1132
+ const dateTimeValue = await getDateTimeValue({ value, element });
1133
+ await element.evaluateHandle((el, dateTimeValue) => {
1134
+ el.value = ""; // clear input
1135
+ el.value = dateTimeValue;
1136
+ }, dateTimeValue);
1137
+ }
1138
+ if (enter) {
1139
+ await new Promise((resolve) => setTimeout(resolve, 2000));
1140
+ await this.page.keyboard.press("Enter");
1141
+ await this.waitForPageLoad();
1142
+ }
1029
1143
  }
1030
- catch (error) {
1144
+ catch (err) {
1031
1145
  //await this.closeUnexpectedPopups();
1032
1146
  this.logger.error("setting date time input failed " + JSON.stringify(info));
1033
- this.logger.info("Trying again")(({ screenshotId, screenshotPath } = await this._screenShot(options, world, info)));
1147
+ this.logger.info("Trying again");
1148
+ ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1034
1149
  info.screenshotPath = screenshotPath;
1035
- Object.assign(error, { info: info });
1150
+ Object.assign(err, { info: info });
1036
1151
  await element.click();
1037
1152
  await new Promise((resolve) => setTimeout(resolve, 500));
1038
- const dateTimeValue = await getDateTimeValue({ value, element });
1039
- await element.evaluateHandle((el, dateTimeValue) => {
1040
- el.value = ""; // clear input
1041
- el.value = dateTimeValue;
1042
- }, dateTimeValue);
1153
+ if (format) {
1154
+ value = dayjs(value).format(format);
1155
+ await element.fill(value);
1156
+ }
1157
+ else {
1158
+ const dateTimeValue = await getDateTimeValue({ value, element });
1159
+ await element.evaluateHandle((el, dateTimeValue) => {
1160
+ el.value = ""; // clear input
1161
+ el.value = dateTimeValue;
1162
+ }, dateTimeValue);
1163
+ }
1164
+ if (enter) {
1165
+ await new Promise((resolve) => setTimeout(resolve, 2000));
1166
+ await this.page.keyboard.press("Enter");
1167
+ await this.waitForPageLoad();
1168
+ }
1043
1169
  }
1044
1170
  }
1045
- catch (error) {
1171
+ catch (e) {
1046
1172
  error = e;
1047
1173
  throw e;
1048
1174
  }
@@ -1205,7 +1331,7 @@ class StableBrowser {
1205
1331
  let element = await this._locate(selectors, info, _params);
1206
1332
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1207
1333
  await this._highlightElements(element);
1208
- await element.fill(value, { timeout: 10000 });
1334
+ await element.fill(value);
1209
1335
  await element.dispatchEvent("change");
1210
1336
  if (enter) {
1211
1337
  await new Promise((resolve) => setTimeout(resolve, 2000));
@@ -1424,7 +1550,7 @@ class StableBrowser {
1424
1550
  return info;
1425
1551
  }
1426
1552
  catch (e) {
1427
- //await this.closeUnexpectedPopups();
1553
+ await this.closeUnexpectedPopups();
1428
1554
  this.logger.error("verify element contains text failed " + info.log);
1429
1555
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1430
1556
  info.screenshotPath = screenshotPath;
@@ -1472,6 +1598,29 @@ class StableBrowser {
1472
1598
  }
1473
1599
  return dataFile;
1474
1600
  }
1601
+ async waitForUserInput(message, world = null) {
1602
+ if (!message) {
1603
+ message = "# Wait for user input. Press any key to continue";
1604
+ }
1605
+ else {
1606
+ message = "# Wait for user input. " + message;
1607
+ }
1608
+ message += "\n";
1609
+ const value = await new Promise((resolve) => {
1610
+ const rl = readline.createInterface({
1611
+ input: process.stdin,
1612
+ output: process.stdout,
1613
+ });
1614
+ rl.question(message, (answer) => {
1615
+ rl.close();
1616
+ resolve(answer);
1617
+ });
1618
+ });
1619
+ if (value) {
1620
+ this.logger.info(`{{userInput}} was set to: ${value}`);
1621
+ }
1622
+ this.setTestData({ userInput: value }, world);
1623
+ }
1475
1624
  setTestData(testData, world = null) {
1476
1625
  if (!testData) {
1477
1626
  return;
@@ -1499,7 +1648,7 @@ class StableBrowser {
1499
1648
  const data = fs.readFileSync(filePath, "utf8");
1500
1649
  const results = [];
1501
1650
  return new Promise((resolve, reject) => {
1502
- const readableStream = new stream.Readable();
1651
+ const readableStream = new Readable();
1503
1652
  readableStream._read = () => { }; // _read is required but you can noop it
1504
1653
  readableStream.push(data);
1505
1654
  readableStream.push(null);
@@ -1679,13 +1828,13 @@ class StableBrowser {
1679
1828
  ])));
1680
1829
  const { data } = await client.send("Page.captureScreenshot", {
1681
1830
  format: "png",
1682
- clip: {
1683
- x: 0,
1684
- y: 0,
1685
- width: viewportWidth,
1686
- height: viewportHeight,
1687
- scale: 1,
1688
- },
1831
+ // clip: {
1832
+ // x: 0,
1833
+ // y: 0,
1834
+ // width: viewportWidth,
1835
+ // height: viewportHeight,
1836
+ // scale: 1,
1837
+ // },
1689
1838
  });
1690
1839
  if (!screenshotPath) {
1691
1840
  return data;
@@ -2511,13 +2660,13 @@ class StableBrowser {
2511
2660
  }
2512
2661
  catch (e) {
2513
2662
  if (e.label === "networkidle") {
2514
- console.log("waitted for the network to be idle timeout");
2663
+ console.log("waited for the network to be idle timeout");
2515
2664
  }
2516
2665
  else if (e.label === "load") {
2517
- console.log("waitted for the load timeout");
2666
+ console.log("waited for the load timeout");
2518
2667
  }
2519
2668
  else if (e.label === "domcontentloaded") {
2520
- console.log("waitted for the domcontent loaded timeout");
2669
+ console.log("waited for the domcontent loaded timeout");
2521
2670
  }
2522
2671
  console.log(".");
2523
2672
  }
@@ -2552,13 +2701,6 @@ class StableBrowser {
2552
2701
  const info = {};
2553
2702
  try {
2554
2703
  await this.page.close();
2555
- if (this.context && this.context.pages && this.context.pages.length > 0) {
2556
- this.context.pages.pop();
2557
- this.page = this.context.pages[this.context.pages.length - 1];
2558
- this.context.page = this.page;
2559
- let title = await this.page.title();
2560
- console.log("Switched to page " + title);
2561
- }
2562
2704
  }
2563
2705
  catch (e) {
2564
2706
  console.log(".");
@@ -2667,33 +2809,18 @@ class StableBrowser {
2667
2809
  }
2668
2810
  async scrollIfNeeded(element, info) {
2669
2811
  try {
2670
- let didScroll = await element.evaluate((node) => {
2671
- const rect = node.getBoundingClientRect();
2672
- if (rect &&
2673
- rect.top >= 0 &&
2674
- rect.left >= 0 &&
2675
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2676
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
2677
- return false;
2678
- }
2679
- else {
2680
- node.scrollIntoView({
2681
- behavior: "smooth",
2682
- block: "center",
2683
- inline: "center",
2684
- });
2685
- return true;
2686
- }
2812
+ await element.scrollIntoViewIfNeeded({
2813
+ timeout: 2000,
2687
2814
  });
2688
- if (didScroll) {
2689
- await new Promise((resolve) => setTimeout(resolve, 500));
2690
- if (info) {
2691
- info.box = await element.boundingBox();
2692
- }
2815
+ await new Promise((resolve) => setTimeout(resolve, 500));
2816
+ if (info) {
2817
+ info.box = await element.boundingBox({
2818
+ timeout: 1000,
2819
+ });
2693
2820
  }
2694
2821
  }
2695
2822
  catch (e) {
2696
- console.log("scroll failed");
2823
+ console.log("#-#");
2697
2824
  }
2698
2825
  }
2699
2826
  _reportToWorld(world, properties) {