forked from dequelabs/axe-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
executable file
·245 lines (222 loc) · 6.04 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
'use strict';
const program = require('commander');
const colors = require('colors');
const link = colors.underline.blue;
const error = colors.red.bold;
const version = require('./package.json').version;
const axeTestUrls = require('./lib/axe-test-urls');
const saveOutcome = require('./lib/save-outcome');
const utils = require('./lib/utils');
program
.version(version)
.usage('<url...> [options]')
.option(
'-i, --include <list>',
'CSS selector of included elements, comma separated',
utils.splitList
)
.option(
'-e, --exclude <list>',
'CSS selector of included elements, comma separated',
utils.splitList
)
.option(
'-r, --rules <list>',
'IDs of rules to run, comma separated',
utils.splitList
)
.option(
'-t, --tags <list>',
'Tags of rules to run, comma separated',
utils.splitList
)
.option(
'-l, --disable <list>',
'IDs of rules to disable, comma separated',
utils.splitList
)
.option(
'-b, --browser [browser-name]',
'Which browser to run (Webdriver required)'
)
.option(
'-s, --save [filename]',
'Save the output as a JSON file. Filename is optional'
)
.option(
'-j, --stdout',
'Output results to STDOUT and silence all other output'
)
.option('-d, --dir <path>', 'Output directory')
.option('-a, --axe-source <path>', 'Path to axe.js file')
.option('-q, --exit', 'Exit with `1` failure code if any a11y tests fail')
.option(
'--load-delay <n>',
'Set how much time (milliseconds) axe will wait after page load before running the audit (default: 0)',
0
)
.option(
'--timeout <n>',
'Set how much time (seconds) axe has to run (default: 90)',
90
)
.option('--timer', 'Log the time it takes to run')
.option('--show-errors', 'Display the full error stack')
// TODO: Replace this with a reporter option, this required adding
// a reporter option to axe-webdriverjs
.option('--no-reporter', 'Turn the CLI reporter off')
.option(
'--chrome-options [options]',
'Options to provide to headless Chrome',
utils.splitList
)
// .option('-c, --config <file>', 'Path to custom axe configuration')
.parse(process.argv);
const silentMode = !!program.stdout;
program.browser = utils.parseBrowser(program.browser);
program.axeSource = utils.getAxeSource(program.axeSource);
if (!program.axeSource) {
console.error(error('Unable to find the axe-core source file.'));
return;
}
if (program.chromeOptions) {
if (program.browser !== 'chrome-headless') {
console.error(
error('You may only provide --chrome-options when using headless chrome')
);
process.exit(2);
}
program.chromeOptions = program.chromeOptions.map(option => `--${option}`);
}
let cliReporter;
if (program.reporter === false || silentMode) {
cliReporter = function() {};
} else {
cliReporter = function(...args) {
console.log(...args);
};
}
// Try to match the version of axe that's used
const axeVersion = utils.getAxeVersion(program.axeSource);
if (!silentMode) {
// Setup axe with the appropriate config
console.log(
colors.bold('Running axe-core ' + axeVersion + ' in ' + program.browser)
);
}
// Make valid URLs of all pages
const urls = program.args.map(utils.parseUrl);
if (urls.length === 0) {
console.error(error('No url was specified. Check `axe -h` for help\n'));
process.exitCode = 1;
return;
}
// Run axe inside the pages
axeTestUrls(urls, program, {
/**
* Inform the user what page is tested
*/
onTestStart: function(url) {
if (silentMode) {
return;
}
console.log(
colors.bold('\nTesting ' + link(url)) +
' ... please wait, this may take a minute.'
);
if (program.timer) {
console.time('Total test time');
}
},
/**
* Put the result in the console
*/
onTestComplete: function logResults(results) {
const violations = results.violations;
if (violations.length === 0) {
cliReporter(colors.green(' 0 violations found!'));
return;
}
const issueCount = violations.reduce((count, violation) => {
cliReporter(
'\n' +
error(' Violation of %j with %d occurrences!\n') +
' %s. Correct invalid elements at:\n' +
violation.nodes
.map(node => ' - ' + utils.selectorToString(node.target) + '\n')
.join('') +
' For details, see: %s',
violation.id,
violation.nodes.length,
violation.description,
link(violation.helpUrl.split('?')[0])
);
return count + violation.nodes.length;
}, 0);
cliReporter(error('\n%d Accessibility issues detected.'), issueCount);
if (program.exit) {
process.exitCode = 1;
}
}
})
.then(function(outcome) {
if (silentMode) {
process.stdout.write(JSON.stringify(outcome, null, 2));
return;
}
console.log('');
if (program.timer) {
console.timeEnd('Total test time');
}
// All results are in, quit the browser, and give a final report
if (outcome.length > 1) {
console.log(
colors.bold.underline('Testing complete of %d pages\n'),
outcome.length
);
} else if (program.timer) {
console.log('');
}
// Save the outcome
if (program.save || program.dir) {
return saveOutcome(outcome, program.save, program.dir)
.then(fileName => {
console.log('Saved file at', fileName, '\n');
})
.catch(err => {
console.error(error('Unable to save file!\n') + err);
process.exitCode = 1;
return Promise.resolve();
});
} else {
return Promise.resolve();
}
})
.then(() => {
if (silentMode) {
return;
}
// Give a notification that 0 issues in axe doesn't mean perfect a11y
console.log(
colors.italic(
'Please note that only 20% to 50% of all accessibility ' +
'issues can automatically be detected. \nManual testing is ' +
'always required. For more information see:\n%s\n'
),
link('https://dequeuniversity.com/curriculum/courses/testingmethods')
);
})
.catch(e => {
console.error(' ');
if (!program['show-errors']) {
console.error(error('An error occurred while testing this page.'));
} else {
console.error(error('Error: %j \n $s'), e.message, e.stack);
}
console.error(
'Please report the problem to: ' +
link('https://github.com/dequelabs/axe-cli/issues/') +
'\n'
);
process.exit(1);
});