/
index.ts
102 lines (88 loc) · 2.7 KB
/
index.ts
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
/* eslint-disable @typescript-eslint/no-object-literal-type-assertion */
import { document } from 'global';
import axe, { AxeResults, ElementContext, RunOptions, Spec } from 'axe-core';
import deprecate from 'util-deprecate';
import { stripIndents } from 'common-tags';
import addons, { makeDecorator } from '@storybook/addons';
import { EVENTS, PARAM_KEY } from './constants';
let progress = Promise.resolve();
interface Setup {
element?: ElementContext;
config: Spec;
options: RunOptions;
}
let setup: Setup = { element: null, config: {}, options: {} };
const getElement = () => {
const storyRoot = document.getElementById('story-root');
if (storyRoot) {
return storyRoot.children;
}
return document.getElementById('root');
};
const report = (input: AxeResults) => addons.getChannel().emit(EVENTS.RESULT, input);
const run = (element: ElementContext, config: Spec, options: RunOptions) => {
progress = progress.then(() => {
axe.reset();
if (config) {
axe.configure(config);
}
return axe
.run(
element || getElement(),
options ||
({
restoreScroll: true,
} as RunOptions) // cast to RunOptions is necessary because axe types are not up to date
)
.then(report)
.catch(error => addons.getChannel().emit(EVENTS.ERROR, String(error)));
});
};
if (module && module.hot && module.hot.decline) {
module.hot.decline();
}
let storedDefaultSetup: Setup | null = null;
export const withA11y = makeDecorator({
name: 'withA11Y',
parameterName: PARAM_KEY,
wrapper: (getStory, context, { parameters }) => {
if (parameters) {
if (storedDefaultSetup === null) {
storedDefaultSetup = { ...setup };
}
Object.assign(setup, parameters as Setup);
} else if (storedDefaultSetup !== null) {
Object.assign(setup, storedDefaultSetup);
storedDefaultSetup = null;
}
addons.getChannel().on(EVENTS.REQUEST, () => run(setup.element, setup.config, setup.options));
return getStory(context);
},
});
// TODO: REMOVE at v6.0.0
export const withA11Y = deprecate(
// @ts-ignore
(...args: any[]) => withA11y(...args),
'withA11Y has been renamed withA11y'
);
// TODO: REMOVE at v6.0.0
export const checkA11y = deprecate(
// @ts-ignore
(...args: any[]) => withA11y(...args),
'checkA11y has been renamed withA11y'
);
// TODO: REMOVE at v6.0.0
export const configureA11y = deprecate(
(config: any) => {
setup = config;
},
stripIndents`
configureA11y is deprecated, please configure addon-a11y using the addParameter api:
addParameters({
a11y: {
// ... axe options
element: '#root', // optional selector which element to inspect
},
});
`
);