Skip to content

Commit

Permalink
feat(runner): add ace accessibility ibm
Browse files Browse the repository at this point in the history
  • Loading branch information
j-mendez committed Sep 26, 2023
1 parent 5b91832 commit 1a77d38
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 46 deletions.
1 change: 1 addition & 0 deletions kayle/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ kayle supports multiple test runners which return different results. The built-i

- `axe`: run tests using [axe-core](./lib/runners/axe.ts).
- `htmlcs` (default): run tests using [HTML CodeSniffer](./lib/runners/htmlcs.ts)
- `ace`: run tests using [IBM ACE](https://github.com/IBMa/equal-access/blob/master/accessibility-checker-engine/README.md)
- `custom`: custom runners using `injectRunner` util.

## Playwright/Puppeteer
Expand Down
7 changes: 3 additions & 4 deletions kayle/lib/kayle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ const injectRunners = async (config: RunnerConfig) => {
if (!config.browserExtension) {
return await Promise.all([
config.page.evaluate(runnersJavascript["kayle"]),
config.page.evaluate(getRunner(config.language, config.runners[0])),
config.runners.length === 2
? config.page.evaluate(getRunner(config.language, config.runners[1]))
: undefined,
...config.runners.map((r) =>
config.page.evaluate(getRunner(config.language, r))
),
]);
}
};
Expand Down
24 changes: 11 additions & 13 deletions kayle/lib/runner-js.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { readFileSync } from "fs";
import { axeRunner } from "./runners/axe";
import { htmlcsRunner } from "./runners/htmlcs";
import { aceRunner } from "./runners/ace";

const loadRunnerFile = (run, langauge) => {
if (run === "htmlcs") {
Expand All @@ -11,6 +12,10 @@ const loadRunnerFile = (run, langauge) => {
return axeRunner[langauge || "en"];
}

if (run === "ace") {
return aceRunner[langauge || "en"];
}

return require(run);
};

Expand Down Expand Up @@ -52,6 +57,9 @@ const runnersJavascript = {
axe_ko: loadRunnerScript("axe", "ko"),
// axe_no_NB: loadRunnerScript("axe", "no-NB"),
// axe_pt_BR: loadRunnerScript("axe", "pt-BR"),
// expiremental
// ace by IBM
ace: loadRunnerScript("ace", ""),
};

// inject a new runner for testing
Expand All @@ -71,20 +79,10 @@ const getRunner = (
) => {
// if langauge exist get the runner type
if (language) {
if (runner === "axe") {
const script = `axe_${language}`;

if (typeof runnersJavascript[script] !== "undefined") {
return runnersJavascript[script];
}
}

if (runner === "htmlcs") {
const script = `htmlcs_${language}`;
const script = `${runner}_${language}`;

if (typeof runnersJavascript[script] !== "undefined") {
return runnersJavascript[script];
}
if (typeof runnersJavascript[script] !== "undefined") {
return runnersJavascript[script];
}
}

Expand Down
73 changes: 45 additions & 28 deletions kayle/lib/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
error: 1,
warning: 2,
notice: 3,
// ibm
VIOLATION: 1,
RECOMMENDATION: 2,
INFORMATION: 3,
};

const issueCodeReverseMap = {
0: "unknown",
1: "error",
2: "warning",
3: "notice",
};

// start of code score maps todo: use enums
Expand Down Expand Up @@ -65,17 +76,34 @@
}
}

const typeCode =
issueCodeMap[
issue.type ||
(issue.value &&
Array.isArray(issue.value) &&
issue.value.length &&
issue.value[0])
];

return {
context: context,
selector: selector,
code: issue.code,
type: issue.type,
typeCode: issueCodeMap[issue.type] || 0,
context: context || issue.snippet,
selector: selector || (issue.path && issue.path.dom),
code: issue.code || issue.ruleId,
type: issue.type || issueCodeReverseMap[typeCode],
typeCode: typeCode || 0,
message: issue.message,
runner: issue.runner || "kayle",
runner: issue.runner || issue.bounds ? "ace" : "kayle",
runnerExtras: issue.runnerExtras,
recurrence: issue.recurrence || 0,
clip,
clip:
clip || issue.bounds
? {
x: issue.bounds.left,
y: issue.bounds.top,
height: issue.bounds.height,
width: issue.bounds.width,
}
: undefined,
};
};

Expand Down Expand Up @@ -141,7 +169,7 @@
const isIssueNotIgnored = (issue) => {
return !options.ignore.some(
(element) =>
element === issue.type || element === issue.code.toLowerCase()
element === issue.type || element === issue.code?.toLowerCase()
);
};

Expand Down Expand Up @@ -179,7 +207,12 @@
const validateIssue = (issue) =>
(options.rootElement && !isElementInTestArea(issue.element)) ||
(options.hideElements && !isElementOutsideHiddenArea(issue.element)) ||
!isIssueNotIgnored(issue);
!isIssueNotIgnored(issue) ||
// IBM exclude errors - this check is quick but, we may want to look into conditional logic
(issue.value &&
Array.isArray(issue.value) &&
issue.value.length >= 2 &&
issue.value[1] === "PASS");

