testaro 5.12.1 → 5.12.2
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/package.json +1 -1
- package/run.js +49 -58
- package/tests/textNodes.js +14 -7
package/package.json
CHANGED
package/run.js
CHANGED
|
@@ -687,7 +687,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
687
687
|
}
|
|
688
688
|
catch(error) {
|
|
689
689
|
actIndex = -2;
|
|
690
|
-
waitError(page, act, error, 'URL');
|
|
690
|
+
waitError(page, act, error, 'text in the URL');
|
|
691
691
|
}
|
|
692
692
|
}
|
|
693
693
|
// Otherwise, if the text is to be a substring of the page title:
|
|
@@ -709,7 +709,7 @@ const doActs = async (report, actIndex, page) => {
|
|
|
709
709
|
}
|
|
710
710
|
catch(error) {
|
|
711
711
|
actIndex = -2;
|
|
712
|
-
waitError(page, act, error, 'title');
|
|
712
|
+
waitError(page, act, error, 'text in the title');
|
|
713
713
|
}
|
|
714
714
|
}
|
|
715
715
|
// Otherwise, if the text is to be a substring of the text of the page body:
|
|
@@ -723,14 +723,14 @@ const doActs = async (report, actIndex, page) => {
|
|
|
723
723
|
which,
|
|
724
724
|
{
|
|
725
725
|
polling: 2000,
|
|
726
|
-
timeout:
|
|
726
|
+
timeout: 15000
|
|
727
727
|
}
|
|
728
728
|
);
|
|
729
729
|
result.found = true;
|
|
730
730
|
}
|
|
731
731
|
catch(error) {
|
|
732
732
|
actIndex = -2;
|
|
733
|
-
waitError(page, act, error, 'body');
|
|
733
|
+
waitError(page, act, error, 'text in the body');
|
|
734
734
|
}
|
|
735
735
|
}
|
|
736
736
|
}
|
|
@@ -950,80 +950,71 @@ const doActs = async (report, actIndex, page) => {
|
|
|
950
950
|
act.result = {found: false};
|
|
951
951
|
let selection = {};
|
|
952
952
|
let tries = 0;
|
|
953
|
-
const slimText = debloat(act.which);
|
|
953
|
+
const slimText = act.which ? debloat(act.which) : '';
|
|
954
954
|
while (tries++ < 5 && ! act.result.found) {
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
break;
|
|
979
|
-
}
|
|
955
|
+
// If the page still exists:
|
|
956
|
+
if (page) {
|
|
957
|
+
// Identify the elements of the specified type.
|
|
958
|
+
const selections = await page.$$(selector);
|
|
959
|
+
// If there are any:
|
|
960
|
+
if (selections.length) {
|
|
961
|
+
// If there are enough to make a match possible:
|
|
962
|
+
if ((act.index || 0) < selections.length) {
|
|
963
|
+
// For each element of the specified type:
|
|
964
|
+
let matchCount = 0;
|
|
965
|
+
const selectionTexts = [];
|
|
966
|
+
for (selection of selections) {
|
|
967
|
+
// Add its text or an empty string to the list of texts of such elements.
|
|
968
|
+
const selectionText = slimText ? await textOf(page, selection) : '';
|
|
969
|
+
selectionTexts.push(selectionText);
|
|
970
|
+
// If its text includes any specified text:
|
|
971
|
+
if (selectionText.includes(slimText)) {
|
|
972
|
+
// If the element has the specified index among such elements:
|
|
973
|
+
if (matchCount++ === (act.index || 0)) {
|
|
974
|
+
// Report it as the matching element and stop checking.
|
|
975
|
+
act.result.found = true;
|
|
976
|
+
act.result.text = slimText;
|
|
977
|
+
break;
|
|
980
978
|
}
|
|
981
979
|
}
|
|
982
|
-
// If no element satisfied the specifications:
|
|
983
|
-
if (! act.result.found) {
|
|
984
|
-
// Add the failure data to the report.
|
|
985
|
-
act.result.success = false;
|
|
986
|
-
act.result.error = 'exhausted';
|
|
987
|
-
act.result.typeElementCount = selections.length;
|
|
988
|
-
if (slimText) {
|
|
989
|
-
act.result.textElementCount = --matchCount;
|
|
990
|
-
}
|
|
991
|
-
act.result.message = 'Not enough specified elements exist';
|
|
992
|
-
act.result.candidateTexts = selectionTexts;
|
|
993
|
-
}
|
|
994
980
|
}
|
|
995
|
-
//
|
|
996
|
-
|
|
981
|
+
// If no element satisfied the specifications:
|
|
982
|
+
if (! act.result.found) {
|
|
997
983
|
// Add the failure data to the report.
|
|
998
984
|
act.result.success = false;
|
|
999
|
-
act.result.error = '
|
|
985
|
+
act.result.error = 'exhausted';
|
|
1000
986
|
act.result.typeElementCount = selections.length;
|
|
1001
|
-
|
|
987
|
+
if (slimText) {
|
|
988
|
+
act.result.textElementCount = --matchCount;
|
|
989
|
+
}
|
|
990
|
+
act.result.message = 'Not enough specified elements exist';
|
|
991
|
+
act.result.candidateTexts = selectionTexts;
|
|
1002
992
|
}
|
|
1003
993
|
}
|
|
1004
|
-
// Otherwise, i.e. if there are
|
|
994
|
+
// Otherwise, i.e. if there are too few such elements to make a match possible:
|
|
1005
995
|
else {
|
|
1006
996
|
// Add the failure data to the report.
|
|
1007
997
|
act.result.success = false;
|
|
1008
|
-
act.result.error = '
|
|
1009
|
-
act.result.typeElementCount =
|
|
1010
|
-
act.result.message = '
|
|
998
|
+
act.result.error = 'fewer';
|
|
999
|
+
act.result.typeElementCount = selections.length;
|
|
1000
|
+
act.result.message = 'Elements of specified type too few';
|
|
1011
1001
|
}
|
|
1012
1002
|
}
|
|
1013
|
-
// Otherwise, i.e. if
|
|
1003
|
+
// Otherwise, i.e. if there are no elements of the specified type:
|
|
1014
1004
|
else {
|
|
1015
1005
|
// Add the failure data to the report.
|
|
1016
1006
|
act.result.success = false;
|
|
1017
|
-
act.result.error = '
|
|
1018
|
-
act.result.
|
|
1007
|
+
act.result.error = 'none';
|
|
1008
|
+
act.result.typeElementCount = 0;
|
|
1009
|
+
act.result.message = 'No elements of specified type found';
|
|
1019
1010
|
}
|
|
1020
1011
|
}
|
|
1021
|
-
// Otherwise, i.e. if no
|
|
1012
|
+
// Otherwise, i.e. if the page no longer exists:
|
|
1022
1013
|
else {
|
|
1023
1014
|
// Add the failure data to the report.
|
|
1024
1015
|
act.result.success = false;
|
|
1025
|
-
act.result.error = '
|
|
1026
|
-
act.result.message = '
|
|
1016
|
+
act.result.error = 'gone';
|
|
1017
|
+
act.result.message = 'Page gone';
|
|
1027
1018
|
}
|
|
1028
1019
|
if (! act.result.found) {
|
|
1029
1020
|
await wait(2000);
|
|
@@ -1036,11 +1027,11 @@ const doActs = async (report, actIndex, page) => {
|
|
|
1036
1027
|
const doAndWait = async actionIsClick => {
|
|
1037
1028
|
try {
|
|
1038
1029
|
const [newPage] = await Promise.all([
|
|
1039
|
-
page.context().waitForEvent('page', {timeout:
|
|
1030
|
+
page.context().waitForEvent('page', {timeout: 15000}),
|
|
1040
1031
|
actionIsClick ? selection.click({timeout: 4000}) : selection.press('Enter')
|
|
1041
1032
|
]);
|
|
1042
1033
|
// Wait for the new page to load.
|
|
1043
|
-
await newPage.waitForLoadState('domcontentloaded', {timeout:
|
|
1034
|
+
await newPage.waitForLoadState('domcontentloaded', {timeout: 15000});
|
|
1044
1035
|
// Make the new page the current page.
|
|
1045
1036
|
page = newPage;
|
|
1046
1037
|
act.result.success = true;
|
package/tests/textNodes.js
CHANGED
|
@@ -15,6 +15,15 @@ exports.reporter = async (page, detailLevel, text) => {
|
|
|
15
15
|
const matchNodes = [];
|
|
16
16
|
// Normalize the body.
|
|
17
17
|
document.body.normalize();
|
|
18
|
+
// Make a copy of the body.
|
|
19
|
+
const tempBody = document.body.cloneNode(true);
|
|
20
|
+
// Insert it into the document.
|
|
21
|
+
document.body.appendChild(tempBody);
|
|
22
|
+
// Remove the irrelevant text content from the copy.
|
|
23
|
+
const extraElements = Array.from(tempBody.querySelectorAll('style, script, svg'));
|
|
24
|
+
extraElements.forEach(element => {
|
|
25
|
+
element.textContent = '';
|
|
26
|
+
});
|
|
18
27
|
// FUNCTION DEFINITIONS START
|
|
19
28
|
// Compacts a string.
|
|
20
29
|
const compact = string => string.replace(/\s+/g, ' ').trim();
|
|
@@ -26,9 +35,9 @@ exports.reporter = async (page, detailLevel, text) => {
|
|
|
26
35
|
const data = {
|
|
27
36
|
tagName: element.tagName
|
|
28
37
|
};
|
|
29
|
-
if (! ['SCRIPT', 'SVG', 'svg'].includes(element.tagName)) {
|
|
38
|
+
if (! ['STYLE', 'SCRIPT', 'SVG', 'svg'].includes(element.tagName)) {
|
|
30
39
|
if (withText) {
|
|
31
|
-
data.text = element.textContent;
|
|
40
|
+
data.text = compact(element.textContent);
|
|
32
41
|
}
|
|
33
42
|
// Add data on its attributes, if any, to the data.
|
|
34
43
|
const {attributes} = element;
|
|
@@ -73,16 +82,13 @@ exports.reporter = async (page, detailLevel, text) => {
|
|
|
73
82
|
// FUNCTION DEFINITIONS END
|
|
74
83
|
const normText = normalize(text);
|
|
75
84
|
// Create a collection of the text nodes.
|
|
76
|
-
const walker = document.createTreeWalker(
|
|
85
|
+
const walker = document.createTreeWalker(tempBody, NodeFilter.SHOW_TEXT);
|
|
77
86
|
// Get their count.
|
|
78
87
|
const data = {nodeCount: 0};
|
|
79
88
|
let more = true;
|
|
80
89
|
while(more) {
|
|
81
90
|
if (walker.nextNode()) {
|
|
82
|
-
if (
|
|
83
|
-
normalize(walker.currentNode.nodeValue).includes(normText)
|
|
84
|
-
&& walker.currentNode.parentElement.tagName !== 'SCRIPT'
|
|
85
|
-
) {
|
|
91
|
+
if (normalize(walker.currentNode.nodeValue).includes(normText)) {
|
|
86
92
|
data.nodeCount++;
|
|
87
93
|
matchNodes.push(walker.currentNode);
|
|
88
94
|
}
|
|
@@ -120,6 +126,7 @@ exports.reporter = async (page, detailLevel, text) => {
|
|
|
120
126
|
data.items.push(itemData);
|
|
121
127
|
});
|
|
122
128
|
}
|
|
129
|
+
document.body.removeChild(tempBody);
|
|
123
130
|
return data;
|
|
124
131
|
}, [detailLevel, text]);
|
|
125
132
|
}
|