@acot/acot-preset-axe
Version:
An axe rule set for acot.
112 lines (111 loc) • 4.33 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createRule = void 0;
const core_1 = require("@acot/core");
const typebox_1 = require("@sinclair/typebox");
const injectAxe = async (page) => {
// FIXME There is a mistake in the type definition of `addScriptTag` in the puppeteer.
const script = (await page.addScriptTag({
path: require.resolve('axe-core'),
}));
return async () => {
await page.evaluate((el) => {
var _a;
(_a = el.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(el);
}, script);
};
};
const flattenResults = (results) => {
return results.reduce((acc, cur) => {
cur.nodes.forEach((node) => {
node.target.forEach((selector) => {
acc.push({
result: cur,
node,
selector,
});
});
});
return acc;
}, []);
};
const nodeChecks = (node) => [
...node.any,
...node.all,
...node.none,
];
const schema = typebox_1.Type.Strict(typebox_1.Type.Object({
context: typebox_1.Type.Optional(typebox_1.Type.String()),
iframes: typebox_1.Type.Optional(typebox_1.Type.Boolean()),
frameWaitTime: typebox_1.Type.Optional(typebox_1.Type.Number({ minimum: 0 })),
rules: typebox_1.Type.Optional(typebox_1.Type.Record(typebox_1.Type.String(), typebox_1.Type.Object({
enabled: typebox_1.Type.Boolean(),
}, {
additionalProperties: false,
}))),
}, {
additionalProperties: false,
}));
const createRule = (config) => {
return (0, core_1.createRule)({
meta: {
recommended: true,
},
schema,
test: async (context) => {
var _a, _b, _c, _d;
const cleanup = await injectAxe(context.page);
const axeResults = await context.page.evaluate((tag, options) => {
const assign = (to, from, key) => {
if (from[key] != null) {
to[key] = from[key];
}
};
const spec = {
branding: {
application: 'acot',
},
};
const opts = {
resultTypes: ['violations', 'incomplete'],
runOnly: {
type: 'rule',
values: window.axe.getRules([tag]).map(({ ruleId }) => ruleId),
},
};
assign(opts, options, 'iframes');
assign(opts, options, 'frameWaitTime');
assign(opts, options, 'rules');
window.axe.configure(spec);
return options.context != null
? window.axe.run(options.context, opts)
: window.axe.run(opts);
}, config.tag, {
context: (_a = context.options.context) !== null && _a !== void 0 ? _a : null,
iframes: (_b = context.options.iframes) !== null && _b !== void 0 ? _b : null,
frameWaitTime: (_c = context.options.iframes) !== null && _c !== void 0 ? _c : null,
rules: (_d = context.options.rules) !== null && _d !== void 0 ? _d : null,
});
const results = [...axeResults.violations, ...axeResults.incomplete];
context.debug('axe results: %O', results);
// Remove Axe module in the HTML before dumping the HTML for the report
await cleanup();
if (results.length > 0) {
await Promise.all(flattenResults(results).map(async ({ result, node, selector }) => {
const el = await context.page.$(selector);
if (el == null) {
return;
}
await Promise.all(nodeChecks(node).map(async (check) => {
await context.report({
message: `${result.help}. ${check.message}. (${result.id})`,
help: result.helpUrl,
node: el,
});
}));
}));
}
},
});
};
exports.createRule = createRule;