automation_model 1.0.398-dev → 1.0.398-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",
@@ -28,6 +31,7 @@ const Types = {
28
31
  SELECT: "select_combobox",
29
32
  VERIFY_PAGE_PATH: "verify_page_path",
30
33
  TYPE_PRESS: "type_press",
34
+ PRESS: "press_key",
31
35
  HOVER: "hover_element",
32
36
  CHECK: "check_element",
33
37
  UNCHECK: "uncheck_element",
@@ -36,7 +40,10 @@ const Types = {
36
40
  SET_DATE_TIME: "set_date_time",
37
41
  SET_VIEWPORT: "set_viewport",
38
42
  VERIFY_VISUAL: "verify_visual",
43
+ LOAD_DATA: "load_data",
44
+ SET_INPUT: "set_input",
39
45
  };
46
+ export const apps = {};
40
47
  class StableBrowser {
41
48
  constructor(browser, page, logger = null, context = null) {
42
49
  this.browser = browser;
@@ -46,6 +53,7 @@ class StableBrowser {
46
53
  this.project_path = null;
47
54
  this.webLogFile = null;
48
55
  this.configuration = null;
56
+ this.appName = "main";
49
57
  if (!this.logger) {
50
58
  this.logger = console;
51
59
  }
@@ -76,14 +84,28 @@ class StableBrowser {
76
84
  this.registerRequestListener();
77
85
  context.pages = [this.page];
78
86
  context.pageLoading = { status: false };
87
+ this.registerPageEventListeners(context);
88
+ }
89
+ registerPageEventListeners(context) {
79
90
  context.playContext.on("page", async function (page) {
80
91
  context.pageLoading.status = true;
81
92
  this.page = page;
82
93
  context.page = page;
83
94
  context.pages.push(page);
84
- this.webLogFile = this.getWebLogFile(logFolder);
85
- this.registerConsoleLogListener(page, context, this.webLogFile);
86
- 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
+ });
87
109
  try {
88
110
  await this.waitForPageLoad();
89
111
  console.log("Switch page: " + (await page.title()));
@@ -94,6 +116,36 @@ class StableBrowser {
94
116
  context.pageLoading.status = false;
95
117
  }.bind(this));
96
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
+ }
97
149
  getWebLogFile(logFolder) {
98
150
  if (!fs.existsSync(logFolder)) {
99
151
  fs.mkdirSync(logFolder, { recursive: true });
@@ -178,24 +230,78 @@ class StableBrowser {
178
230
  }
179
231
  return text;
180
232
  }
181
- _getLocator(locator, scope, _params) {
182
- if (locator.type === "pw_selector") {
183
- 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
+ }
184
256
  }
257
+ }
258
+ _getLocator(locator, scope, _params) {
259
+ locator = this._fixLocatorUsingParams(locator, _params);
260
+ let locatorReturn;
185
261
  if (locator.role) {
186
262
  if (locator.role[1].nameReg) {
187
263
  locator.role[1].name = reg_parser(locator.role[1].nameReg);
188
264
  delete locator.role[1].nameReg;
189
265
  }
190
- if (locator.role[1].name) {
191
- locator.role[1].name = this._fixUsingParams(locator.role[1].name, _params);
192
- }
193
- 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]);
194
270
  }
195
271
  if (locator.css) {
196
- 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
+ }
197
285
  }
198
- throw new Error("unknown locator type");
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");
303
+ }
304
+ return locatorReturn;
199
305
  }
