automation_model 1.0.597-dev → 1.0.599-dev
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.
- package/lib/command_common.d.ts +1 -1
- package/lib/command_common.js +21 -25
- package/lib/command_common.js.map +1 -1
- package/lib/stable_browser.d.ts +4 -5
- package/lib/stable_browser.js +184 -176
- package/lib/stable_browser.js.map +1 -1
- package/package.json +1 -1
package/lib/stable_browser.js
CHANGED
|
@@ -7,6 +7,7 @@ import path from "path";
|
|
|
7
7
|
import reg_parser from "regex-parser";
|
|
8
8
|
import { findDateAlternatives, findNumberAlternatives } from "./analyze_helper.js";
|
|
9
9
|
import { getDateTimeValue } from "./date_time.js";
|
|
10
|
+
import drawRectangle from "./drawRect.js";
|
|
10
11
|
//import { closeUnexpectedPopups } from "./popups.js";
|
|
11
12
|
import { getTableCells, getTableData } from "./table_analyze.js";
|
|
12
13
|
import { _convertToRegexQuery, _copyContext, _fixLocatorUsingParams, _fixUsingParams, _getServerUrl, extractStepExampleParameters, KEYBOARD_EVENTS, maskValue, replaceWithLocalTestData, scrollPageToLoadLazyElements, unEscapeString, } from "./utils.js";
|
|
@@ -52,6 +53,9 @@ export const Types = {
|
|
|
52
53
|
VERIFY_TEXT_WITH_RELATION: "verify_text_with_relation",
|
|
53
54
|
};
|
|
54
55
|
export const apps = {};
|
|
56
|
+
const formatElementName = (elementName) => {
|
|
57
|
+
return elementName ? JSON.stringify(elementName) : "element";
|
|
58
|
+
};
|
|
55
59
|
class StableBrowser {
|
|
56
60
|
browser;
|
|
57
61
|
page;
|
|
@@ -252,7 +256,7 @@ class StableBrowser {
|
|
|
252
256
|
highlight: false,
|
|
253
257
|
};
|
|
254
258
|
try {
|
|
255
|
-
await _preCommand(state, this
|
|
259
|
+
await _preCommand(state, this);
|
|
256
260
|
await this.page.goto(url, {
|
|
257
261
|
timeout: 60000,
|
|
258
262
|
});
|
|
@@ -373,7 +377,7 @@ class StableBrowser {
|
|
|
373
377
|
}
|
|
374
378
|
return { elementCount: tagCount, randomToken };
|
|
375
379
|
}
|
|
376
|
-
async _collectLocatorInformation(selectorHierarchy, index = 0, scope, foundLocators, _params, info, visibleOnly = true, allowDisabled = false) {
|
|
380
|
+
async _collectLocatorInformation(selectorHierarchy, index = 0, scope, foundLocators, _params, info, visibleOnly = true, allowDisabled = false, element_name = null) {
|
|
377
381
|
if (!info) {
|
|
378
382
|
info = {};
|
|
379
383
|
}
|
|
@@ -400,7 +404,7 @@ class StableBrowser {
|
|
|
400
404
|
let locatorString = await this._locateElmentByTextClimbCss(scope, replacedText, locatorSearch.climb, locatorSearch.css, _params);
|
|
401
405
|
if (!locatorString) {
|
|
402
406
|
info.failCause.textNotFound = true;
|
|
403
|
-
info.failCause.lastError =
|
|
407
|
+
info.failCause.lastError = `failed to locate ${formatElementName(element_name)} by text: ${locatorSearch.text}`;
|
|
404
408
|
return;
|
|
405
409
|
}
|
|
406
410
|
locator = await this._getLocator({ css: locatorString }, scope, _params);
|
|
@@ -410,7 +414,7 @@ class StableBrowser {
|
|
|
410
414
|
let result = await this._locateElementByText(scope, text, locatorSearch.tag, false, locatorSearch.partial === true, true, _params);
|
|
411
415
|
if (result.elementCount === 0) {
|
|
412
416
|
info.failCause.textNotFound = true;
|
|
413
|
-
info.failCause.lastError =
|
|
417
|
+
info.failCause.lastError = `failed to locate ${formatElementName(element_name)} by text: ${text}`;
|
|
414
418
|
return;
|
|
415
419
|
}
|
|
416
420
|
locatorSearch.css = "[data-blinq-id-" + result.randomToken + "]";
|
|
@@ -462,11 +466,11 @@ class StableBrowser {
|
|
|
462
466
|
info.printMessages = {};
|
|
463
467
|
}
|
|
464
468
|
if (info.locatorLog && !visible) {
|
|
465
|
-
info.failCause.lastError =
|
|
469
|
+
info.failCause.lastError = `${formatElementName(element_name)} is not visible, searching for ${originalLocatorSearch}`;
|
|
466
470
|
info.locatorLog.setLocatorSearchStatus(originalLocatorSearch, "FOUND_NOT_VISIBLE");
|
|
467
471
|
}
|
|
468
472
|
if (info.locatorLog && !enabled) {
|
|
469
|
-
info.failCause.lastError =
|
|
473
|
+
info.failCause.lastError = `${formatElementName(element_name)} is disabled, searching for ${originalLocatorSearch}`;
|
|
470
474
|
info.locatorLog.setLocatorSearchStatus(originalLocatorSearch, "FOUND_NOT_ENABLED");
|
|
471
475
|
}
|
|
472
476
|
if (!info.printMessages[j.toString()]) {
|
|
@@ -546,7 +550,13 @@ class StableBrowser {
|
|
|
546
550
|
}
|
|
547
551
|
let element = await this._locate_internal(selectors, info, _params, timeout, allowDisabled);
|
|
548
552
|
if (!element.rerun) {
|
|
549
|
-
|
|
553
|
+
const randomToken = Math.random().toString(36).substring(7);
|
|
554
|
+
element.evaluate((el, randomToken) => {
|
|
555
|
+
el.setAttribute("data-blinq-id-" + randomToken, "");
|
|
556
|
+
}, randomToken);
|
|
557
|
+
const scope = element._frame ?? element.page();
|
|
558
|
+
const newSelector = scope.locator("[data-blinq-id-" + randomToken + "]");
|
|
559
|
+
return newSelector;
|
|
550
560
|
}
|
|
551
561
|
}
|
|
552
562
|
throw new Error("unable to locate element " + JSON.stringify(selectors));
|
|
@@ -619,7 +629,7 @@ class StableBrowser {
|
|
|
619
629
|
//info.log += "unable to locate iframe " + selectors.iframe_src + "\n";
|
|
620
630
|
if (Date.now() - startTime > timeout) {
|
|
621
631
|
info.failCause.iframeNotFound = true;
|
|
622
|
-
info.failCause.lastError =
|
|
632
|
+
info.failCause.lastError = `unable to locate iframe "${selectors.iframe_src}"`;
|
|
623
633
|
throw new Error("unable to locate iframe " + selectors.iframe_src);
|
|
624
634
|
}
|
|
625
635
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -693,17 +703,17 @@ class StableBrowser {
|
|
|
693
703
|
}
|
|
694
704
|
// info.log += "scanning locators in priority 1" + "\n";
|
|
695
705
|
let onlyPriority3 = selectorsLocators[0].priority === 3;
|
|
696
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["1"], scope, _params, info, visibleOnly, allowDisabled);
|
|
706
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["1"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
697
707
|
if (result.foundElements.length === 0) {
|
|
698
708
|
// info.log += "scanning locators in priority 2" + "\n";
|
|
699
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["2"], scope, _params, info, visibleOnly, allowDisabled);
|
|
709
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["2"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
700
710
|
}
|
|
701
711
|
if (result.foundElements.length === 0 && onlyPriority3) {
|
|
702
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled);
|
|
712
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
703
713
|
}
|
|
704
714
|
else {
|
|
705
715
|
if (result.foundElements.length === 0 && !highPriorityOnly) {
|
|
706
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled);
|
|
716
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
707
717
|
}
|
|
708
718
|
}
|
|
709
719
|
let foundElements = result.foundElements;
|
|
@@ -771,11 +781,11 @@ class StableBrowser {
|
|
|
771
781
|
//info.log += "failed to locate unique element, total elements found " + locatorsCount + "\n";
|
|
772
782
|
info.failCause.locatorNotFound = true;
|
|
773
783
|
if (!info?.failCause?.lastError) {
|
|
774
|
-
info.failCause.lastError =
|
|
784
|
+
info.failCause.lastError = `failed to locate ${formatElementName(selectors.element_name)}, ${locatorsCount > 0 ? `${locatorsCount} matching elements found` : "no matching elements found"}`;
|
|
775
785
|
}
|
|
776
786
|
throw new Error("failed to locate first element no elements found, " + info.log);
|
|
777
787
|
}
|
|
778
|
-
async _scanLocatorsGroup(locatorsGroup, scope, _params, info, visibleOnly, allowDisabled = false) {
|
|
788
|
+
async _scanLocatorsGroup(locatorsGroup, scope, _params, info, visibleOnly, allowDisabled = false, element_name) {
|
|
779
789
|
let foundElements = [];
|
|
780
790
|
const result = {
|
|
781
791
|
foundElements: foundElements,
|
|
@@ -783,7 +793,7 @@ class StableBrowser {
|
|
|
783
793
|
for (let i = 0; i < locatorsGroup.length; i++) {
|
|
784
794
|
let foundLocators = [];
|
|
785
795
|
try {
|
|
786
|
-
await this._collectLocatorInformation(locatorsGroup, i, scope, foundLocators, _params, info, visibleOnly, allowDisabled);
|
|
796
|
+
await this._collectLocatorInformation(locatorsGroup, i, scope, foundLocators, _params, info, visibleOnly, allowDisabled, element_name);
|
|
787
797
|
}
|
|
788
798
|
catch (e) {
|
|
789
799
|
// this call can fail it the browser is navigating
|
|
@@ -791,7 +801,7 @@ class StableBrowser {
|
|
|
791
801
|
// this.logger.debug(e);
|
|
792
802
|
foundLocators = [];
|
|
793
803
|
try {
|
|
794
|
-
await this._collectLocatorInformation(locatorsGroup, i, this.page, foundLocators, _params, info, visibleOnly, allowDisabled);
|
|
804
|
+
await this._collectLocatorInformation(locatorsGroup, i, this.page, foundLocators, _params, info, visibleOnly, allowDisabled, element_name);
|
|
795
805
|
}
|
|
796
806
|
catch (e) {
|
|
797
807
|
this.logger.info("unable to use locator (second try) " + JSON.stringify(locatorsGroup[i]));
|
|
@@ -827,7 +837,7 @@ class StableBrowser {
|
|
|
827
837
|
operation: "simpleClick",
|
|
828
838
|
log: "***** click on " + elementDescription + " *****\n",
|
|
829
839
|
};
|
|
830
|
-
_preCommand(state, this
|
|
840
|
+
_preCommand(state, this);
|
|
831
841
|
const startTime = Date.now();
|
|
832
842
|
let timeout = 30000;
|
|
833
843
|
if (options && options.timeout) {
|
|
@@ -876,7 +886,7 @@ class StableBrowser {
|
|
|
876
886
|
operation: "simpleClickType",
|
|
877
887
|
log: "***** click type on " + elementDescription + " *****\n",
|
|
878
888
|
};
|
|
879
|
-
_preCommand(state, this
|
|
889
|
+
_preCommand(state, this);
|
|
880
890
|
const startTime = Date.now();
|
|
881
891
|
let timeout = 30000;
|
|
882
892
|
if (options && options.timeout) {
|
|
@@ -924,7 +934,7 @@ class StableBrowser {
|
|
|
924
934
|
log: "***** click on " + selectors.element_name + " *****\n",
|
|
925
935
|
};
|
|
926
936
|
try {
|
|
927
|
-
await _preCommand(state, this
|
|
937
|
+
await _preCommand(state, this);
|
|
928
938
|
// if (state.options && state.options.context) {
|
|
929
939
|
// state.selectors.locators[0].text = state.options.context;
|
|
930
940
|
// }
|
|
@@ -960,18 +970,18 @@ class StableBrowser {
|
|
|
960
970
|
log: "***** check " + selectors.element_name + " *****\n",
|
|
961
971
|
};
|
|
962
972
|
try {
|
|
963
|
-
await _preCommand(state, this
|
|
973
|
+
await _preCommand(state, this);
|
|
964
974
|
state.info.checked = checked;
|
|
965
975
|
// let element = await this._locate(selectors, info, _params);
|
|
966
976
|
// ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
967
977
|
try {
|
|
968
|
-
if (world && world.screenshot && !world.screenshotPath) {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
972
|
-
await this._unHighlightElements(element);
|
|
973
|
-
}
|
|
978
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
979
|
+
// console.log(`Highlighting while running from recorder`);
|
|
980
|
+
await this._highlightElements(element);
|
|
974
981
|
await state.element.setChecked(checked);
|
|
982
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
983
|
+
// await this._unHighlightElements(element);
|
|
984
|
+
// }
|
|
975
985
|
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
976
986
|
// await this._unHighlightElements(element);
|
|
977
987
|
}
|
|
@@ -1009,10 +1019,10 @@ class StableBrowser {
|
|
|
1009
1019
|
log: "***** hover " + selectors.element_name + " *****\n",
|
|
1010
1020
|
};
|
|
1011
1021
|
try {
|
|
1012
|
-
await _preCommand(state, this
|
|
1022
|
+
await _preCommand(state, this);
|
|
1013
1023
|
try {
|
|
1014
1024
|
await state.element.hover();
|
|
1015
|
-
await _screenshot(state, this);
|
|
1025
|
+
// await _screenshot(state, this);
|
|
1016
1026
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1017
1027
|
}
|
|
1018
1028
|
catch (e) {
|
|
@@ -1020,10 +1030,10 @@ class StableBrowser {
|
|
|
1020
1030
|
state.info.log += "hover failed, will try again" + "\n";
|
|
1021
1031
|
state.element = await this._locate(selectors, state.info, _params);
|
|
1022
1032
|
await state.element.hover({ timeout: 10000 });
|
|
1023
|
-
await _screenshot(state, this);
|
|
1033
|
+
// await _screenshot(state, this);
|
|
1024
1034
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1025
1035
|
}
|
|
1026
|
-
|
|
1036
|
+
await _screenshot(state, this);
|
|
1027
1037
|
await this.waitForPageLoad();
|
|
1028
1038
|
return state.info;
|
|
1029
1039
|
}
|
|
@@ -1050,7 +1060,7 @@ class StableBrowser {
|
|
|
1050
1060
|
log: "***** select option " + selectors.element_name + " *****\n",
|
|
1051
1061
|
};
|
|
1052
1062
|
try {
|
|
1053
|
-
await _preCommand(state, this
|
|
1063
|
+
await _preCommand(state, this);
|
|
1054
1064
|
try {
|
|
1055
1065
|
await state.element.selectOption(values);
|
|
1056
1066
|
}
|
|
@@ -1084,7 +1094,7 @@ class StableBrowser {
|
|
|
1084
1094
|
log: "",
|
|
1085
1095
|
};
|
|
1086
1096
|
try {
|
|
1087
|
-
await _preCommand(state, this
|
|
1097
|
+
await _preCommand(state, this);
|
|
1088
1098
|
const valueSegment = state.value.split("&&");
|
|
1089
1099
|
for (let i = 0; i < valueSegment.length; i++) {
|
|
1090
1100
|
if (i > 0) {
|
|
@@ -1127,7 +1137,7 @@ class StableBrowser {
|
|
|
1127
1137
|
log: "***** set input value " + selectors.element_name + " *****\n",
|
|
1128
1138
|
};
|
|
1129
1139
|
try {
|
|
1130
|
-
await _preCommand(state, this
|
|
1140
|
+
await _preCommand(state, this);
|
|
1131
1141
|
let value = await this._replaceWithLocalData(state.value, this);
|
|
1132
1142
|
try {
|
|
1133
1143
|
await state.element.evaluateHandle((el, value) => {
|
|
@@ -1164,7 +1174,7 @@ class StableBrowser {
|
|
|
1164
1174
|
throwError: false,
|
|
1165
1175
|
};
|
|
1166
1176
|
try {
|
|
1167
|
-
await _preCommand(state, this
|
|
1177
|
+
await _preCommand(state, this);
|
|
1168
1178
|
try {
|
|
1169
1179
|
await state.element.click();
|
|
1170
1180
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
@@ -1238,7 +1248,7 @@ class StableBrowser {
|
|
|
1238
1248
|
_value = newValue;
|
|
1239
1249
|
}
|
|
1240
1250
|
try {
|
|
1241
|
-
await _preCommand(state, this
|
|
1251
|
+
await _preCommand(state, this);
|
|
1242
1252
|
state.info.value = _value;
|
|
1243
1253
|
if (options === null || options === undefined || !options.press) {
|
|
1244
1254
|
try {
|
|
@@ -1331,7 +1341,7 @@ class StableBrowser {
|
|
|
1331
1341
|
log: "***** fill on " + selectors.element_name + " with value " + value + "*****\n",
|
|
1332
1342
|
};
|
|
1333
1343
|
try {
|
|
1334
|
-
await _preCommand(state, this
|
|
1344
|
+
await _preCommand(state, this);
|
|
1335
1345
|
await state.element.fill(value);
|
|
1336
1346
|
await state.element.dispatchEvent("change");
|
|
1337
1347
|
if (enter) {
|
|
@@ -1377,19 +1387,21 @@ class StableBrowser {
|
|
|
1377
1387
|
catch (e) {
|
|
1378
1388
|
//ignore
|
|
1379
1389
|
}
|
|
1380
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
1390
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
1381
1391
|
try {
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
}
|
|
1392
|
+
await this._highlightElements(element);
|
|
1393
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
1394
|
+
// // console.log(`Highlighting for get text while running from recorder`);
|
|
1395
|
+
// this._highlightElements(element)
|
|
1396
|
+
// .then(async () => {
|
|
1397
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1398
|
+
// this._unhighlightElements(element).then(
|
|
1399
|
+
// () => {}
|
|
1400
|
+
// // console.log(`Unhighlighting vrtr in recorder is successful`)
|
|
1401
|
+
// );
|
|
1402
|
+
// })
|
|
1403
|
+
// .catch(e);
|
|
1404
|
+
// }
|
|
1393
1405
|
const elementText = await element.innerText();
|
|
1394
1406
|
return {
|
|
1395
1407
|
text: elementText,
|
|
@@ -1436,13 +1448,13 @@ class StableBrowser {
|
|
|
1436
1448
|
}
|
|
1437
1449
|
let foundObj = null;
|
|
1438
1450
|
try {
|
|
1439
|
-
await _preCommand(state, this
|
|
1451
|
+
await _preCommand(state, this);
|
|
1440
1452
|
state.info.pattern = pattern;
|
|
1441
1453
|
foundObj = await this._getText(selectors, 0, _params, options, state.info, world);
|
|
1442
1454
|
if (foundObj && foundObj.element) {
|
|
1443
1455
|
await this.scrollIfNeeded(foundObj.element, state.info);
|
|
1444
1456
|
}
|
|
1445
|
-
await _screenshot(state, this
|
|
1457
|
+
await _screenshot(state, this);
|
|
1446
1458
|
let escapedText = text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
1447
1459
|
pattern = pattern.replace("{text}", escapedText);
|
|
1448
1460
|
let regex = new RegExp(pattern, "im");
|
|
@@ -1487,12 +1499,12 @@ class StableBrowser {
|
|
|
1487
1499
|
}
|
|
1488
1500
|
let foundObj = null;
|
|
1489
1501
|
try {
|
|
1490
|
-
await _preCommand(state, this
|
|
1502
|
+
await _preCommand(state, this);
|
|
1491
1503
|
foundObj = await this._getText(selectors, climb, _params, options, state.info, world);
|
|
1492
1504
|
if (foundObj && foundObj.element) {
|
|
1493
1505
|
await this.scrollIfNeeded(foundObj.element, state.info);
|
|
1494
1506
|
}
|
|
1495
|
-
await _screenshot(state, this
|
|
1507
|
+
await _screenshot(state, this);
|
|
1496
1508
|
const dateAlternatives = findDateAlternatives(text);
|
|
1497
1509
|
const numberAlternatives = findNumberAlternatives(text);
|
|
1498
1510
|
if (dateAlternatives.date) {
|
|
@@ -1681,7 +1693,7 @@ class StableBrowser {
|
|
|
1681
1693
|
}
|
|
1682
1694
|
return data;
|
|
1683
1695
|
}
|
|
1684
|
-
async _screenShot(options = {}, world = null, info = null
|
|
1696
|
+
async _screenShot(options = {}, world = null, info = null) {
|
|
1685
1697
|
// collect url/path/title
|
|
1686
1698
|
if (info) {
|
|
1687
1699
|
if (!info.title) {
|
|
@@ -1710,7 +1722,7 @@ class StableBrowser {
|
|
|
1710
1722
|
const uuidStr = "id_" + randomUUID();
|
|
1711
1723
|
const screenshotPath = path.join(world.screenshotPath, uuidStr + ".png");
|
|
1712
1724
|
try {
|
|
1713
|
-
await this.takeScreenshot(screenshotPath
|
|
1725
|
+
await this.takeScreenshot(screenshotPath);
|
|
1714
1726
|
// let buffer = await this.page.screenshot({ timeout: 4000 });
|
|
1715
1727
|
// // save the buffer to the screenshot path asynchrously
|
|
1716
1728
|
// fs.writeFile(screenshotPath, buffer, (err) => {
|
|
@@ -1721,7 +1733,7 @@ class StableBrowser {
|
|
|
1721
1733
|
result.screenshotId = uuidStr;
|
|
1722
1734
|
result.screenshotPath = screenshotPath;
|
|
1723
1735
|
if (info && info.box) {
|
|
1724
|
-
|
|
1736
|
+
await drawRectangle(screenshotPath, info.box.x, info.box.y, info.box.width, info.box.height);
|
|
1725
1737
|
}
|
|
1726
1738
|
}
|
|
1727
1739
|
catch (e) {
|
|
@@ -1731,7 +1743,7 @@ class StableBrowser {
|
|
|
1731
1743
|
else if (options && options.screenshot) {
|
|
1732
1744
|
result.screenshotPath = options.screenshotPath;
|
|
1733
1745
|
try {
|
|
1734
|
-
await this.takeScreenshot(options.screenshotPath
|
|
1746
|
+
await this.takeScreenshot(options.screenshotPath);
|
|
1735
1747
|
// let buffer = await this.page.screenshot({ timeout: 4000 });
|
|
1736
1748
|
// // save the buffer to the screenshot path asynchrously
|
|
1737
1749
|
// fs.writeFile(options.screenshotPath, buffer, (err) => {
|
|
@@ -1744,12 +1756,12 @@ class StableBrowser {
|
|
|
1744
1756
|
this.logger.info("unable to take screenshot, ignored");
|
|
1745
1757
|
}
|
|
1746
1758
|
if (info && info.box) {
|
|
1747
|
-
|
|
1759
|
+
await drawRectangle(options.screenshotPath, info.box.x, info.box.y, info.box.width, info.box.height);
|
|
1748
1760
|
}
|
|
1749
1761
|
}
|
|
1750
1762
|
return result;
|
|
1751
1763
|
}
|
|
1752
|
-
async takeScreenshot(screenshotPath
|
|
1764
|
+
async takeScreenshot(screenshotPath) {
|
|
1753
1765
|
const playContext = this.context.playContext;
|
|
1754
1766
|
// Using CDP to capture the screenshot
|
|
1755
1767
|
const viewportWidth = Math.max(...(await this.page.evaluate(() => [
|
|
@@ -1767,9 +1779,9 @@ class StableBrowser {
|
|
|
1767
1779
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1768
1780
|
// console.log(`Unhighlighted previous element`);
|
|
1769
1781
|
// }
|
|
1770
|
-
if (focusedElement) {
|
|
1771
|
-
|
|
1772
|
-
}
|
|
1782
|
+
// if (focusedElement) {
|
|
1783
|
+
// await this._highlightElements(focusedElement);
|
|
1784
|
+
// }
|
|
1773
1785
|
if (this.context.browserName === "chromium") {
|
|
1774
1786
|
const client = await playContext.newCDPSession(this.page);
|
|
1775
1787
|
const { data } = await client.send("Page.captureScreenshot", {
|
|
@@ -1791,10 +1803,10 @@ class StableBrowser {
|
|
|
1791
1803
|
else {
|
|
1792
1804
|
screenshotBuffer = await this.page.screenshot();
|
|
1793
1805
|
}
|
|
1794
|
-
if (focusedElement) {
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
}
|
|
1806
|
+
// if (focusedElement) {
|
|
1807
|
+
// // console.log(`Focused element ${JSON.stringify(focusedElement._selector)}`)
|
|
1808
|
+
// await this._unhighlightElements(focusedElement);
|
|
1809
|
+
// }
|
|
1798
1810
|
let image = await Jimp.read(screenshotBuffer);
|
|
1799
1811
|
// Get the image dimensions
|
|
1800
1812
|
const { width, height } = image.bitmap;
|
|
@@ -1821,7 +1833,7 @@ class StableBrowser {
|
|
|
1821
1833
|
};
|
|
1822
1834
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1823
1835
|
try {
|
|
1824
|
-
await _preCommand(state, this
|
|
1836
|
+
await _preCommand(state, this);
|
|
1825
1837
|
await expect(state.element).toHaveCount(1, { timeout: 10000 });
|
|
1826
1838
|
return state.info;
|
|
1827
1839
|
}
|
|
@@ -1844,10 +1856,11 @@ class StableBrowser {
|
|
|
1844
1856
|
text: `Extract attribute from element`,
|
|
1845
1857
|
operation: "extractAttribute",
|
|
1846
1858
|
log: "***** extract attribute " + attribute + " from " + selectors.element_name + " *****\n",
|
|
1859
|
+
allowDisabled: true,
|
|
1847
1860
|
};
|
|
1848
1861
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1849
1862
|
try {
|
|
1850
|
-
await _preCommand(state, this
|
|
1863
|
+
await _preCommand(state, this);
|
|
1851
1864
|
switch (attribute) {
|
|
1852
1865
|
case "inner_text":
|
|
1853
1866
|
state.value = await state.element.innerText();
|
|
@@ -1865,7 +1878,7 @@ class StableBrowser {
|
|
|
1865
1878
|
state.info.value = state.value;
|
|
1866
1879
|
this.setTestData({ [variable]: state.value }, world);
|
|
1867
1880
|
this.logger.info("set test data: " + variable + "=" + state.value);
|
|
1868
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1881
|
+
// await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1869
1882
|
return state.info;
|
|
1870
1883
|
}
|
|
1871
1884
|
catch (e) {
|
|
@@ -1894,7 +1907,7 @@ class StableBrowser {
|
|
|
1894
1907
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1895
1908
|
let val;
|
|
1896
1909
|
try {
|
|
1897
|
-
await _preCommand(state, this
|
|
1910
|
+
await _preCommand(state, this);
|
|
1898
1911
|
switch (attribute) {
|
|
1899
1912
|
case "innerText":
|
|
1900
1913
|
val = String(await state.element.innerText());
|
|
@@ -2036,17 +2049,17 @@ class StableBrowser {
|
|
|
2036
2049
|
if (node && node.style) {
|
|
2037
2050
|
let originalOutline = node.style.outline;
|
|
2038
2051
|
// console.log(`Original outline was: ${originalOutline}`);
|
|
2039
|
-
node.__previousOutline = originalOutline;
|
|
2052
|
+
// node.__previousOutline = originalOutline;
|
|
2040
2053
|
node.style.outline = "2px solid red";
|
|
2041
2054
|
// console.log(`New outline is: ${node.style.outline}`);
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2055
|
+
if (window) {
|
|
2056
|
+
window.addEventListener("beforeunload", function (e) {
|
|
2057
|
+
node.style.outline = originalOutline;
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
setTimeout(function () {
|
|
2061
|
+
node.style.outline = originalOutline;
|
|
2062
|
+
}, 2000);
|
|
2050
2063
|
}
|
|
2051
2064
|
})
|
|
2052
2065
|
.then(() => { })
|
|
@@ -2072,15 +2085,15 @@ class StableBrowser {
|
|
|
2072
2085
|
element.__previousOutline = originalOutline;
|
|
2073
2086
|
// Set the new border to be red and 2px solid
|
|
2074
2087
|
element.style.outline = "2px solid red";
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2088
|
+
if (window) {
|
|
2089
|
+
window.addEventListener("beforeunload", function (e) {
|
|
2090
|
+
element.style.outline = originalOutline;
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2080
2093
|
// Set a timeout to revert to the original border after 2 seconds
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2094
|
+
setTimeout(function () {
|
|
2095
|
+
element.style.outline = originalOutline;
|
|
2096
|
+
}, 2000);
|
|
2084
2097
|
}
|
|
2085
2098
|
return;
|
|
2086
2099
|
}, [css])
|
|
@@ -2095,58 +2108,54 @@ class StableBrowser {
|
|
|
2095
2108
|
console.debug(error);
|
|
2096
2109
|
}
|
|
2097
2110
|
}
|
|
2098
|
-
async _unhighlightElements(scope, css) {
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
catch (error) {
|
|
2147
|
-
// console.debug(error);
|
|
2148
|
-
}
|
|
2149
|
-
}
|
|
2111
|
+
// async _unhighlightElements(scope, css) {
|
|
2112
|
+
// try {
|
|
2113
|
+
// if (!scope) {
|
|
2114
|
+
// return;
|
|
2115
|
+
// }
|
|
2116
|
+
// if (!css) {
|
|
2117
|
+
// scope
|
|
2118
|
+
// .evaluate((node) => {
|
|
2119
|
+
// if (node && node.style) {
|
|
2120
|
+
// if (!node.__previousOutline) {
|
|
2121
|
+
// node.style.outline = "";
|
|
2122
|
+
// } else {
|
|
2123
|
+
// node.style.outline = node.__previousOutline;
|
|
2124
|
+
// }
|
|
2125
|
+
// }
|
|
2126
|
+
// })
|
|
2127
|
+
// .then(() => {})
|
|
2128
|
+
// .catch((e) => {
|
|
2129
|
+
// // console.log(`Error while unhighlighting node ${JSON.stringify(scope)}: ${e}`);
|
|
2130
|
+
// });
|
|
2131
|
+
// } else {
|
|
2132
|
+
// scope
|
|
2133
|
+
// .evaluate(([css]) => {
|
|
2134
|
+
// if (!css) {
|
|
2135
|
+
// return;
|
|
2136
|
+
// }
|
|
2137
|
+
// let elements = Array.from(document.querySelectorAll(css));
|
|
2138
|
+
// for (i = 0; i < elements.length; i++) {
|
|
2139
|
+
// let element = elements[i];
|
|
2140
|
+
// if (!element.style) {
|
|
2141
|
+
// return;
|
|
2142
|
+
// }
|
|
2143
|
+
// if (!element.__previousOutline) {
|
|
2144
|
+
// element.style.outline = "";
|
|
2145
|
+
// } else {
|
|
2146
|
+
// element.style.outline = element.__previousOutline;
|
|
2147
|
+
// }
|
|
2148
|
+
// }
|
|
2149
|
+
// })
|
|
2150
|
+
// .then(() => {})
|
|
2151
|
+
// .catch((e) => {
|
|
2152
|
+
// // console.error(`Error while unhighlighting element in css: ${e}`);
|
|
2153
|
+
// });
|
|
2154
|
+
// }
|
|
2155
|
+
// } catch (error) {
|
|
2156
|
+
// // console.debug(error);
|
|
2157
|
+
// }
|
|
2158
|
+
// }
|
|
2150
2159
|
async verifyPagePath(pathPart, options = {}, world = null) {
|
|
2151
2160
|
const startTime = Date.now();
|
|
2152
2161
|
let error = null;
|
|
@@ -2261,7 +2270,7 @@ class StableBrowser {
|
|
|
2261
2270
|
let dateAlternatives = findDateAlternatives(text);
|
|
2262
2271
|
let numberAlternatives = findNumberAlternatives(text);
|
|
2263
2272
|
try {
|
|
2264
|
-
await _preCommand(state, this
|
|
2273
|
+
await _preCommand(state, this);
|
|
2265
2274
|
state.info.text = text;
|
|
2266
2275
|
while (true) {
|
|
2267
2276
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, text, state);
|
|
@@ -2275,31 +2284,31 @@ class StableBrowser {
|
|
|
2275
2284
|
if (resultWithElementsFound[0].randomToken) {
|
|
2276
2285
|
const frame = resultWithElementsFound[0].frame;
|
|
2277
2286
|
const dataAttribute = `[data-blinq-id-${resultWithElementsFound[0].randomToken}]`;
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2287
|
+
await this._highlightElements(frame, dataAttribute);
|
|
2288
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
2289
|
+
// console.log(`Highlighting for verify text is found while running from recorder`);
|
|
2290
|
+
// this._highlightElements(frame, dataAttribute).then(async () => {
|
|
2291
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
2292
|
+
// this._unhighlightElements(frame, dataAttribute)
|
|
2293
|
+
// .then(async () => {
|
|
2294
|
+
// console.log(`Unhighlighted frame dataAttribute successfully`);
|
|
2295
|
+
// })
|
|
2296
|
+
// .catch(
|
|
2297
|
+
// (e) => {}
|
|
2298
|
+
// console.error(e)
|
|
2299
|
+
// );
|
|
2300
|
+
// });
|
|
2301
|
+
// }
|
|
2291
2302
|
const element = await frame.locator(dataAttribute).first();
|
|
2292
2303
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2293
2304
|
// await this._unhighlightElements(frame, dataAttribute);
|
|
2294
2305
|
if (element) {
|
|
2295
2306
|
await this.scrollIfNeeded(element, state.info);
|
|
2296
2307
|
await element.dispatchEvent("bvt_verify_page_contains_text");
|
|
2297
|
-
await _screenshot(state, this, element);
|
|
2308
|
+
// await _screenshot(state, this, element);
|
|
2298
2309
|
}
|
|
2299
2310
|
}
|
|
2300
|
-
|
|
2301
|
-
await _screenshot(state, this);
|
|
2302
|
-
}
|
|
2311
|
+
await _screenshot(state, this);
|
|
2303
2312
|
return state.info;
|
|
2304
2313
|
}
|
|
2305
2314
|
// await expect(element).toHaveCount(1, { timeout: 10000 });
|
|
@@ -2335,7 +2344,7 @@ class StableBrowser {
|
|
|
2335
2344
|
let dateAlternatives = findDateAlternatives(text);
|
|
2336
2345
|
let numberAlternatives = findNumberAlternatives(text);
|
|
2337
2346
|
try {
|
|
2338
|
-
await _preCommand(state, this
|
|
2347
|
+
await _preCommand(state, this);
|
|
2339
2348
|
state.info.text = text;
|
|
2340
2349
|
while (true) {
|
|
2341
2350
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, text, state);
|
|
@@ -2387,7 +2396,7 @@ class StableBrowser {
|
|
|
2387
2396
|
let numberAlternatives = findNumberAlternatives(textToVerify);
|
|
2388
2397
|
let foundAncore = false;
|
|
2389
2398
|
try {
|
|
2390
|
-
await _preCommand(state, this
|
|
2399
|
+
await _preCommand(state, this);
|
|
2391
2400
|
state.info.text = textToVerify;
|
|
2392
2401
|
while (true) {
|
|
2393
2402
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, textAnchor, state);
|
|
@@ -2416,18 +2425,20 @@ class StableBrowser {
|
|
|
2416
2425
|
const result = await this._locateElementByText(continer, textToVerify, "*", false, true, true, {});
|
|
2417
2426
|
if (result.elementCount > 0) {
|
|
2418
2427
|
const dataAttribute = "[data-blinq-id-" + result.randomToken + "]";
|
|
2428
|
+
await this._highlightElements(frame, dataAttribute);
|
|
2419
2429
|
//const cssAnchor = `[data-blinq-id="blinq-id-${token}-anchor"]`;
|
|
2420
|
-
if (world && world.screenshot && !world.screenshotPath) {
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2430
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
2431
|
+
// console.log(`Highlighting for vtrt while running from recorder`);
|
|
2432
|
+
// this._highlightElements(frame, dataAttribute)
|
|
2433
|
+
// .then(async () => {
|
|
2434
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
2435
|
+
// this._unhighlightElements(frame, dataAttribute).then(
|
|
2436
|
+
// () => {}
|
|
2437
|
+
// console.log(`Unhighlighting vrtr in recorder is successful`)
|
|
2438
|
+
// );
|
|
2439
|
+
// })
|
|
2440
|
+
// .catch(e);
|
|
2441
|
+
// }
|
|
2431
2442
|
//await this._highlightElements(frame, cssAnchor);
|
|
2432
2443
|
const element = await frame.locator(dataAttribute).first();
|
|
2433
2444
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -2435,11 +2446,8 @@ class StableBrowser {
|
|
|
2435
2446
|
if (element) {
|
|
2436
2447
|
await this.scrollIfNeeded(element, state.info);
|
|
2437
2448
|
await element.dispatchEvent("bvt_verify_page_contains_text");
|
|
2438
|
-
await _screenshot(state, this, element);
|
|
2439
|
-
}
|
|
2440
|
-
else {
|
|
2441
|
-
await _screenshot(state, this);
|
|
2442
2449
|
}
|
|
2450
|
+
await _screenshot(state, this);
|
|
2443
2451
|
return state.info;
|
|
2444
2452
|
}
|
|
2445
2453
|
}
|
|
@@ -2562,14 +2570,14 @@ class StableBrowser {
|
|
|
2562
2570
|
info.selectors = selectors;
|
|
2563
2571
|
try {
|
|
2564
2572
|
let table = await this._locate(selectors, info, _params);
|
|
2565
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
2573
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
2566
2574
|
const tableData = await getTableData(this.page, table);
|
|
2567
2575
|
return tableData;
|
|
2568
2576
|
}
|
|
2569
2577
|
catch (e) {
|
|
2570
2578
|
this.logger.error("getTableData failed " + info.log);
|
|
2571
2579
|
this.logger.error(e);
|
|
2572
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
2580
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
2573
2581
|
info.screenshotPath = screenshotPath;
|
|
2574
2582
|
Object.assign(e, { info: info });
|
|
2575
2583
|
error = e;
|
|
@@ -2850,7 +2858,7 @@ class StableBrowser {
|
|
|
2850
2858
|
throwError: false,
|
|
2851
2859
|
};
|
|
2852
2860
|
try {
|
|
2853
|
-
await _preCommand(state, this
|
|
2861
|
+
await _preCommand(state, this);
|
|
2854
2862
|
await this.page.close();
|
|
2855
2863
|
}
|
|
2856
2864
|
catch (e) {
|