/* 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 dedent from 'ts-dedent'; 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); }); }; if (module && module.hot && module.hot.decline) { module.hot.decline(); } export const withA11y = makeDecorator({ name: 'withA11Y', parameterName: PARAM_KEY, wrapper: (getStory, context, { parameters }) => { if (parameters) { setup = parameters as Setup; } 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; }, dedent` configureA11y is deprecated, please configure addon-a11y using the addParameter api: addParameters({ a11y: { // ... axe options element: '#root', // optional selector which element to inspect }, }); ` );