automation_model 1.0.596-dev → 1.0.598-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 +28 -26
- package/lib/command_common.js.map +1 -1
- package/lib/stable_browser.d.ts +4 -5
- package/lib/stable_browser.js +181 -182
- 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
|
}
|
|
@@ -396,10 +400,11 @@ class StableBrowser {
|
|
|
396
400
|
//info.log += "searching for locator " + JSON.stringify(locatorSearch) + "\n";
|
|
397
401
|
let locator = null;
|
|
398
402
|
if (locatorSearch.climb && locatorSearch.climb >= 0) {
|
|
399
|
-
|
|
403
|
+
const replacedText = await this._replaceWithLocalData(locatorSearch.text, this.world);
|
|
404
|
+
let locatorString = await this._locateElmentByTextClimbCss(scope, replacedText, locatorSearch.climb, locatorSearch.css, _params);
|
|
400
405
|
if (!locatorString) {
|
|
401
406
|
info.failCause.textNotFound = true;
|
|
402
|
-
info.failCause.lastError =
|
|
407
|
+
info.failCause.lastError = `failed to locate ${formatElementName(element_name)} by text: ${locatorSearch.text}`;
|
|
403
408
|
return;
|
|
404
409
|
}
|
|
405
410
|
locator = await this._getLocator({ css: locatorString }, scope, _params);
|
|
@@ -409,7 +414,7 @@ class StableBrowser {
|
|
|
409
414
|
let result = await this._locateElementByText(scope, text, locatorSearch.tag, false, locatorSearch.partial === true, true, _params);
|
|
410
415
|
if (result.elementCount === 0) {
|
|
411
416
|
info.failCause.textNotFound = true;
|
|
412
|
-
info.failCause.lastError =
|
|
417
|
+
info.failCause.lastError = `failed to locate ${formatElementName(element_name)} by text: ${text}`;
|
|
413
418
|
return;
|
|
414
419
|
}
|
|
415
420
|
locatorSearch.css = "[data-blinq-id-" + result.randomToken + "]";
|
|
@@ -461,11 +466,11 @@ class StableBrowser {
|
|
|
461
466
|
info.printMessages = {};
|
|
462
467
|
}
|
|
463
468
|
if (info.locatorLog && !visible) {
|
|
464
|
-
info.failCause.lastError =
|
|
469
|
+
info.failCause.lastError = `${formatElementName(element_name)} is not visible, searching for ${originalLocatorSearch}`;
|
|
465
470
|
info.locatorLog.setLocatorSearchStatus(originalLocatorSearch, "FOUND_NOT_VISIBLE");
|
|
466
471
|
}
|
|
467
472
|
if (info.locatorLog && !enabled) {
|
|
468
|
-
info.failCause.lastError =
|
|
473
|
+
info.failCause.lastError = `${formatElementName(element_name)} is disabled, searching for ${originalLocatorSearch}`;
|
|
469
474
|
info.locatorLog.setLocatorSearchStatus(originalLocatorSearch, "FOUND_NOT_ENABLED");
|
|
470
475
|
}
|
|
471
476
|
if (!info.printMessages[j.toString()]) {
|
|
@@ -618,7 +623,7 @@ class StableBrowser {
|
|
|
618
623
|
//info.log += "unable to locate iframe " + selectors.iframe_src + "\n";
|
|
619
624
|
if (Date.now() - startTime > timeout) {
|
|
620
625
|
info.failCause.iframeNotFound = true;
|
|
621
|
-
info.failCause.lastError =
|
|
626
|
+
info.failCause.lastError = `unable to locate iframe "${selectors.iframe_src}"`;
|
|
622
627
|
throw new Error("unable to locate iframe " + selectors.iframe_src);
|
|
623
628
|
}
|
|
624
629
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
@@ -692,17 +697,17 @@ class StableBrowser {
|
|
|
692
697
|
}
|
|
693
698
|
// info.log += "scanning locators in priority 1" + "\n";
|
|
694
699
|
let onlyPriority3 = selectorsLocators[0].priority === 3;
|
|
695
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["1"], scope, _params, info, visibleOnly, allowDisabled);
|
|
700
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["1"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
696
701
|
if (result.foundElements.length === 0) {
|
|
697
702
|
// info.log += "scanning locators in priority 2" + "\n";
|
|
698
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["2"], scope, _params, info, visibleOnly, allowDisabled);
|
|
703
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["2"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
699
704
|
}
|
|
700
705
|
if (result.foundElements.length === 0 && onlyPriority3) {
|
|
701
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled);
|
|
706
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
702
707
|
}
|
|
703
708
|
else {
|
|
704
709
|
if (result.foundElements.length === 0 && !highPriorityOnly) {
|
|
705
|
-
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled);
|
|
710
|
+
result = await this._scanLocatorsGroup(locatorsByPriority["3"], scope, _params, info, visibleOnly, allowDisabled, selectors?.element_name);
|
|
706
711
|
}
|
|
707
712
|
}
|
|
708
713
|
let foundElements = result.foundElements;
|
|
@@ -770,11 +775,11 @@ class StableBrowser {
|
|
|
770
775
|
//info.log += "failed to locate unique element, total elements found " + locatorsCount + "\n";
|
|
771
776
|
info.failCause.locatorNotFound = true;
|
|
772
777
|
if (!info?.failCause?.lastError) {
|
|
773
|
-
info.failCause.lastError =
|
|
778
|
+
info.failCause.lastError = `failed to locate ${formatElementName(selectors.element_name)}, ${locatorsCount > 0 ? `${locatorsCount} matching elements found` : "no matching elements found"}`;
|
|
774
779
|
}
|
|
775
780
|
throw new Error("failed to locate first element no elements found, " + info.log);
|
|
776
781
|
}
|
|
777
|
-
async _scanLocatorsGroup(locatorsGroup, scope, _params, info, visibleOnly, allowDisabled = false) {
|
|
782
|
+
async _scanLocatorsGroup(locatorsGroup, scope, _params, info, visibleOnly, allowDisabled = false, element_name) {
|
|
778
783
|
let foundElements = [];
|
|
779
784
|
const result = {
|
|
780
785
|
foundElements: foundElements,
|
|
@@ -782,7 +787,7 @@ class StableBrowser {
|
|
|
782
787
|
for (let i = 0; i < locatorsGroup.length; i++) {
|
|
783
788
|
let foundLocators = [];
|
|
784
789
|
try {
|
|
785
|
-
await this._collectLocatorInformation(locatorsGroup, i, scope, foundLocators, _params, info, visibleOnly, allowDisabled);
|
|
790
|
+
await this._collectLocatorInformation(locatorsGroup, i, scope, foundLocators, _params, info, visibleOnly, allowDisabled, element_name);
|
|
786
791
|
}
|
|
787
792
|
catch (e) {
|
|
788
793
|
// this call can fail it the browser is navigating
|
|
@@ -790,7 +795,7 @@ class StableBrowser {
|
|
|
790
795
|
// this.logger.debug(e);
|
|
791
796
|
foundLocators = [];
|
|
792
797
|
try {
|
|
793
|
-
await this._collectLocatorInformation(locatorsGroup, i, this.page, foundLocators, _params, info, visibleOnly, allowDisabled);
|
|
798
|
+
await this._collectLocatorInformation(locatorsGroup, i, this.page, foundLocators, _params, info, visibleOnly, allowDisabled, element_name);
|
|
794
799
|
}
|
|
795
800
|
catch (e) {
|
|
796
801
|
this.logger.info("unable to use locator (second try) " + JSON.stringify(locatorsGroup[i]));
|
|
@@ -826,7 +831,7 @@ class StableBrowser {
|
|
|
826
831
|
operation: "simpleClick",
|
|
827
832
|
log: "***** click on " + elementDescription + " *****\n",
|
|
828
833
|
};
|
|
829
|
-
_preCommand(state, this
|
|
834
|
+
_preCommand(state, this);
|
|
830
835
|
const startTime = Date.now();
|
|
831
836
|
let timeout = 30000;
|
|
832
837
|
if (options && options.timeout) {
|
|
@@ -875,7 +880,7 @@ class StableBrowser {
|
|
|
875
880
|
operation: "simpleClickType",
|
|
876
881
|
log: "***** click type on " + elementDescription + " *****\n",
|
|
877
882
|
};
|
|
878
|
-
_preCommand(state, this
|
|
883
|
+
_preCommand(state, this);
|
|
879
884
|
const startTime = Date.now();
|
|
880
885
|
let timeout = 30000;
|
|
881
886
|
if (options && options.timeout) {
|
|
@@ -923,7 +928,7 @@ class StableBrowser {
|
|
|
923
928
|
log: "***** click on " + selectors.element_name + " *****\n",
|
|
924
929
|
};
|
|
925
930
|
try {
|
|
926
|
-
await _preCommand(state, this
|
|
931
|
+
await _preCommand(state, this);
|
|
927
932
|
// if (state.options && state.options.context) {
|
|
928
933
|
// state.selectors.locators[0].text = state.options.context;
|
|
929
934
|
// }
|
|
@@ -959,18 +964,18 @@ class StableBrowser {
|
|
|
959
964
|
log: "***** check " + selectors.element_name + " *****\n",
|
|
960
965
|
};
|
|
961
966
|
try {
|
|
962
|
-
await _preCommand(state, this
|
|
967
|
+
await _preCommand(state, this);
|
|
963
968
|
state.info.checked = checked;
|
|
964
969
|
// let element = await this._locate(selectors, info, _params);
|
|
965
970
|
// ({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
966
971
|
try {
|
|
967
|
-
if (world && world.screenshot && !world.screenshotPath) {
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
971
|
-
await this._unHighlightElements(element);
|
|
972
|
-
}
|
|
972
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
973
|
+
// console.log(`Highlighting while running from recorder`);
|
|
974
|
+
await this._highlightElements(element);
|
|
973
975
|
await state.element.setChecked(checked);
|
|
976
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
977
|
+
// await this._unHighlightElements(element);
|
|
978
|
+
// }
|
|
974
979
|
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
975
980
|
// await this._unHighlightElements(element);
|
|
976
981
|
}
|
|
@@ -1008,10 +1013,10 @@ class StableBrowser {
|
|
|
1008
1013
|
log: "***** hover " + selectors.element_name + " *****\n",
|
|
1009
1014
|
};
|
|
1010
1015
|
try {
|
|
1011
|
-
await _preCommand(state, this
|
|
1016
|
+
await _preCommand(state, this);
|
|
1012
1017
|
try {
|
|
1013
1018
|
await state.element.hover();
|
|
1014
|
-
await _screenshot(state, this);
|
|
1019
|
+
// await _screenshot(state, this);
|
|
1015
1020
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1016
1021
|
}
|
|
1017
1022
|
catch (e) {
|
|
@@ -1019,10 +1024,10 @@ class StableBrowser {
|
|
|
1019
1024
|
state.info.log += "hover failed, will try again" + "\n";
|
|
1020
1025
|
state.element = await this._locate(selectors, state.info, _params);
|
|
1021
1026
|
await state.element.hover({ timeout: 10000 });
|
|
1022
|
-
await _screenshot(state, this);
|
|
1027
|
+
// await _screenshot(state, this);
|
|
1023
1028
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1024
1029
|
}
|
|
1025
|
-
|
|
1030
|
+
await _screenshot(state, this);
|
|
1026
1031
|
await this.waitForPageLoad();
|
|
1027
1032
|
return state.info;
|
|
1028
1033
|
}
|
|
@@ -1049,7 +1054,7 @@ class StableBrowser {
|
|
|
1049
1054
|
log: "***** select option " + selectors.element_name + " *****\n",
|
|
1050
1055
|
};
|
|
1051
1056
|
try {
|
|
1052
|
-
await _preCommand(state, this
|
|
1057
|
+
await _preCommand(state, this);
|
|
1053
1058
|
try {
|
|
1054
1059
|
await state.element.selectOption(values);
|
|
1055
1060
|
}
|
|
@@ -1083,7 +1088,7 @@ class StableBrowser {
|
|
|
1083
1088
|
log: "",
|
|
1084
1089
|
};
|
|
1085
1090
|
try {
|
|
1086
|
-
await _preCommand(state, this
|
|
1091
|
+
await _preCommand(state, this);
|
|
1087
1092
|
const valueSegment = state.value.split("&&");
|
|
1088
1093
|
for (let i = 0; i < valueSegment.length; i++) {
|
|
1089
1094
|
if (i > 0) {
|
|
@@ -1126,7 +1131,7 @@ class StableBrowser {
|
|
|
1126
1131
|
log: "***** set input value " + selectors.element_name + " *****\n",
|
|
1127
1132
|
};
|
|
1128
1133
|
try {
|
|
1129
|
-
await _preCommand(state, this
|
|
1134
|
+
await _preCommand(state, this);
|
|
1130
1135
|
let value = await this._replaceWithLocalData(state.value, this);
|
|
1131
1136
|
try {
|
|
1132
1137
|
await state.element.evaluateHandle((el, value) => {
|
|
@@ -1163,7 +1168,7 @@ class StableBrowser {
|
|
|
1163
1168
|
throwError: false,
|
|
1164
1169
|
};
|
|
1165
1170
|
try {
|
|
1166
|
-
await _preCommand(state, this
|
|
1171
|
+
await _preCommand(state, this);
|
|
1167
1172
|
try {
|
|
1168
1173
|
await state.element.click();
|
|
1169
1174
|
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
@@ -1237,7 +1242,7 @@ class StableBrowser {
|
|
|
1237
1242
|
_value = newValue;
|
|
1238
1243
|
}
|
|
1239
1244
|
try {
|
|
1240
|
-
await _preCommand(state, this
|
|
1245
|
+
await _preCommand(state, this);
|
|
1241
1246
|
state.info.value = _value;
|
|
1242
1247
|
if (options === null || options === undefined || !options.press) {
|
|
1243
1248
|
try {
|
|
@@ -1330,7 +1335,7 @@ class StableBrowser {
|
|
|
1330
1335
|
log: "***** fill on " + selectors.element_name + " with value " + value + "*****\n",
|
|
1331
1336
|
};
|
|
1332
1337
|
try {
|
|
1333
|
-
await _preCommand(state, this
|
|
1338
|
+
await _preCommand(state, this);
|
|
1334
1339
|
await state.element.fill(value);
|
|
1335
1340
|
await state.element.dispatchEvent("change");
|
|
1336
1341
|
if (enter) {
|
|
@@ -1376,19 +1381,21 @@ class StableBrowser {
|
|
|
1376
1381
|
catch (e) {
|
|
1377
1382
|
//ignore
|
|
1378
1383
|
}
|
|
1379
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
1384
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
1380
1385
|
try {
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
}
|
|
1386
|
+
await this._highlightElements(element);
|
|
1387
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
1388
|
+
// // console.log(`Highlighting for get text while running from recorder`);
|
|
1389
|
+
// this._highlightElements(element)
|
|
1390
|
+
// .then(async () => {
|
|
1391
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1392
|
+
// this._unhighlightElements(element).then(
|
|
1393
|
+
// () => {}
|
|
1394
|
+
// // console.log(`Unhighlighting vrtr in recorder is successful`)
|
|
1395
|
+
// );
|
|
1396
|
+
// })
|
|
1397
|
+
// .catch(e);
|
|
1398
|
+
// }
|
|
1392
1399
|
const elementText = await element.innerText();
|
|
1393
1400
|
return {
|
|
1394
1401
|
text: elementText,
|
|
@@ -1435,13 +1442,13 @@ class StableBrowser {
|
|
|
1435
1442
|
}
|
|
1436
1443
|
let foundObj = null;
|
|
1437
1444
|
try {
|
|
1438
|
-
await _preCommand(state, this
|
|
1445
|
+
await _preCommand(state, this);
|
|
1439
1446
|
state.info.pattern = pattern;
|
|
1440
1447
|
foundObj = await this._getText(selectors, 0, _params, options, state.info, world);
|
|
1441
1448
|
if (foundObj && foundObj.element) {
|
|
1442
1449
|
await this.scrollIfNeeded(foundObj.element, state.info);
|
|
1443
1450
|
}
|
|
1444
|
-
await _screenshot(state, this
|
|
1451
|
+
await _screenshot(state, this);
|
|
1445
1452
|
let escapedText = text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
|
1446
1453
|
pattern = pattern.replace("{text}", escapedText);
|
|
1447
1454
|
let regex = new RegExp(pattern, "im");
|
|
@@ -1486,12 +1493,12 @@ class StableBrowser {
|
|
|
1486
1493
|
}
|
|
1487
1494
|
let foundObj = null;
|
|
1488
1495
|
try {
|
|
1489
|
-
await _preCommand(state, this
|
|
1496
|
+
await _preCommand(state, this);
|
|
1490
1497
|
foundObj = await this._getText(selectors, climb, _params, options, state.info, world);
|
|
1491
1498
|
if (foundObj && foundObj.element) {
|
|
1492
1499
|
await this.scrollIfNeeded(foundObj.element, state.info);
|
|
1493
1500
|
}
|
|
1494
|
-
await _screenshot(state, this
|
|
1501
|
+
await _screenshot(state, this);
|
|
1495
1502
|
const dateAlternatives = findDateAlternatives(text);
|
|
1496
1503
|
const numberAlternatives = findNumberAlternatives(text);
|
|
1497
1504
|
if (dateAlternatives.date) {
|
|
@@ -1680,7 +1687,7 @@ class StableBrowser {
|
|
|
1680
1687
|
}
|
|
1681
1688
|
return data;
|
|
1682
1689
|
}
|
|
1683
|
-
async _screenShot(options = {}, world = null, info = null
|
|
1690
|
+
async _screenShot(options = {}, world = null, info = null) {
|
|
1684
1691
|
// collect url/path/title
|
|
1685
1692
|
if (info) {
|
|
1686
1693
|
if (!info.title) {
|
|
@@ -1709,7 +1716,7 @@ class StableBrowser {
|
|
|
1709
1716
|
const uuidStr = "id_" + randomUUID();
|
|
1710
1717
|
const screenshotPath = path.join(world.screenshotPath, uuidStr + ".png");
|
|
1711
1718
|
try {
|
|
1712
|
-
await this.takeScreenshot(screenshotPath
|
|
1719
|
+
await this.takeScreenshot(screenshotPath);
|
|
1713
1720
|
// let buffer = await this.page.screenshot({ timeout: 4000 });
|
|
1714
1721
|
// // save the buffer to the screenshot path asynchrously
|
|
1715
1722
|
// fs.writeFile(screenshotPath, buffer, (err) => {
|
|
@@ -1720,7 +1727,7 @@ class StableBrowser {
|
|
|
1720
1727
|
result.screenshotId = uuidStr;
|
|
1721
1728
|
result.screenshotPath = screenshotPath;
|
|
1722
1729
|
if (info && info.box) {
|
|
1723
|
-
|
|
1730
|
+
await drawRectangle(screenshotPath, info.box.x, info.box.y, info.box.width, info.box.height);
|
|
1724
1731
|
}
|
|
1725
1732
|
}
|
|
1726
1733
|
catch (e) {
|
|
@@ -1730,7 +1737,7 @@ class StableBrowser {
|
|
|
1730
1737
|
else if (options && options.screenshot) {
|
|
1731
1738
|
result.screenshotPath = options.screenshotPath;
|
|
1732
1739
|
try {
|
|
1733
|
-
await this.takeScreenshot(options.screenshotPath
|
|
1740
|
+
await this.takeScreenshot(options.screenshotPath);
|
|
1734
1741
|
// let buffer = await this.page.screenshot({ timeout: 4000 });
|
|
1735
1742
|
// // save the buffer to the screenshot path asynchrously
|
|
1736
1743
|
// fs.writeFile(options.screenshotPath, buffer, (err) => {
|
|
@@ -1743,12 +1750,12 @@ class StableBrowser {
|
|
|
1743
1750
|
this.logger.info("unable to take screenshot, ignored");
|
|
1744
1751
|
}
|
|
1745
1752
|
if (info && info.box) {
|
|
1746
|
-
|
|
1753
|
+
await drawRectangle(options.screenshotPath, info.box.x, info.box.y, info.box.width, info.box.height);
|
|
1747
1754
|
}
|
|
1748
1755
|
}
|
|
1749
1756
|
return result;
|
|
1750
1757
|
}
|
|
1751
|
-
async takeScreenshot(screenshotPath
|
|
1758
|
+
async takeScreenshot(screenshotPath) {
|
|
1752
1759
|
const playContext = this.context.playContext;
|
|
1753
1760
|
// Using CDP to capture the screenshot
|
|
1754
1761
|
const viewportWidth = Math.max(...(await this.page.evaluate(() => [
|
|
@@ -1766,9 +1773,9 @@ class StableBrowser {
|
|
|
1766
1773
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1767
1774
|
// console.log(`Unhighlighted previous element`);
|
|
1768
1775
|
// }
|
|
1769
|
-
if (focusedElement) {
|
|
1770
|
-
|
|
1771
|
-
}
|
|
1776
|
+
// if (focusedElement) {
|
|
1777
|
+
// await this._highlightElements(focusedElement);
|
|
1778
|
+
// }
|
|
1772
1779
|
if (this.context.browserName === "chromium") {
|
|
1773
1780
|
const client = await playContext.newCDPSession(this.page);
|
|
1774
1781
|
const { data } = await client.send("Page.captureScreenshot", {
|
|
@@ -1790,10 +1797,10 @@ class StableBrowser {
|
|
|
1790
1797
|
else {
|
|
1791
1798
|
screenshotBuffer = await this.page.screenshot();
|
|
1792
1799
|
}
|
|
1793
|
-
if (focusedElement) {
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
}
|
|
1800
|
+
// if (focusedElement) {
|
|
1801
|
+
// // console.log(`Focused element ${JSON.stringify(focusedElement._selector)}`)
|
|
1802
|
+
// await this._unhighlightElements(focusedElement);
|
|
1803
|
+
// }
|
|
1797
1804
|
let image = await Jimp.read(screenshotBuffer);
|
|
1798
1805
|
// Get the image dimensions
|
|
1799
1806
|
const { width, height } = image.bitmap;
|
|
@@ -1820,7 +1827,7 @@ class StableBrowser {
|
|
|
1820
1827
|
};
|
|
1821
1828
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1822
1829
|
try {
|
|
1823
|
-
await _preCommand(state, this
|
|
1830
|
+
await _preCommand(state, this);
|
|
1824
1831
|
await expect(state.element).toHaveCount(1, { timeout: 10000 });
|
|
1825
1832
|
return state.info;
|
|
1826
1833
|
}
|
|
@@ -1843,10 +1850,11 @@ class StableBrowser {
|
|
|
1843
1850
|
text: `Extract attribute from element`,
|
|
1844
1851
|
operation: "extractAttribute",
|
|
1845
1852
|
log: "***** extract attribute " + attribute + " from " + selectors.element_name + " *****\n",
|
|
1853
|
+
allowDisabled: true,
|
|
1846
1854
|
};
|
|
1847
1855
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1848
1856
|
try {
|
|
1849
|
-
await _preCommand(state, this
|
|
1857
|
+
await _preCommand(state, this);
|
|
1850
1858
|
switch (attribute) {
|
|
1851
1859
|
case "inner_text":
|
|
1852
1860
|
state.value = await state.element.innerText();
|
|
@@ -1864,7 +1872,7 @@ class StableBrowser {
|
|
|
1864
1872
|
state.info.value = state.value;
|
|
1865
1873
|
this.setTestData({ [variable]: state.value }, world);
|
|
1866
1874
|
this.logger.info("set test data: " + variable + "=" + state.value);
|
|
1867
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1875
|
+
// await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1868
1876
|
return state.info;
|
|
1869
1877
|
}
|
|
1870
1878
|
catch (e) {
|
|
@@ -1893,7 +1901,7 @@ class StableBrowser {
|
|
|
1893
1901
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
1894
1902
|
let val;
|
|
1895
1903
|
try {
|
|
1896
|
-
await _preCommand(state, this
|
|
1904
|
+
await _preCommand(state, this);
|
|
1897
1905
|
switch (attribute) {
|
|
1898
1906
|
case "innerText":
|
|
1899
1907
|
val = String(await state.element.innerText());
|
|
@@ -2035,21 +2043,20 @@ class StableBrowser {
|
|
|
2035
2043
|
if (node && node.style) {
|
|
2036
2044
|
let originalOutline = node.style.outline;
|
|
2037
2045
|
// console.log(`Original outline was: ${originalOutline}`);
|
|
2038
|
-
node.__previousOutline = originalOutline;
|
|
2046
|
+
// node.__previousOutline = originalOutline;
|
|
2039
2047
|
node.style.outline = "2px solid red";
|
|
2040
2048
|
// console.log(`New outline is: ${node.style.outline}`);
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
+
if (window) {
|
|
2050
|
+
window.addEventListener("beforeunload", function (e) {
|
|
2051
|
+
node.style.outline = originalBorder;
|
|
2052
|
+
});
|
|
2053
|
+
}
|
|
2054
|
+
setTimeout(function () {
|
|
2055
|
+
node.style.outline = originalOutline;
|
|
2056
|
+
}, 2000);
|
|
2049
2057
|
}
|
|
2050
2058
|
})
|
|
2051
|
-
.then(() => {
|
|
2052
|
-
})
|
|
2059
|
+
.then(() => { })
|
|
2053
2060
|
.catch((e) => {
|
|
2054
2061
|
// ignore
|
|
2055
2062
|
// console.error(`Could not highlight node : ${e}`);
|
|
@@ -2072,20 +2079,19 @@ class StableBrowser {
|
|
|
2072
2079
|
element.__previousOutline = originalOutline;
|
|
2073
2080
|
// Set the new border to be red and 2px solid
|
|
2074
2081
|
element.style.outline = "2px solid red";
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2082
|
+
if (window) {
|
|
2083
|
+
window.addEventListener("beforeunload", function (e) {
|
|
2084
|
+
element.style.outline = originalBorder;
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2080
2087
|
// Set a timeout to revert to the original border after 2 seconds
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2088
|
+
setTimeout(function () {
|
|
2089
|
+
element.style.outline = originalBorder;
|
|
2090
|
+
}, 2000);
|
|
2084
2091
|
}
|
|
2085
2092
|
return;
|
|
2086
2093
|
}, [css])
|
|
2087
|
-
.then(() => {
|
|
2088
|
-
})
|
|
2094
|
+
.then(() => { })
|
|
2089
2095
|
.catch((e) => {
|
|
2090
2096
|
// ignore
|
|
2091
2097
|
// console.error(`Could not highlight css: ${e}`);
|
|
@@ -2096,60 +2102,54 @@ class StableBrowser {
|
|
|
2096
2102
|
console.debug(error);
|
|
2097
2103
|
}
|
|
2098
2104
|
}
|
|
2099
|
-
async _unhighlightElements(scope, css) {
|
|
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
|
-
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
catch (error) {
|
|
2150
|
-
// console.debug(error);
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2105
|
+
// async _unhighlightElements(scope, css) {
|
|
2106
|
+
// try {
|
|
2107
|
+
// if (!scope) {
|
|
2108
|
+
// return;
|
|
2109
|
+
// }
|
|
2110
|
+
// if (!css) {
|
|
2111
|
+
// scope
|
|
2112
|
+
// .evaluate((node) => {
|
|
2113
|
+
// if (node && node.style) {
|
|
2114
|
+
// if (!node.__previousOutline) {
|
|
2115
|
+
// node.style.outline = "";
|
|
2116
|
+
// } else {
|
|
2117
|
+
// node.style.outline = node.__previousOutline;
|
|
2118
|
+
// }
|
|
2119
|
+
// }
|
|
2120
|
+
// })
|
|
2121
|
+
// .then(() => {})
|
|
2122
|
+
// .catch((e) => {
|
|
2123
|
+
// // console.log(`Error while unhighlighting node ${JSON.stringify(scope)}: ${e}`);
|
|
2124
|
+
// });
|
|
2125
|
+
// } else {
|
|
2126
|
+
// scope
|
|
2127
|
+
// .evaluate(([css]) => {
|
|
2128
|
+
// if (!css) {
|
|
2129
|
+
// return;
|
|
2130
|
+
// }
|
|
2131
|
+
// let elements = Array.from(document.querySelectorAll(css));
|
|
2132
|
+
// for (i = 0; i < elements.length; i++) {
|
|
2133
|
+
// let element = elements[i];
|
|
2134
|
+
// if (!element.style) {
|
|
2135
|
+
// return;
|
|
2136
|
+
// }
|
|
2137
|
+
// if (!element.__previousOutline) {
|
|
2138
|
+
// element.style.outline = "";
|
|
2139
|
+
// } else {
|
|
2140
|
+
// element.style.outline = element.__previousOutline;
|
|
2141
|
+
// }
|
|
2142
|
+
// }
|
|
2143
|
+
// })
|
|
2144
|
+
// .then(() => {})
|
|
2145
|
+
// .catch((e) => {
|
|
2146
|
+
// // console.error(`Error while unhighlighting element in css: ${e}`);
|
|
2147
|
+
// });
|
|
2148
|
+
// }
|
|
2149
|
+
// } catch (error) {
|
|
2150
|
+
// // console.debug(error);
|
|
2151
|
+
// }
|
|
2152
|
+
// }
|
|
2153
2153
|
async verifyPagePath(pathPart, options = {}, world = null) {
|
|
2154
2154
|
const startTime = Date.now();
|
|
2155
2155
|
let error = null;
|
|
@@ -2264,7 +2264,7 @@ class StableBrowser {
|
|
|
2264
2264
|
let dateAlternatives = findDateAlternatives(text);
|
|
2265
2265
|
let numberAlternatives = findNumberAlternatives(text);
|
|
2266
2266
|
try {
|
|
2267
|
-
await _preCommand(state, this
|
|
2267
|
+
await _preCommand(state, this);
|
|
2268
2268
|
state.info.text = text;
|
|
2269
2269
|
while (true) {
|
|
2270
2270
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, text, state);
|
|
@@ -2278,31 +2278,31 @@ class StableBrowser {
|
|
|
2278
2278
|
if (resultWithElementsFound[0].randomToken) {
|
|
2279
2279
|
const frame = resultWithElementsFound[0].frame;
|
|
2280
2280
|
const dataAttribute = `[data-blinq-id-${resultWithElementsFound[0].randomToken}]`;
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2281
|
+
await this._highlightElements(frame, dataAttribute);
|
|
2282
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
2283
|
+
// console.log(`Highlighting for verify text is found while running from recorder`);
|
|
2284
|
+
// this._highlightElements(frame, dataAttribute).then(async () => {
|
|
2285
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
2286
|
+
// this._unhighlightElements(frame, dataAttribute)
|
|
2287
|
+
// .then(async () => {
|
|
2288
|
+
// console.log(`Unhighlighted frame dataAttribute successfully`);
|
|
2289
|
+
// })
|
|
2290
|
+
// .catch(
|
|
2291
|
+
// (e) => {}
|
|
2292
|
+
// console.error(e)
|
|
2293
|
+
// );
|
|
2294
|
+
// });
|
|
2295
|
+
// }
|
|
2294
2296
|
const element = await frame.locator(dataAttribute).first();
|
|
2295
2297
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2296
2298
|
// await this._unhighlightElements(frame, dataAttribute);
|
|
2297
2299
|
if (element) {
|
|
2298
2300
|
await this.scrollIfNeeded(element, state.info);
|
|
2299
2301
|
await element.dispatchEvent("bvt_verify_page_contains_text");
|
|
2300
|
-
await _screenshot(state, this, element);
|
|
2302
|
+
// await _screenshot(state, this, element);
|
|
2301
2303
|
}
|
|
2302
2304
|
}
|
|
2303
|
-
|
|
2304
|
-
await _screenshot(state, this);
|
|
2305
|
-
}
|
|
2305
|
+
await _screenshot(state, this);
|
|
2306
2306
|
return state.info;
|
|
2307
2307
|
}
|
|
2308
2308
|
// await expect(element).toHaveCount(1, { timeout: 10000 });
|
|
@@ -2338,7 +2338,7 @@ class StableBrowser {
|
|
|
2338
2338
|
let dateAlternatives = findDateAlternatives(text);
|
|
2339
2339
|
let numberAlternatives = findNumberAlternatives(text);
|
|
2340
2340
|
try {
|
|
2341
|
-
await _preCommand(state, this
|
|
2341
|
+
await _preCommand(state, this);
|
|
2342
2342
|
state.info.text = text;
|
|
2343
2343
|
while (true) {
|
|
2344
2344
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, text, state);
|
|
@@ -2390,7 +2390,7 @@ class StableBrowser {
|
|
|
2390
2390
|
let numberAlternatives = findNumberAlternatives(textToVerify);
|
|
2391
2391
|
let foundAncore = false;
|
|
2392
2392
|
try {
|
|
2393
|
-
await _preCommand(state, this
|
|
2393
|
+
await _preCommand(state, this);
|
|
2394
2394
|
state.info.text = textToVerify;
|
|
2395
2395
|
while (true) {
|
|
2396
2396
|
const resultWithElementsFound = await this.findTextInAllFrames(dateAlternatives, numberAlternatives, textAnchor, state);
|
|
@@ -2419,18 +2419,20 @@ class StableBrowser {
|
|
|
2419
2419
|
const result = await this._locateElementByText(continer, textToVerify, "*", false, true, true, {});
|
|
2420
2420
|
if (result.elementCount > 0) {
|
|
2421
2421
|
const dataAttribute = "[data-blinq-id-" + result.randomToken + "]";
|
|
2422
|
+
await this._highlightElements(frame, dataAttribute);
|
|
2422
2423
|
//const cssAnchor = `[data-blinq-id="blinq-id-${token}-anchor"]`;
|
|
2423
|
-
if (world && world.screenshot && !world.screenshotPath) {
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2424
|
+
// if (world && world.screenshot && !world.screenshotPath) {
|
|
2425
|
+
// console.log(`Highlighting for vtrt while running from recorder`);
|
|
2426
|
+
// this._highlightElements(frame, dataAttribute)
|
|
2427
|
+
// .then(async () => {
|
|
2428
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
2429
|
+
// this._unhighlightElements(frame, dataAttribute).then(
|
|
2430
|
+
// () => {}
|
|
2431
|
+
// console.log(`Unhighlighting vrtr in recorder is successful`)
|
|
2432
|
+
// );
|
|
2433
|
+
// })
|
|
2434
|
+
// .catch(e);
|
|
2435
|
+
// }
|
|
2434
2436
|
//await this._highlightElements(frame, cssAnchor);
|
|
2435
2437
|
const element = await frame.locator(dataAttribute).first();
|
|
2436
2438
|
// await new Promise((resolve) => setTimeout(resolve, 100));
|
|
@@ -2438,11 +2440,8 @@ class StableBrowser {
|
|
|
2438
2440
|
if (element) {
|
|
2439
2441
|
await this.scrollIfNeeded(element, state.info);
|
|
2440
2442
|
await element.dispatchEvent("bvt_verify_page_contains_text");
|
|
2441
|
-
await _screenshot(state, this, element);
|
|
2442
|
-
}
|
|
2443
|
-
else {
|
|
2444
|
-
await _screenshot(state, this);
|
|
2445
2443
|
}
|
|
2444
|
+
await _screenshot(state, this);
|
|
2446
2445
|
return state.info;
|
|
2447
2446
|
}
|
|
2448
2447
|
}
|
|
@@ -2565,14 +2564,14 @@ class StableBrowser {
|
|
|
2565
2564
|
info.selectors = selectors;
|
|
2566
2565
|
try {
|
|
2567
2566
|
let table = await this._locate(selectors, info, _params);
|
|
2568
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
2567
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
2569
2568
|
const tableData = await getTableData(this.page, table);
|
|
2570
2569
|
return tableData;
|
|
2571
2570
|
}
|
|
2572
2571
|
catch (e) {
|
|
2573
2572
|
this.logger.error("getTableData failed " + info.log);
|
|
2574
2573
|
this.logger.error(e);
|
|
2575
|
-
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info
|
|
2574
|
+
({ screenshotId, screenshotPath } = await this._screenShot(options, world, info));
|
|
2576
2575
|
info.screenshotPath = screenshotPath;
|
|
2577
2576
|
Object.assign(e, { info: info });
|
|
2578
2577
|
error = e;
|
|
@@ -2853,7 +2852,7 @@ class StableBrowser {
|
|
|
2853
2852
|
throwError: false,
|
|
2854
2853
|
};
|
|
2855
2854
|
try {
|
|
2856
|
-
await _preCommand(state, this
|
|
2855
|
+
await _preCommand(state, this);
|
|
2857
2856
|
await this.page.close();
|
|
2858
2857
|
}
|
|
2859
2858
|
catch (e) {
|