@axe-core/cli 4.7.4-60abf5e.0 → 4.7.4-7f71bce.0

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.
@@ -1,73 +0,0 @@
1
- import 'mocha';
2
- import { assert } from 'chai';
3
- import testPages from './axe-test-urls';
4
- import { ConfigParams } from '../types';
5
-
6
- describe('testPages', function () {
7
- this.timeout(10000);
8
- let config: ConfigParams;
9
- let mockDriver: any;
10
-
11
- beforeEach(() => {
12
- const func = async (arg: any) => '{}';
13
- mockDriver = {
14
- get: func,
15
- executeAsyncScript: func,
16
- executeScript: func,
17
- wait: func,
18
- switchTo: () => ({ defaultContent: () => {} }),
19
- findElements: async () => [],
20
- quit: func,
21
- manage: () => ({
22
- setTimeouts: func
23
- })
24
- };
25
- config = { driver: mockDriver };
26
- });
27
-
28
- it('return a promise', () => {
29
- assert.instanceOf(testPages([], config), Promise);
30
- });
31
-
32
- it('calls driver.get() for each URL', async () => {
33
- const urlsCalled: string[] = [];
34
- const urls = ['http://foo', 'http://bar', 'http://baz'];
35
-
36
- mockDriver.get = async (url: string) => {
37
- urlsCalled.push(url);
38
- return url;
39
- };
40
-
41
- await testPages(urls, config);
42
-
43
- assert.deepEqual(urlsCalled, urls);
44
- });
45
-
46
- it('injects axe into the page', async () => {
47
- const scripts: string[] = [];
48
- config.axeSource = 'axe="hi, I am axe"';
49
- mockDriver.executeScript = async (script: string) => {
50
- scripts.push(script);
51
- return script;
52
- };
53
-
54
- await testPages(['http://foo'], config);
55
- assert.include(scripts[0].toString(), config.axeSource);
56
- });
57
-
58
- it('runs axe once the page is loaded', async () => {
59
- const asyncScripts: string[] = [];
60
- mockDriver.executeAsyncScript = async (script: string) => {
61
- asyncScripts.push(script);
62
- return '{}';
63
- };
64
-
65
- await testPages(['http://foo'], config);
66
-
67
- assert.isDefined(
68
- asyncScripts
69
- .map(script => script.toString())
70
- .find(script => script.match(/(axe\.run)|(axe\.a11yCheck)/))
71
- );
72
- });
73
- });
@@ -1,98 +0,0 @@
1
- import WebDriver from 'selenium-webdriver';
2
- import AxeBuilder from '@axe-core/webdriverjs';
3
- import { AxeResults } from 'axe-core';
4
- import { EventResponse, ConfigParams } from '../types';
5
-
6
- const testPages = async (
7
- urls: string | string[],
8
- config: ConfigParams,
9
- events?: EventResponse
10
- ): Promise<AxeResults[] | AxeResults> => {
11
- const driver: WebDriver.WebDriver = await config.driver;
12
-
13
- if (urls.length === 0) {
14
- await driver.quit();
15
- return Promise.resolve([]);
16
- }
17
-
18
- return new Promise((resolve, reject) => {
19
- const currentUrl = urls[0].replace(/[,;]$/, '');
20
-
21
- if (events?.onTestStart) {
22
- events?.onTestStart(currentUrl);
23
- }
24
-
25
- if (config.timer) {
26
- events?.startTimer('axe page load time');
27
- }
28
-
29
- driver
30
- .get(currentUrl)
31
- .then(() => {
32
- if (config.timer) {
33
- events?.endTimer('axe page load time');
34
- }
35
-
36
- if (config.loadDelay) {
37
- events?.waitingMessage(config.loadDelay);
38
- }
39
-
40
- return new Promise(resolve => {
41
- setTimeout(resolve, config.loadDelay);
42
- });
43
- })
44
- .then(() => {
45
- const axe = new AxeBuilder(driver, config.axeSource);
46
-
47
- if (Array.isArray(config.include)) {
48
- config.include.forEach((include: string) => axe.include(include));
49
- }
50
-
51
- if (Array.isArray(config.exclude)) {
52
- config.exclude.forEach((exclude: string) => axe.exclude(exclude));
53
- }
54
-
55
- if (config.tags) {
56
- axe.withTags(config.tags);
57
- } else if (config.rules) {
58
- axe.withRules(config.rules);
59
- }
60
-
61
- /* istanbul ignore if */
62
- if (config.disable) {
63
- axe.disableRules(config.disable);
64
- }
65
-
66
- if (config.timer) {
67
- events?.startTimer('axe-core execution time');
68
- }
69
-
70
- axe.analyze((err: Error | null, results: AxeResults) => {
71
- if (config.timer) {
72
- events?.endTimer('axe-core execution time');
73
- }
74
-
75
- /* istanbul ignore if */
76
- if (err) {
77
- return reject(err);
78
- }
79
-
80
- // Notify about the update
81
- if (events?.onTestComplete) {
82
- events?.onTestComplete(results);
83
- }
84
-
85
- // Move to the next item
86
- testPages(urls.slice(1), config, events).then((out: AxeResults) => {
87
- resolve([results].concat(out));
88
- });
89
- });
90
- })
91
- .catch(async e => {
92
- await driver.quit();
93
- reject(e);
94
- });
95
- });
96
- };
97
-
98
- export default testPages;
@@ -1,26 +0,0 @@
1
- import 'mocha';
2
- import { assert } from 'chai';
3
- import events from './events';
4
-
5
- describe('events()', () => {
6
- const event = events({
7
- silentMode: false,
8
- timer: false,
9
- cliReporter: () => {},
10
- verbose: false,
11
- exit: false
12
- });
13
- const functions = [
14
- 'startTimer',
15
- 'endTimer',
16
- 'waitingMessage',
17
- 'onTestStart',
18
- 'onTestComplete'
19
- ];
20
- for (const eventFunction of functions) {
21
- it(`${eventFunction} is a typeof function`, () => {
22
- // @ts-ignore
23
- assert.isFunction(event[eventFunction]);
24
- });
25
- }
26
- });
package/src/lib/events.ts DELETED
@@ -1,68 +0,0 @@
1
- import type { AxeResults } from 'axe-core';
2
- import type { EventParams } from '../types';
3
- import { selectorToString, error, link, bold, green } from './utils';
4
-
5
- export default ({ silentMode, timer, cliReporter, verbose }: EventParams) => {
6
- return {
7
- startTimer: (message: string) => {
8
- console.time(message);
9
- },
10
- endTimer: (message: string) => {
11
- console.timeEnd(message);
12
- },
13
- waitingMessage: (loadDelayTime: number) => {
14
- console.log(
15
- 'Waiting for ' + loadDelayTime + ' milliseconds after page loads...'
16
- );
17
- },
18
- onTestStart: (url: string) => {
19
- if (silentMode) {
20
- return;
21
- }
22
- console.log(
23
- bold('\nTesting ' + link(url)) +
24
- ' ... please wait, this may take a minute.'
25
- );
26
- if (timer) {
27
- console.time('Total test time');
28
- }
29
- },
30
- onTestComplete: (results: AxeResults) => {
31
- const { violations, testEngine, testEnvironment, testRunner } = results;
32
-
33
- /* istanbul ignore if */
34
- if (violations.length === 0) {
35
- cliReporter(green(' 0 violations found!'));
36
- return;
37
- }
38
-
39
- const issueCount = violations.reduce((count, violation) => {
40
- cliReporter(
41
- '\n' +
42
- error(' Violation of %j with %d occurrences!\n') +
43
- ' %s. Correct invalid elements at:\n' +
44
- violation.nodes
45
- .map(node => ' - ' + selectorToString(node.target) + '\n')
46
- .join('') +
47
- ' For details, see: %s',
48
- violation.id,
49
- violation.nodes.length,
50
- violation.description,
51
- link(violation.helpUrl.split('?')[0])
52
- );
53
- return count + violation.nodes.length;
54
- }, 0);
55
-
56
- cliReporter(error('\n%d Accessibility issues detected.'), issueCount);
57
-
58
- if (verbose) {
59
- const metadata = {
60
- 'Test Runner': testRunner,
61
- 'Test Engine': testEngine,
62
- 'Test Environment': testEnvironment
63
- };
64
- cliReporter(`\n${JSON.stringify(metadata, null, 2)}`);
65
- }
66
- }
67
- };
68
- };
package/src/lib/index.ts DELETED
@@ -1,5 +0,0 @@
1
- import testPages from './axe-test-urls';
2
- import { saveOutcome } from './utils';
3
- import * as utils from './utils';
4
-
5
- export { saveOutcome, testPages, utils };
@@ -1,160 +0,0 @@
1
- import 'mocha';
2
- import { assert } from 'chai';
3
- import tempy from 'tempy';
4
- import { join } from 'path';
5
- import { mkdirSync, writeFileSync, rmSync } from 'fs';
6
- import { dependencies } from '../../package.json';
7
- import * as utils from './utils';
8
-
9
- describe('utils', () => {
10
- describe('parseUrl', () => {
11
- it('given a url without protocol', () => {
12
- const url = 'foobar.com';
13
- assert.deepEqual(utils.parseUrl(url), `http://${url}`);
14
- });
15
- it('given a url with a protocol', () => {
16
- const url = 'http://foobar.com';
17
- assert.deepEqual(utils.parseUrl(url), url);
18
- });
19
- });
20
-
21
- describe('parseBrowser', () => {
22
- it('given an unknown browser returns error', () => {
23
- assert.throws(() => utils.parseBrowser('foobar'));
24
- });
25
-
26
- it('given no browser returns chrome-headless', () => {
27
- assert.deepEqual(utils.parseBrowser(), 'chrome-headless');
28
- });
29
-
30
- describe('returns firefox', () => {
31
- const firefoxBrowsers = ['ff', 'firefox', 'gecko', 'marionette'];
32
- for (const firefoxBrowser of firefoxBrowsers) {
33
- it(`given ${firefoxBrowser} returns firefox`, () => {
34
- assert.deepEqual(utils.parseBrowser(firefoxBrowser), 'firefox');
35
- });
36
- }
37
- });
38
-
39
- describe('returns chrome', () => {
40
- it('given chrome returns chrome', () => {
41
- assert.deepEqual(utils.parseBrowser('chrome'), 'chrome');
42
- });
43
- });
44
-
45
- describe('returns ie', () => {
46
- const ieBrowsers = [
47
- 'ie',
48
- 'explorer',
49
- 'internetexplorer',
50
- 'internet_explorer',
51
- 'internet-explorer'
52
- ];
53
-
54
- for (const ieBrowser of ieBrowsers) {
55
- it(`given ${ieBrowser} returns ie`, () => {
56
- assert.deepEqual(utils.parseBrowser(ieBrowser), 'ie');
57
- });
58
- }
59
- });
60
-
61
- describe('returns safari', () => {
62
- it('given safari return safari', () => {
63
- assert.deepEqual(utils.parseBrowser('safari'), 'safari');
64
- });
65
- });
66
-
67
- describe('returns edge', () => {
68
- const edgeBrowsers = ['edge', 'microsoftedge'];
69
- for (const edgeBrowser of edgeBrowsers) {
70
- it(`given ${edgeBrowser} returns MicrosoftEdge`, () => {
71
- assert.deepEqual(utils.parseBrowser(edgeBrowser), 'MicrosoftEdge');
72
- });
73
- }
74
- });
75
- });
76
-
77
- describe('getAxeSource', () => {
78
- describe('mock file', () => {
79
- function setupTree() {
80
- const tempDir = tempy.directory();
81
- const parentDirname = join(tempDir, 'node_modules', 'axe-core');
82
- mkdirSync(parentDirname, { recursive: true });
83
- writeFileSync(join(parentDirname, 'axe.js'), 'parent');
84
-
85
- const cliDirname = join(tempDir, 'packages', 'cli');
86
- const nodeModDirname = join(
87
- cliDirname,
88
- 'node_modules',
89
- 'axe-core'
90
- );
91
- mkdirSync(nodeModDirname, { recursive: true });
92
- writeFileSync(join(nodeModDirname, 'axe.js'), 'node modules');
93
-
94
- const cwdDirname = join(tempDir, 'packages', 'cli', 'lib');
95
- mkdirSync(cwdDirname);
96
- writeFileSync(join(cwdDirname, 'axe.js'), 'cwd');
97
- return {
98
- cliDirname,
99
- parentDirname,
100
- nodeModDirname,
101
- cwdDirname
102
- };
103
- }
104
-
105
- it('uses axe.js from the working directory if it exists', () => {
106
- const { cwdDirname } = setupTree();
107
- const axeSource = utils.getAxeSource(undefined, cwdDirname);
108
- assert.include(axeSource, 'cwd');
109
- });
110
- it("falls back to axe-core from the working directory's node_modules if axe.js doesn't exist in the working directory", () => {
111
- const { cliDirname, cwdDirname } = setupTree();
112
- rmSync(join(cwdDirname, 'axe.js'));
113
- const axeSource = utils.getAxeSource(undefined, cliDirname);
114
- assert.include(axeSource, 'node modules');
115
- });
116
- it("falls back to axe-core from our own package's node_modules if no working-directory based implementation exists", () => {
117
- const { cwdDirname, nodeModDirname } = setupTree();
118
- rmSync(join(cwdDirname, 'axe.js'));
119
- rmSync(join(nodeModDirname, 'axe.js'));
120
- const axeSource = utils.getAxeSource(undefined, cwdDirname);
121
- assert.include(axeSource, 'parent');
122
- });
123
- });
124
-
125
- it('given no axe source use local source', () => {
126
- const axeSource = utils.getAxeSource();
127
- assert.isNotNull(axeSource);
128
- });
129
-
130
- it('given invalid axe source throws error', () => {
131
- assert.throws(() => utils.getAxeSource('././././'));
132
- });
133
- });
134
-
135
- describe('getAxeVersion', () => {
136
- it('given valid axe version returns only version', () => {
137
- assert.deepEqual(utils.getAxeVersion(`axe.version = '4.1.1'`), '4.1.1');
138
- });
139
-
140
- it('given invalid axe version returns unknown version string', () => {
141
- assert.deepEqual(utils.getAxeVersion(`axe = '4.1.1'`), 'unknown version');
142
- });
143
- });
144
-
145
- describe('splitList', () => {
146
- it('given a comma delimited string returns array', () => {
147
- const delimited = 'foo,bar,baz';
148
- const array = utils.splitList(delimited);
149
- assert.isArray(array);
150
- assert.deepEqual(array, ['foo', 'bar', 'baz']);
151
- });
152
-
153
- it('given a single string returns an array', () => {
154
- const string = 'foo';
155
- const array = utils.splitList(string);
156
- assert.isArray(array);
157
- assert.deepEqual(array, ['foo']);
158
- });
159
- });
160
- });
package/src/lib/utils.ts DELETED
@@ -1,155 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import colors from 'colors';
4
- import { AxeResults } from 'axe-core';
5
-
6
- export const saveOutcome = (
7
- outcome: AxeResults | AxeResults[],
8
- fileName?: string,
9
- dir?: string
10
- ): string => {
11
- if (typeof fileName !== 'string') {
12
- fileName = 'axe-results-' + Date.now() + '.json';
13
- }
14
- /* istanbul ignore if */
15
- if (typeof dir !== 'string') {
16
- dir = process.cwd();
17
- } else if (!path.isAbsolute(dir)) {
18
- dir = path.join(process.cwd(), dir);
19
- }
20
-
21
- const filePath = path.join(dir, fileName);
22
-
23
- /* istanbul ignore else */
24
- if (!fs.existsSync(filePath)) {
25
- fs.mkdirSync(dir, { recursive: true });
26
- }
27
- fs.writeFileSync(filePath, JSON.stringify(outcome, null, 2), 'utf-8');
28
- return filePath;
29
- };
30
-
31
- export const parseUrl = (url: string): string => {
32
- if (!/[a-z]+:\/\//.test(url)) {
33
- return 'http://' + url;
34
- }
35
- return url;
36
- };
37
-
38
- export const parseBrowser = (browser?: string): string | Error => {
39
- if (!browser) {
40
- return 'chrome-headless';
41
- }
42
-
43
- const l = browser.length;
44
- switch (browser.toLowerCase()) {
45
- case 'ff':
46
- case 'firefox'.substr(0, l):
47
- case 'gecko'.substr(0, l):
48
- case 'marionette'.substr(0, l):
49
- return 'firefox';
50
-
51
- case 'chrome'.substr(0, l):
52
- return 'chrome';
53
-
54
- case 'ie':
55
- case 'explorer'.substr(0, l):
56
- case 'internetexplorer'.substr(0, l):
57
- case 'internet_explorer'.substr(0, l):
58
- case 'internet-explorer'.substr(0, l):
59
- return 'ie';
60
-
61
- case 'safari'.substr(0, l):
62
- return 'safari';
63
-
64
- case 'edge'.substr(0, l):
65
- case 'microsoftedge'.substr(0, l):
66
- return 'MicrosoftEdge';
67
-
68
- default:
69
- throw new Error('Unknown browser ' + browser);
70
- }
71
- };
72
-
73
- export const getAxeSource = (
74
- axePath?: string,
75
- dirname?: string
76
- ): string | void => {
77
- // Abort if axePath should exist, and it isn't
78
- if (axePath && !fs.existsSync(axePath)) {
79
- return;
80
- }
81
-
82
- let cwd = dirname;
83
- if (!cwd) {
84
- cwd = process.cwd();
85
- }
86
-
87
- if (!dirname) {
88
- dirname = __dirname;
89
- }
90
-
91
- // Look for axe in current working directory
92
- if (!axePath) {
93
- axePath = path.join(cwd, 'axe.js');
94
- }
95
-
96
- if (!fs.existsSync(axePath)) {
97
- // Look for axe in CWD ./node_modules
98
- axePath = path.join(cwd, 'node_modules', 'axe-core', 'axe.js');
99
- }
100
-
101
- if (!fs.existsSync(axePath)) {
102
- // `__dirname` is /@axe-core/cli/dist/src/lib when installed globally
103
- // to access the locally installed axe-core package we need to go up 3 levels
104
- // if all else fails, use the locally installed axe
105
- axePath = path.join(
106
- dirname,
107
- '..',
108
- '..',
109
- '..',
110
- 'node_modules',
111
- 'axe-core',
112
- 'axe.js'
113
- );
114
- }
115
-
116
- return fs.readFileSync(axePath, 'utf-8');
117
- };
118
-
119
- export const getAxeVersion = (source: string): string => {
120
- const match = source.match(/\.version\s*=\s'([^']+)'/);
121
- return match ? match[1] : 'unknown version';
122
- };
123
-
124
- export const splitList = (val: string): string[] => {
125
- return val.split(/[,;]/).map(str => str.trim());
126
- };
127
-
128
- export const selectorToString = (
129
- selectors: string[],
130
- separator?: string
131
- ): string => {
132
- separator = separator || ' ';
133
- return selectors
134
- .reduce((prev, curr) => prev.concat(curr as never), [])
135
- .join(separator);
136
- };
137
-
138
- export const reporter = (
139
- noReporter: boolean,
140
- silentMode: boolean
141
- ): (() => void) => {
142
- if (!noReporter || silentMode) {
143
- return () => {};
144
- } else {
145
- return (...args: string[]) => {
146
- console.log(...args);
147
- };
148
- }
149
- };
150
-
151
- export const link = colors.underline.blue;
152
- export const error = colors.red.bold;
153
- export const bold = colors.bold;
154
- export const green = colors.green;
155
- export const italics = colors.italic;
@@ -1,104 +0,0 @@
1
- import 'mocha';
2
- import { assert } from 'chai';
3
- import { startDriver } from './webdriver';
4
- import { WebDriver } from 'selenium-webdriver';
5
- import chromedriver from 'chromedriver';
6
- import chrome from 'selenium-webdriver/chrome';
7
- import type { Options } from 'selenium-webdriver/chrome';
8
- import path from 'path';
9
- import { WebdriverConfigParams } from '../types';
10
- describe('startDriver', () => {
11
- let config: WebdriverConfigParams;
12
- let browser: string;
13
- let driver: WebDriver;
14
- beforeEach(() => {
15
- browser = 'chrome-headless';
16
- config = {
17
- timeout: 90,
18
- get browser() {
19
- return browser;
20
- }
21
- };
22
- });
23
-
24
- afterEach(async () => {
25
- await driver.quit();
26
- });
27
-
28
- it('creates a driver', async () => {
29
- driver = await startDriver(config);
30
- assert.isObject(driver);
31
- assert.isFunction(driver.manage);
32
- });
33
-
34
- xit('sets the config.browser as the browser', async () => {
35
- browser = 'chrome';
36
- driver = await startDriver(config);
37
- const capabilities = await driver.getCapabilities();
38
- assert.equal(capabilities.get('browserName'), browser);
39
- });
40
-
41
- it('sets the browser as chrome with chrome-headless', async () => {
42
- browser = 'chrome-headless';
43
- driver = await startDriver(config);
44
- const capabilities = await driver.getCapabilities();
45
-
46
- assert.equal(capabilities.get('browserName'), 'chrome');
47
- });
48
-
49
- it('uses the chromedriver path with chrome-headless', async () => {
50
- browser = 'chrome-headless';
51
- driver = await startDriver(config);
52
- const chromedriverPath = (config as any).builder.chromeService_.exe_;
53
-
54
- assert.equal(chromedriverPath, chromedriver.path);
55
- });
56
-
57
- it('uses the passed in chromedriver path with chrome-headless', async () => {
58
- browser = 'chrome-headless';
59
- config.chromedriverPath = path.relative(process.cwd(), chromedriver.path);
60
- driver = await startDriver(config);
61
- const chromedriverPath = (config as any).builder.chromeService_.exe_;
62
-
63
- assert.notEqual(config.chromedriverPath, chromedriver.path);
64
- assert.equal(chromedriverPath, config.chromedriverPath);
65
- });
66
-
67
- it('passes the --no-sandbox argument to chromeOptions', async () => {
68
- browser = 'chrome-headless';
69
- config.chromeOptions = ['--no-sandbox'];
70
- driver = await startDriver(config);
71
-
72
- const options = config?.builder?.getChromeOptions();
73
- assert.isArray(options?.get('goog:chromeOptions').args);
74
- assert.deepEqual(options?.get('goog:chromeOptions').args, [
75
- 'headless',
76
- '--no-sandbox'
77
- ]);
78
- });
79
-
80
- it('passes multiple arguments argument to chromeOptions', async () => {
81
- browser = 'chrome-headless';
82
- config.chromeOptions = ['no-sandbox', 'disable-dev-shm-usage'];
83
- driver = await startDriver(config);
84
-
85
- const options = config?.builder?.getChromeOptions();
86
- assert.isArray(options?.get('goog:chromeOptions').args);
87
- assert.deepEqual(options?.get('goog:chromeOptions').args, [
88
- 'headless',
89
- 'no-sandbox',
90
- 'disable-dev-shm-usage'
91
- ]);
92
- });
93
-
94
- it('sets the --timeout flag', async () => {
95
- browser = 'chrome-headless';
96
- config.timeout = 10000;
97
- driver = await startDriver(config);
98
- config.builder;
99
- const timeoutValue = await driver.manage().getTimeouts();
100
-
101
- assert.isObject(timeoutValue);
102
- assert.deepEqual(timeoutValue.script, 10000000);
103
- });
104
- });