testilo 3.10.0 → 3.10.1
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
CHANGED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<!DOCTYPE HTML>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<meta name="author" content="Testilo">
|
|
7
|
+
<meta name="creator" content="Testilo">
|
|
8
|
+
<meta name="publisher" name="Testilo">
|
|
9
|
+
<meta name="description" content="report of accessibility testing of a web page">
|
|
10
|
+
<meta name="keywords" content="accessibility a11y web testing">
|
|
11
|
+
<title>Accessibility test digest</title>
|
|
12
|
+
<link rel="icon" href="favicon.png">
|
|
13
|
+
<link rel="stylesheet" href="style.css">
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<main>
|
|
17
|
+
<header>
|
|
18
|
+
<h1>Accessibility test digest</h1>
|
|
19
|
+
<h2>Synopsis</h2>
|
|
20
|
+
<div id="synopsis">
|
|
21
|
+
<p><strong>Page</strong>: __org__</p>
|
|
22
|
+
<p><strong>URL</strong>: __url__</p>
|
|
23
|
+
<p><strong>Score</strong>: __totalScore__</p>
|
|
24
|
+
<p><strong>Tested by</strong>: Testaro, procedure <code>tpProductPrice</code></p>
|
|
25
|
+
<p><strong>Scored by</strong>: Testilo, procedure <code>spProductPrice</code></p>
|
|
26
|
+
<p><strong>Digested by</strong>: Testilo, procedure <code>dpProductPrice</code></p>
|
|
27
|
+
</div>
|
|
28
|
+
</header>
|
|
29
|
+
<h2>Introduction</h2>
|
|
30
|
+
<p>This is a report on transactional <a href="https://www.w3.org/WAI/fundamentals/accessibility-intro/">accessibility</a>. Suppose a person is visiting a website and wants to engage in some transaction with it. Is the transaction easy, predictable, and safe? If so, the website is <dfn>transactionally accessible</dfn>. To achieve transactional accessibility, websites can design transactions that conform to the most common and standard conventions. Then users will correctly guess what to do at each step. Users with some disabilities will especially benefit from being able to use existing knowledge and tools, without the need to discover how to do things on a website.</p>
|
|
31
|
+
<p>This transaction involves finding the price of a product. The transaction begins when a person opens the home page of a vendor of the product. The user wants to find the price at which the vendor offers the product. The test assumes that there is a standard transaction structure in such a situation:</p>
|
|
32
|
+
<ol>
|
|
33
|
+
<li>The user finds a search input on the page.</li>
|
|
34
|
+
<li>The user enters a quoted query identifying the product into that input.</li>
|
|
35
|
+
<li>The user presses the Enter key to submit the query.</li>
|
|
36
|
+
<li>That submission takes the user to a product page.</li>
|
|
37
|
+
<li>On the product page, there is a description of the product offering, containing both the full name of the product and the price at which the vendor offers the product.</li>
|
|
38
|
+
<li>The elements containing the product name and price are coded with the <code>itemprop</code> attributes (<code>itemprop="name"</code> and <code>itemprop="price"</code>, respectively) specified by the <a href="https://schema.org/price">Schema.org standard for the price property</a>.</li>
|
|
39
|
+
</ol>
|
|
40
|
+
<p>As of this version of <code>spProductPrice</code>, the <code>itemprop="priceCurrency"</code> attribute is not considered; Schema.org recommends using <code>USD</code> rather than <code>$</code> as the currency identifier for the United States dollar in association with that <code>itemprop</code> value.</p>
|
|
41
|
+
<p>Thus, instead of the user needing to figure out how this particular website discloses product prices, the user is assumed already to know how websites normally do that. Instead of exploring the site to find its method, the person uses the standard method.</p>
|
|
42
|
+
<h2>Procedures</h2>
|
|
43
|
+
<p>The <a href="https://www.npmjs.com/package/testaro">Testaro</a> application used its <code>tpProductPrice</code> testing procedure to evaluate the accessibility of this transaction on the __org__ web page at <a href="__url__">__url__</a> on __dateSlash__. Testaro produced a report.</p>
|
|
44
|
+
<p>The <a href="https://www.npmjs.com/package/testilo">Testilo</a> application processed the report and used the <code>spProductPrice</code> scoring procedure to compute a score for the transaction. The total score is __totalScore__ (where 0 is the worst and 24 is the best possible score). The scored report is appended below.</p>
|
|
45
|
+
<p>Finally, Testilo used procedure <code>dpProductPrice</code> to produce this digest, briefly explaining how <code>spA11yMessage</code> computed the scores.</p>
|
|
46
|
+
<h2>Score summary</h2>
|
|
47
|
+
<table class="allBorder secondCellRight">
|
|
48
|
+
<caption>Score components</caption>
|
|
49
|
+
<tbody class="headersLeft">
|
|
50
|
+
__scoreRows__
|
|
51
|
+
</tbody>
|
|
52
|
+
</table>
|
|
53
|
+
<h2>Explanation</h2>
|
|
54
|
+
<p>The components of the total score are:</p>
|
|
55
|
+
<ul>
|
|
56
|
+
<li><code>pageLoad</code>: 2 points if it was possible to visit the page</li>
|
|
57
|
+
<li><code>pageFast</code>: 2 points if the page loaded within 4 seconds, or 1 point if it loaded within 6 seconds</li>
|
|
58
|
+
<li><code>searchInput</code>: 1 point if the page contained a search input</li>
|
|
59
|
+
<li><code>searchType</code>: 2 points if the search input consisted of an <code>input</code> element with a <code>type="search"</code> attribute rather than an <code>aria-label</code> or <code>placeholder</code> attribute with a value containing <code>search</code>.</li>
|
|
60
|
+
<li><code>searchWork</code>: 2 points if it was possible to submit the search query by pressing the Enter key</li>
|
|
61
|
+
<li><code>searchFast</code>: 3 points if the product page loaded within 3 seconds, 2 points if within 5 seconds, or 1 point if within 7 seconds</li>
|
|
62
|
+
<li><code>nameInPage</code>: 2 points if the product name was on the product page</li>
|
|
63
|
+
<li><code>nameInNode</code>: 2 points if the product name was the value of a text node on the product page</li>
|
|
64
|
+
<li><code>nameProp</code>: 3 points if the element containing that text node had an <code>itemprop="name"</code> attribute</li>
|
|
65
|
+
<li><code>price</code>: 1 point if a price appeared in the text content of the product page</li>
|
|
66
|
+
<li><code>priceProximity</code>: 4 points if the parent element of the product-name element has a price in its text content and has a descendant element with an <code>itemprop="price"</code> attribute, or 3 if this is true for a grandparent element, or 2 if true for a great-grandparent element, or 1 if true for a great-great-grandparent element.</li>
|
|
67
|
+
</ul>
|
|
68
|
+
<p>The precise rules of <code>spProductPrice</code> are found in the <a href="https://github.com/jrpool/testilo/blob/main/procs/score/spProductPrice.js">code itself</a>.</p>
|
|
69
|
+
<h2>Suggestions</h2>
|
|
70
|
+
<ul>
|
|
71
|
+
__suggestions__
|
|
72
|
+
</ul>
|
|
73
|
+
<h2>Report</h2>
|
|
74
|
+
<pre>__report__</pre>
|
|
75
|
+
<footer>
|
|
76
|
+
<p class="date">Produced <time itemprop="datePublished" datetime="__dateISO__">__dateSlash__</time></p>
|
|
77
|
+
</footer>
|
|
78
|
+
</main>
|
|
79
|
+
</body>
|
|
80
|
+
</html>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
index: digester for scoring procedure spA11yMessage.
|
|
3
|
+
Creator of parameters for substitution into index.html.
|
|
4
|
+
Usage example for selected files in REPORTDIR_SCORED: node digest dpA11yMessage 35k1r
|
|
5
|
+
Usage example for all files in REPORTDIR_SCORED: node digest dpA11yMessage
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// CONSTANTS
|
|
9
|
+
|
|
10
|
+
// Newlines with indentations.
|
|
11
|
+
const joiner = '\n ';
|
|
12
|
+
const innerJoiner = '\n ';
|
|
13
|
+
|
|
14
|
+
// FUNCTIONS
|
|
15
|
+
|
|
16
|
+
// Makes strings HTML-safe.
|
|
17
|
+
const htmlEscape = textOrNumber => textOrNumber
|
|
18
|
+
.toString()
|
|
19
|
+
.replace(/&/g, '&')
|
|
20
|
+
.replace(/</g, '<');
|
|
21
|
+
// Gets a row of the score-summary table.
|
|
22
|
+
const getScoreRow = (component, score) => `<tr><th>${component}</th><td>${score}</td></tr>`;
|
|
23
|
+
// Adds parameters to a query for a digest.
|
|
24
|
+
exports.makeQuery = (report, query) => {
|
|
25
|
+
// Add an HTML-safe copy of the host report to the query to be appended to the digest.
|
|
26
|
+
const {script, host, score} = report;
|
|
27
|
+
const reportJSON = JSON.stringify(report, null, 2);
|
|
28
|
+
const reportJSONSafe = htmlEscape(reportJSON);
|
|
29
|
+
query.report = reportJSONSafe;
|
|
30
|
+
// Add the job data to the query.
|
|
31
|
+
query.dateISO = report.endTime.slice(0, 10);
|
|
32
|
+
query.dateSlash = query.dateISO.replace(/-/g, '/');
|
|
33
|
+
if (host && host.what && host.which) {
|
|
34
|
+
query.org = host.what;
|
|
35
|
+
query.url = host.which;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
const firstURLCommand = script.commands.find(command => command.type === 'url');
|
|
39
|
+
if (firstURLCommand && firstURLCommand.what && firstURLCommand.which) {
|
|
40
|
+
query.org = firstURLCommand.what;
|
|
41
|
+
query.url = firstURLCommand.which;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
console.log('ERROR: host missing or invalid');
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// Add the score data to the query.
|
|
49
|
+
const scoreRows = [];
|
|
50
|
+
Object.keys(score).forEach(scoreName => {
|
|
51
|
+
scoreRows.push(getScoreRow(scoreName, score[scoreName]));
|
|
52
|
+
});
|
|
53
|
+
query.totalScore = score.total;
|
|
54
|
+
query.scoreRows = scoreRows.join(innerJoiner);
|
|
55
|
+
// Add suggestions to the query.
|
|
56
|
+
const suggestions = [];
|
|
57
|
+
if (score.pageLoad === 0) {
|
|
58
|
+
suggestions.push(['pageLoad', 'Make it possible to visit the page.']);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
if (score.pageFast < 2) {
|
|
62
|
+
suggestions.push(['pageFast', 'Make the page load faster.']);
|
|
63
|
+
}
|
|
64
|
+
if (score.searchInput === 0) {
|
|
65
|
+
suggestions.push(['searchInput', 'Add a search input to the page.']);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (score.searchType === 0) {
|
|
69
|
+
suggestions.push(['searchType', 'Give the search input the attribute <code>type="search"</code>.']);
|
|
70
|
+
}
|
|
71
|
+
if (score.searchWork === 0) {
|
|
72
|
+
suggestions.push(
|
|
73
|
+
['searchWork', 'Make it possible to submit a search query by pressing the Enter key.']
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
if (score.searchFast === 0) {
|
|
78
|
+
suggestions.push(['searchFast', 'Make search queries produce results faster.']);
|
|
79
|
+
}
|
|
80
|
+
if (score.nameInPage === 0) {
|
|
81
|
+
suggestions.push([
|
|
82
|
+
'nameInPage',
|
|
83
|
+
'Make the page after a product search contain the full name of the product.'
|
|
84
|
+
])
|
|
85
|
+
}
|
|
86
|
+
else if (score.nameInNode === 0) {
|
|
87
|
+
suggestions.push([
|
|
88
|
+
'nameInNode',
|
|
89
|
+
'Make the text content of an element on the product page be exactly the full name of the product.'
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
else if (score.nameProp === 0) {
|
|
93
|
+
suggestions.push(
|
|
94
|
+
[
|
|
95
|
+
'nameProp',
|
|
96
|
+
'Give the product-name element the attribute <code>itemprop="name"</code>.'
|
|
97
|
+
]
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
if (score.price === 0) {
|
|
101
|
+
suggestions.push(['price', 'Place a price onto the product page.']);
|
|
102
|
+
}
|
|
103
|
+
else if (score.priceProximity < 4) {
|
|
104
|
+
suggestions.push(['priceProximity', 'Make the price element share a parent with the product-name element and give the price element the attribute <code>itemprop="price"</code>.']);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
query.suggestions = suggestions
|
|
110
|
+
.map(pair => `<li><code>${pair[0]}</code>: ${pair[1]}</li>`)
|
|
111
|
+
.join(innerJoiner);
|
|
112
|
+
};
|