// get issues with acc builder return counter
const processIssues = (
Expand Down Expand Up @@ -270,33 +303,17 @@

// alt elements that require fixing
const missingAltIndexs = [];
// multiple runners found
const multiRunners = runnerIssues.length === 2;

// pre-allocate array if multi runners
const issues = new Array(
multiRunners
? runnerIssues[0].length + runnerIssues[1].length
: runnerIssues[0].length
);
const issues = new Array(runnerIssues.reduce((r, x) => r + x.length, 0));

const tracker = {
errorPointer: 0,
ic: 0,
};

// init index for runner
processIssues(
runnerIssues[0],
issues,
tracker, // init index
meta,
missingAltIndexs
);

// process second runner if found
if (multiRunners) {
processIssues(runnerIssues[1], issues, tracker, meta, missingAltIndexs);
for (const runnerIssue of runnerIssues) {
processIssues(runnerIssue, issues, tracker, meta, missingAltIndexs);
}

issues.length = tracker.ic;
Expand Down
53 changes: 53 additions & 0 deletions kayle/lib/runners/ace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const run = async (options) => {
return new Promise((resolve, reject) => {
if (
// @ts-ignore
typeof window.define === "function" &&
// @ts-ignore
window.define.amd &&
typeof window.require === "function"
) {
// @ts-ignore module load
window.require(["accessibility-checker-engine"], (ace) => {
Object.keys(ace).forEach((key) => {
window[key] = ace[key];
});
// @ts-ignore set the window runner
window.ace = ace;
});
}

// @ts-ignore
const checker = new ace.Checker();

checker
.check(
(options.rootElement &&
window.document.querySelector(options.rootElement)) ||
window.document,
["IBM_Accessibility"]
)
.then((report) => {
resolve(report.results);
});
});
};

const aceRunner = {
en: {
scripts: [require.resolve("accessibility-checker-engine/ace.js")],
run,
},
};

// // hard code locales to the list to htmlcs locales not EN
// const locales = ["fr", "es", "it", "ja", "nl", "pl", "zh_CN", "zh_TW"];

// for (const lang of locales) {
// ibmRunner[lang.replace("_", "-")] = {
// scripts: [require.resolve(`fast_htmlcs/build/HTMLCS.${lang}.js`)],
// run,
// };
// }

export { aceRunner };
4 changes: 3 additions & 1 deletion kayle/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kayle",
"version": "0.6.4",
"version": "0.7.0",
"description": "Extremely fast and accurate accessibility engine built for any headless tool like playwright or puppeteer.",
"main": "./build/index.js",
"keywords": [
Expand Down Expand Up @@ -35,6 +35,7 @@
"test:puppeteer": "npm run compile:test && node _tests/tests/basic.js",
"test:puppeteer:axe": "npm run compile:test && node _tests/tests/basic-axe.js",
"test:puppeteer:htmlcs": "npm run compile:test && node _tests/tests/basic-htmlcs.js",
"test:puppeteer:ace": "npm run compile:test && node _tests/tests/basic-ace.js",
"test:missing": "npm run compile:test && node _tests/tests/missing.js",
"test:playwright": "npm run compile:test && npx playwright test ./tests/basic-playwright.spec.ts",
"test:playwright:axe": "npm run compile:test && npx playwright test ./tests/basic-axe-playwright.spec.ts",
Expand All @@ -57,6 +58,7 @@
"bugs": "https://github.com/a11ywatch/kayle/issues",
"license": "MIT",
"dependencies": {
"accessibility-checker-engine": "3.1.61",
"fast_axecore": "workspace:*",
"fast_htmlcs": "workspace:*",
"kayle_innate": "workspace:*"
Expand Down
40 changes: 40 additions & 0 deletions kayle/tests/basic-ace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import assert from "assert";
import puppeteer from "puppeteer";
import { kayle } from "kayle";
import { drakeMock } from "./mocks/html-mock";
import { performance } from "perf_hooks";

(async () => {
const browser = await puppeteer.launch({ headless: "new" });
const page = await browser.newPage();
if (process.env.LOG_ENABLED) {
page.on("console", (msg) => console.log("PAGE LOG:", msg.text()));
}
const startTime = performance.now();
const { issues, pageUrl, documentTitle, meta, automateable } = await kayle({
page,
browser,
runners: ["ace"],
includeWarnings: true,
html: drakeMock,
origin: "https://www.drake.com", // origin is the fake url in place of the raw content
});
const nextTime = performance.now() - startTime;

console.log(issues);
console.log(meta);
console.log(automateable);
console.log("time took", nextTime);

// valid list
assert(Array.isArray(issues));
assert(meta.errorCount === 55);
assert(meta.warningCount === 42);
// TODO: IBM ACE accessibility error handling
// assert(meta.accessScore === 50);

assert(typeof pageUrl === "string");
assert(typeof documentTitle === "string");

await browser.close();
})();
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2100,6 +2100,13 @@ __metadata:
languageName: node
linkType: hard

"accessibility-checker-engine@npm:3.1.61":
version: 3.1.61
resolution: "accessibility-checker-engine@npm:3.1.61"
checksum: 08d5f4138c242e74a4516aee56c9b6550589d91ebce58873e38fb9272674e7fbb132c3bbbe69a71fc9b4fb445773e2dd57154e6a21b78574f0f19a10caf0c94a
languageName: node
linkType: hard

"acorn-jsx@npm:^5.0.0, acorn-jsx@npm:^5.3.2":
version: 5.3.2
resolution: "acorn-jsx@npm:5.3.2"
Expand Down Expand Up @@ -6104,6 +6111,7 @@ __metadata:
"@swc/helpers": ^0.5.1
"@types/jsdom": ^20.0.1
"@types/node": ^18.11.9
accessibility-checker-engine: 3.1.61
fast_axecore: "workspace:*"
fast_htmlcs: "workspace:*"
kayle_innate: "workspace:*"
Expand Down

0 comments on commit 1a77d38

Please sign in to comment.