200
306
  async _locateElmentByTextClimbCss(scope, text, climb, css, _params) {
201
307
  let result = await this._locateElementByText(scope, this._fixUsingParams(text, _params), "*", false, true, _params);
@@ -406,6 +512,8 @@ class StableBrowser {
406
512
  if (result.foundElements.length > 0) {
407
513
  let dialogCloseLocator = result.foundElements[0].locator;
408
514
  await dialogCloseLocator.click();
515
+ // wait for the dialog to close
516
+ await dialogCloseLocator.waitFor({ state: "hidden" });
409
517
  return { rerun: true };
410
518
  }
411
519
  }
@@ -414,7 +522,7 @@ class StableBrowser {
414
522
  }
415
523
  async _locate(selectors, info, _params, timeout = 30000) {
416
524
  for (let i = 0; i < 3; i++) {
417
- info.log += "attempt " + i + ": totoal locators " + selectors.locators.length + "\n";
525
+ info.log += "attempt " + i + ": total locators " + selectors.locators.length + "\n";
418
526
  for (let j = 0; j < selectors.locators.length; j++) {
419
527
  let selector = selectors.locators[j];
420
528
  info.log += "searching for locator " + j + ":" + JSON.stringify(selector) + "\n";
@@ -434,9 +542,27 @@ class StableBrowser {
434
542
  //let arrayMode = Array.isArray(selectors);
435
543
  let scope = this.page;
436
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
+ };
437
558
  info.log += "searching for iframe " + selectors.iframe_src + "/" + selectors.frameLocators + "\n";
438
559
  while (true) {
439
560
  let frameFound = false;
561
+ if (selectors.nestFrmLoc) {
562
+ scope = findFrame(selectors.nestFrmLoc, scope);
563
+ frameFound = true;
564
+ break;
565
+ }
440
566
  if (selectors.frameLocators) {
441
567
  for (let i = 0; i < selectors.frameLocators.length; i++) {
442
568
  let frameLocator = selectors.frameLocators[i];
@@ -600,6 +726,9 @@ class StableBrowser {
600
726
  async click(selectors, _params, options = {}, world = null) {
601
727
  this._validateSelectors(selectors);
602
728
  const startTime = Date.now();
729
+ if (options && options.context) {
730
+ selectors.locators[0].text = options.context;
731
+ }
603
732
  const info = {};
604
733
  info.log = "***** click on " + selectors.element_name + " *****\n";
605
734
  info.operation = "click";
@@ -613,14 +742,14 @@ class StableBrowser {
613
742
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
614
743
  try {
615
744
  await this._highlightElements(element);
616
- await element.click({ timeout: 5000 });
745
+ await element.click();
617
746
  await new Promise((resolve) => setTimeout(resolve, 1000));
618
747
  }
619
748
  catch (e) {
620
749
  // await this.closeUnexpectedPopups();
621
750
  info.log += "click failed, will try again" + "\n";
622
751
  element = await this._locate(selectors, info, _params);
623
- await element.click({ timeout: 10000, force: true });
752
+ await element.dispatchEvent("click");
624
753
  await new Promise((resolve) => setTimeout(resolve, 1000));
625
754
  }
626
755
  await this.waitForPageLoad();
@@ -673,7 +802,7 @@ class StableBrowser {
673
802
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
674
803
  try {
675
804
  await this._highlightElements(element);
676
- await element.setChecked(checked, { timeout: 5000 });
805
+ await element.setChecked(checked);
677
806
  await new Promise((resolve) => setTimeout(resolve, 1000));
678
807
  }
679
808
  catch (e) {
@@ -737,7 +866,7 @@ class StableBrowser {
737
866
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
738
867
  try {
739
868
  await this._highlightElements(element);
740
- await element.hover({ timeout: 10000 });
869
+ await element.hover();
741
870
  await new Promise((resolve) => setTimeout(resolve, 1000));
742
871
  }
743
872
  catch (e) {
@@ -799,7 +928,7 @@ class StableBrowser {
799
928
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
800
929
  try {
801
930
  await this._highlightElements(element);
802
- await element.selectOption(values, { timeout: 5000 });
931
+ await element.selectOption(values);
803
932
  }
804
933
  catch (e) {
805
934
  //await this.closeUnexpectedPopups();
@@ -908,71 +1037,45 @@ class StableBrowser {
908
1037
  });
909
1038
  }
910
1039
  }
911
- 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.
912
1042
  this._validateSelectors(selectors);
913
1043
  const startTime = Date.now();
914
- let error = null;
915
- let screenshotId = null;
916
- let screenshotPath = null;
917
1044
  const info = {};
918
- info.log = "";
919
- info.operation = Types.SET_DATE_TIME;
1045
+ info.log = "***** set input value " + selectors.element_name + " *****\n";
1046
+ info.operation = "setInputValue";
920
1047
  info.selectors = selectors;
1048
+ value = this._fixUsingParams(value, _params);
921
1049
  info.value = value;
1050
+ let error = null;
1051
+ let screenshotId = null;
1052
+ let screenshotPath = null;
922
1053
  try {
923
1054
  value = await this._replaceWithLocalData(value, this);
924
1055
  let element = await this._locate(selectors, info, _params);
925
- //insert red border around the element
926
1056
  await this.scrollIfNeeded(element, info);
927
1057
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
928
1058
  await this._highlightElements(element);
929
1059
  try {
930
- await element.click();
931
- await new Promise((resolve) => setTimeout(resolve, 500));
932
- if (format) {
933
- value = dayjs(value).format(format);
934
- await element.fill(value);
935
- }
936
- else {
937
- const dateTimeValue = await getDateTimeValue({ value, element });
938
- await element.evaluateHandle((el, dateTimeValue) => {
939
- el.value = ""; // clear input
940
- el.value = dateTimeValue;
941
- }, dateTimeValue);
942
- }
943
- if (enter) {
944
- await new Promise((resolve) => setTimeout(resolve, 2000));
945
- await this.page.keyboard.press("Enter");
946
- await this.waitForPageLoad();
947
- }
1060
+ await element.evaluateHandle((el, value) => {
1061
+ el.value = value;
1062
+ }, value);
948
1063
  }
949
1064
  catch (error) {
950
- //await this.closeUnexpectedPopups();
951
- this.logger.error("setting date time input failed " + JSON.stringify(info));
952
- 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));
953
1067
  info.screenshotPath = screenshotPath;
954
1068
  Object.assign(error, { info: info });
955
- await element.click();
956
- await new Promise((resolve) => setTimeout(resolve, 500));
957
- if (format) {
958
- value = dayjs(value).format(format);
959
- await element.fill(value);
960
- }
961
- else {
962
- const dateTimeValue = await getDateTimeValue({ value, element });
963
- await element.evaluateHandle((el, dateTimeValue) => {
964
- el.value = ""; // clear input
965
- el.value = dateTimeValue;
966
- }, dateTimeValue);
967
- }
968
- if (enter) {
969
- await new Promise((resolve) => setTimeout(resolve, 2000));
970
- await this.page.keyboard.press("Enter");
971
- await this.waitForPageLoad();
972
- }
1069
+ await element.evaluateHandle((el, value) => {
1070
+ el.value = value;
1071
+ });
973
1072
  }
974
1073
  }
975
- 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 });
976
1079
  error = e;
977
1080
  throw e;
978
1081
  }
@@ -980,10 +1083,10 @@ class StableBrowser {
980
1083
  const endTime = Date.now();
981
1084
  this._reportToWorld(world, {
982
1085
  element_name: selectors.element_name,
983
- type: Types.SET_DATE_TIME,
984
- screenshotId,
1086
+ type: Types.SET_INPUT,
1087
+ text: `Set input value`,
985
1088
  value: value,
986
- text: `setDateTime input with value: ${value}`,
1089
+ screenshotId,
987
1090
  result: error
988
1091
  ? {
989
1092
  status: "FAILED",
@@ -1000,7 +1103,7 @@ class StableBrowser {
1000
1103
  });
1001
1104
  }
1002
1105
  }
1003
- 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) {
1004
1107
  this._validateSelectors(selectors);
1005
1108
  const startTime = Date.now();
1006
1109
  let error = null;
@@ -1012,6 +1115,7 @@ class StableBrowser {
1012
1115
  info.selectors = selectors;
1013
1116
  info.value = value;
1014
1117
  try {
1118
+ value = await this._replaceWithLocalData(value, this);
1015
1119
  let element = await this._locate(selectors, info, _params);
1016
1120
  //insert red border around the element
1017
1121
  await this.scrollIfNeeded(element, info);
@@ -1020,28 +1124,51 @@ class StableBrowser {
1020
1124
  try {
1021
1125
  await element.click();
1022
1126
  await new Promise((resolve) => setTimeout(resolve, 500));
1023
- const dateTimeValue = await getDateTimeValue({ value, element });
1024
- await element.evaluateHandle((el, dateTimeValue) => {
1025
- el.value = ""; // clear input
1026
- el.value = dateTimeValue;
1027
- }, 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
+ }
1028
1143
  }
1029
- catch (error) {
1144
+ catch (err) {
1030
1145
  //await this.closeUnexpectedPopups();
1031
1146
  this.logger.error("setting date time input failed " + JSON.stringify(info));
1032
- 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));
1033
1149
  info.screenshotPath = screenshotPath;
1034
- Object.assign(error, { info: info });
1150
+ Object.assign(err, { info: info });
1035
1151
  await element.click();
1036
1152
  await new Promise((resolve) => setTimeout(resolve, 500));
1037
- const dateTimeValue = await getDateTimeValue({ value, element });
1038
- await element.evaluateHandle((el, dateTimeValue) => {
1039
- el.value = ""; // clear input
1040
- el.value = dateTimeValue;
1041
- }, 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
+ }
1042
1169
  }
1043
1170
  }
1044
- catch (error) {
1171
+ catch (e) {
1045
1172
  error = e;
1046
1173
  throw e;
1047
1174
  }
@@ -1091,20 +1218,32 @@ class StableBrowser {
1091
1218
  await this.scrollIfNeeded(element, info);
1092
1219
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1093
1220
  await this._highlightElements(element);
1094
- try {
1095
- let currentValue = await element.inputValue();
1096
- if (currentValue) {
1097
- await element.fill("");
1221
+ if (options === null || options === undefined || !options.press) {
1222
+ try {
1223
+ let currentValue = await element.inputValue();
1224
+ if (currentValue) {
1225
+ await element.fill("");
1226
+ }
1227
+ }
1228
+ catch (e) {
1229
+ this.logger.info("unable to clear input value");
1098
1230
  }
1099
1231
  }
1100
- catch (e) {
1101
- this.logger.info("unable to clear input value");
1102
- }
1103
- try {
1104
- await element.click({ timeout: 5000 });
1232
+ if (options === null || options === undefined || options.press) {
1233
+ try {
1234
+ await element.click({ timeout: 5000 });
1235
+ }
1236
+ catch (e) {
1237
+ await element.dispatchEvent("click");
1238
+ }
1105
1239
  }
1106
- catch (e) {
1107
- await element.dispatchEvent("click");
1240
+ else {
1241
+ try {
1242
+ await element.focus();
1243
+ }
1244
+ catch (e) {
1245
+ await element.dispatchEvent("focus");
1246
+ }
1108
1247
  }
1109
1248
  await new Promise((resolve) => setTimeout(resolve, 500));
1110
1249
  const valueSegment = _value.split("&&");
@@ -1192,7 +1331,7 @@ class StableBrowser {
1192
1331
  let element = await this._locate(selectors, info, _params);
1193
1332
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1194
1333
  await this._highlightElements(element);
1195
- await element.fill(value, { timeout: 10000 });
1334
+ await element.fill(value);
1196
1335
  await element.dispatchEvent("change");
1197
1336
  if (enter) {
1198
1337
  await new Promise((resolve) => setTimeout(resolve, 2000));
@@ -1411,7 +1550,7 @@ class StableBrowser {
1411
1550
  return info;
1412
1551
  }
1413
1552
  catch (e) {
1414
- //await this.closeUnexpectedPopups();
1553
+ await this.closeUnexpectedPopups();
1415
1554
  this.logger.error("verify element contains text failed " + info.log);
1416
1555
  ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
1417
1556
  info.screenshotPath = screenshotPath;
@@ -1459,6 +1598,29 @@ class StableBrowser {
1459
1598
  }
1460
1599
  return dataFile;
1461
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
+ }
1462
1624
  setTestData(testData, world = null) {
1463
1625
  if (!testData) {
1464
1626
  return;
@@ -1486,7 +1648,7 @@ class StableBrowser {
1486
1648
  const data = fs.readFileSync(filePath, "utf8");
1487
1649
  const results = [];
1488
1650
  return new Promise((resolve, reject) => {
1489
- const readableStream = new stream.Readable();
1651
+ const readableStream = new Readable();
1490
1652
  readableStream._read = () => { }; // _read is required but you can noop it
1491
1653
  readableStream.push(data);
1492
1654
  readableStream.push(null);
@@ -1666,13 +1828,13 @@ class StableBrowser {
1666
1828
  ])));
1667
1829
  const { data } = await client.send("Page.captureScreenshot", {
1668
1830
  format: "png",
1669
- clip: {
1670
- x: 0,
1671
- y: 0,
1672
- width: viewportWidth,
1673
- height: viewportHeight,
1674
- scale: 1,
1675
- },
1831
+ // clip: {
1832
+ // x: 0,
1833
+ // y: 0,
1834
+ // width: viewportWidth,
1835
+ // height: viewportHeight,
1836
+ // scale: 1,
1837
+ // },
1676
1838
  });
1677
1839
  if (!screenshotPath) {
1678
1840
  return data;
@@ -2498,13 +2660,13 @@ class StableBrowser {
2498
2660
  }
2499
2661
  catch (e) {
2500
2662
  if (e.label === "networkidle") {
2501
- console.log("waitted for the network to be idle timeout");
2663
+ console.log("waited for the network to be idle timeout");
2502
2664
  }
2503
2665
  else if (e.label === "load") {
2504
- console.log("waitted for the load timeout");
2666
+ console.log("waited for the load timeout");
2505
2667
  }
2506
2668
  else if (e.label === "domcontentloaded") {
2507
- console.log("waitted for the domcontent loaded timeout");
2669
+ console.log("waited for the domcontent loaded timeout");
2508
2670
  }
2509
2671
  console.log(".");
2510
2672
  }
@@ -2539,13 +2701,6 @@ class StableBrowser {
2539
2701
  const info = {};
2540
2702
  try {
2541
2703
  await this.page.close();
2542
- if (this.context && this.context.pages && this.context.pages.length > 0) {
2543
- this.context.pages.pop();
2544
- this.page = this.context.pages[this.context.pages.length - 1];
2545
- this.context.page = this.page;
2546
- let title = await this.page.title();
2547
- console.log("Switched to page " + title);
2548
- }
2549
2704
  }
2550
2705
  catch (e) {
2551
2706
  console.log(".");
@@ -2654,33 +2809,18 @@ class StableBrowser {
2654
2809
  }
2655
2810
  async scrollIfNeeded(element, info) {
2656
2811
  try {
2657
- let didScroll = await element.evaluate((node) => {
2658
- const rect = node.getBoundingClientRect();
2659
- if (rect &&
2660
- rect.top >= 0 &&
2661
- rect.left >= 0 &&
2662
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
2663
- rect.right <= (window.innerWidth || document.documentElement.clientWidth)) {
2664
- return false;
2665
- }
2666
- else {
2667
- node.scrollIntoView({
2668
- behavior: "smooth",
2669
- block: "center",
2670
- inline: "center",
2671
- });
2672
- return true;
2673
- }
2812
+ await element.scrollIntoViewIfNeeded({
2813
+ timeout: 2000,
2674
2814
  });
2675
- if (didScroll) {
2676
- await new Promise((resolve) => setTimeout(resolve, 500));
2677
- if (info) {
2678
- info.box = await element.boundingBox();
2679
- }
2815
+ await new Promise((resolve) => setTimeout(resolve, 500));
2816
+ if (info) {
2817
+ info.box = await element.boundingBox({
2818
+ timeout: 1000,
2819
+ });
2680
2820
  }
2681
2821
  }
2682
2822
  catch (e) {
2683
- console.log("scroll failed");
2823
+ console.log("#-#");
2684
2824
  }
2685
2825
  }
2686
2826
  _reportToWorld(world, properties) {