testaro 5.9.2 → 5.9.3
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/commands.js +1 -1
- package/package.json +1 -1
- package/tests/elements.js +123 -103
package/commands.js
CHANGED
|
@@ -153,7 +153,7 @@ exports.commands = {
|
|
|
153
153
|
elements: [
|
|
154
154
|
'Perform an elements test',
|
|
155
155
|
{
|
|
156
|
-
detailLevel: [true, 'number', '', '0
|
|
156
|
+
detailLevel: [true, 'number', '', '0 to 3, to specify the level of detail'],
|
|
157
157
|
tagName: [false, 'string', '', 'tag name of elements'],
|
|
158
158
|
onlyVisible: [false, 'boolean', '', 'whether to exclude invisible elements'],
|
|
159
159
|
attribute: [false, 'string', 'hasLength', 'required attribute or attribute=value']
|
package/package.json
CHANGED
package/tests/elements.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
2
|
elements
|
|
3
3
|
This test reports data about specified elements.
|
|
4
|
+
Meanings of detailLevel values:
|
|
5
|
+
0. Only total element count; no detail.
|
|
6
|
+
1. Also data on each specified element.
|
|
7
|
+
2. Data on each specified element also include the text content of the parent element.
|
|
8
|
+
3. Data on each specified element also include data on its sibling nodes.
|
|
4
9
|
*/
|
|
5
10
|
exports.reporter = async (page, detailLevel, tagName, onlyVisible, attribute) => {
|
|
6
11
|
// Determine a selector of the specified elements.
|
|
@@ -11,120 +16,135 @@ exports.reporter = async (page, detailLevel, tagName, onlyVisible, attribute) =>
|
|
|
11
16
|
if (onlyVisible) {
|
|
12
17
|
selector += ':visible';
|
|
13
18
|
}
|
|
19
|
+
let data = {};
|
|
14
20
|
// Get the data on the elements.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (nodeType === 1) {
|
|
25
|
-
sibInfo.tagName = node.tagName;
|
|
26
|
-
}
|
|
27
|
-
else if (nodeType === 3) {
|
|
28
|
-
sibInfo.text = compact(text);
|
|
29
|
-
}
|
|
30
|
-
return sibInfo;
|
|
31
|
-
};
|
|
32
|
-
// FUNCTION DEFINITIONS END
|
|
33
|
-
// Initialize the data with the count of the specified elements.
|
|
34
|
-
const data = {
|
|
35
|
-
total: elements.length
|
|
36
|
-
};
|
|
37
|
-
// If no itemization is required:
|
|
38
|
-
if (detailLevel === 0) {
|
|
39
|
-
// Return the element count.
|
|
40
|
-
return data;
|
|
41
|
-
}
|
|
42
|
-
// Otherwise, i.e. if itemization is required:
|
|
43
|
-
else {
|
|
44
|
-
// Initialize the item data.
|
|
45
|
-
data.items = [];
|
|
46
|
-
// For each specified element:
|
|
47
|
-
elements.forEach(element => {
|
|
48
|
-
// Initialize data on it.
|
|
49
|
-
const parent = element.parentElement;
|
|
50
|
-
const datum = {
|
|
51
|
-
tagName: element.tagName,
|
|
52
|
-
parentTagName: parent ? parent.tagName : '',
|
|
53
|
-
code: compact(element.outerHTML),
|
|
54
|
-
attributes: [],
|
|
55
|
-
textContent: compact(element.textContent)
|
|
21
|
+
try {
|
|
22
|
+
data = await page.$$eval(selector, (elements, detailLevel) => {
|
|
23
|
+
// FUNCTION DEFINITIONS START
|
|
24
|
+
// Compacts a string.
|
|
25
|
+
const compact = string => string.replace(/\s+/g, ' ').trim();
|
|
26
|
+
// Gets data on the sibling nodes of an element.
|
|
27
|
+
const getSibInfo = (node, nodeType, text) => {
|
|
28
|
+
const sibInfo = {
|
|
29
|
+
type: nodeType
|
|
56
30
|
};
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// Add data on the attribute to the element data.
|
|
60
|
-
const {name, value} = attribute;
|
|
61
|
-
datum.attributes.push({
|
|
62
|
-
name,
|
|
63
|
-
value
|
|
64
|
-
});
|
|
65
|
-
// If the element has reference labels:
|
|
66
|
-
if (name === 'aria-labelledby') {
|
|
67
|
-
// Add their texts to the element data.
|
|
68
|
-
const labelerIDs = value.split(/\s+/);
|
|
69
|
-
const labelers = [];
|
|
70
|
-
labelerIDs.forEach(id => {
|
|
71
|
-
const labeler = document.getElementById(id);
|
|
72
|
-
if (labeler) {
|
|
73
|
-
labelers.push(compact(labeler.textContent));
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
if (labelers.length) {
|
|
77
|
-
datum.labelers = labelers;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
31
|
+
if (nodeType === 1) {
|
|
32
|
+
sibInfo.tagName = node.tagName;
|
|
80
33
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const compactContent = compact(textContent);
|
|
84
|
-
if (compactContent) {
|
|
85
|
-
// Add it to the element data.
|
|
86
|
-
datum.textContent = compactContent;
|
|
34
|
+
else if (nodeType === 3) {
|
|
35
|
+
sibInfo.text = compact(text);
|
|
87
36
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
37
|
+
return sibInfo;
|
|
38
|
+
};
|
|
39
|
+
// FUNCTION DEFINITIONS END
|
|
40
|
+
// Initialize the data with the count of the specified elements.
|
|
41
|
+
const data = {
|
|
42
|
+
total: elements.length
|
|
43
|
+
};
|
|
44
|
+
// If no itemization is required:
|
|
45
|
+
if (detailLevel === 0) {
|
|
46
|
+
// Return the element count.
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
// Otherwise, i.e. if itemization is required:
|
|
50
|
+
else {
|
|
51
|
+
// Initialize the item data.
|
|
52
|
+
data.items = [];
|
|
53
|
+
// For each specified element:
|
|
54
|
+
elements.forEach(element => {
|
|
55
|
+
// Initialize data on it.
|
|
56
|
+
const parent = element.parentElement;
|
|
57
|
+
const datum = {
|
|
58
|
+
tagName: element.tagName,
|
|
59
|
+
parentTagName: parent ? parent.tagName : '',
|
|
60
|
+
code: compact(element.outerHTML),
|
|
61
|
+
attributes: [],
|
|
62
|
+
textContent: compact(element.textContent)
|
|
99
63
|
};
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
64
|
+
// For each of its attributes:
|
|
65
|
+
for (const attribute of element.attributes) {
|
|
66
|
+
// Add data on the attribute to the element data.
|
|
67
|
+
const {name, value} = attribute;
|
|
68
|
+
datum.attributes.push({
|
|
69
|
+
name,
|
|
70
|
+
value
|
|
71
|
+
});
|
|
72
|
+
// If the element has reference labels:
|
|
73
|
+
if (name === 'aria-labelledby') {
|
|
74
|
+
// Add their texts to the element data.
|
|
75
|
+
const labelerIDs = value.split(/\s+/);
|
|
76
|
+
const labelers = [];
|
|
77
|
+
labelerIDs.forEach(id => {
|
|
78
|
+
const labeler = document.getElementById(id);
|
|
79
|
+
if (labeler) {
|
|
80
|
+
labelers.push(compact(labeler.textContent));
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
if (labelers.length) {
|
|
84
|
+
datum.labelers = labelers;
|
|
108
85
|
}
|
|
109
86
|
}
|
|
110
87
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
88
|
+
// If the element has text content:
|
|
89
|
+
const {labels, textContent} = element;
|
|
90
|
+
const compactContent = compact(textContent);
|
|
91
|
+
if (compactContent) {
|
|
92
|
+
// Add it to the element data.
|
|
93
|
+
datum.textContent = compactContent;
|
|
94
|
+
}
|
|
95
|
+
// If the element has labels:
|
|
96
|
+
if (labels && labels.length) {
|
|
97
|
+
// Add their texts to the element data.
|
|
98
|
+
datum.labels = Array.from(labels).map(label => compact(label.textContent));
|
|
99
|
+
}
|
|
100
|
+
// If the parental text content is required:
|
|
101
|
+
if (detailLevel > 1) {
|
|
102
|
+
// Add it to the element data.
|
|
103
|
+
datum.parentTextContent = parent ? parent.textContent : '';
|
|
104
|
+
}
|
|
105
|
+
// If sibling itemization is required:
|
|
106
|
+
if (detailLevel === 3) {
|
|
107
|
+
// Add the sibling data to the element data.
|
|
108
|
+
datum.siblings = {
|
|
109
|
+
before: [],
|
|
110
|
+
after: []
|
|
111
|
+
};
|
|
112
|
+
let more = element;
|
|
113
|
+
while (more) {
|
|
114
|
+
more = more.previousSibling;
|
|
115
|
+
if (more) {
|
|
116
|
+
const {nodeType, nodeValue} = more;
|
|
117
|
+
if (! (nodeType === 3 && nodeValue === '')) {
|
|
118
|
+
const sibInfo = getSibInfo(more, nodeType, nodeValue);
|
|
119
|
+
datum.siblings.before.unshift(sibInfo);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
more = element;
|
|
124
|
+
while (more) {
|
|
125
|
+
more = more.nextSibling;
|
|
126
|
+
if (more) {
|
|
127
|
+
const {nodeType, textContent} = more;
|
|
128
|
+
if (! (nodeType === 3 && textContent === '')) {
|
|
129
|
+
const sibInfo = getSibInfo(more, nodeType, compact(textContent));
|
|
130
|
+
datum.siblings.after.push(sibInfo);
|
|
131
|
+
}
|
|
119
132
|
}
|
|
120
133
|
}
|
|
121
134
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
}
|
|
135
|
+
data.items.push(datum);
|
|
136
|
+
});
|
|
137
|
+
return data;
|
|
138
|
+
}
|
|
139
|
+
}, detailLevel);
|
|
140
|
+
}
|
|
141
|
+
catch(error) {
|
|
142
|
+
console.log(`ERROR performing test (${error.message})`);
|
|
143
|
+
data = {
|
|
144
|
+
prevented: true,
|
|
145
|
+
error: 'ERROR performing test'
|
|
146
|
+
};
|
|
147
|
+
}
|
|
128
148
|
// Return the result.
|
|
129
149
|
return {result: data};
|
|
130
150
|
};
|