UNPKG

accessibility-checker

Version:

An automated testing tools for accessibility testing using Puppeteer, Selenium, or Zombie

348 lines (345 loc) 16.6 kB
#!/usr/bin/env node "use strict"; /****************************************************************************** Copyright:: 2020- IBM, Inc Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *****************************************************************************/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; var aChecker = require("../index.js"); var fs = require('fs'); var readline = require('readline'); var path = require("path"); var validCLParams = [ "inputFile" ]; var splitCLParams = [ "policies", "failLevels", "reportLevels", "outputFormat", "label" ]; function processCommandLine(ACConfig) { var _a = process.argv, args = _a.slice(2); var lastArg = null; var lastFlag = null; for (var _i = 0, args_1 = args; _i < args_1.length; _i++) { var arg = args_1[_i]; if (arg.match(/^--.*$/)) { lastFlag = arg.substring(2); lastArg = null; } else if (lastFlag) { if (lastFlag in ACConfig || validCLParams.includes(lastFlag)) { if (splitCLParams.includes(lastFlag)) { arg = arg.split(","); } ACConfig[lastFlag] = arg; } lastFlag = lastArg = null; } else { lastArg = arg; } } if (lastArg) { ACConfig.inputFile = lastArg; } } function getFiles(dir) { return __awaiter(this, void 0, void 0, function () { var retVal, _i, _a, f, _b, _c; return __generator(this, function (_d) { switch (_d.label) { case 0: retVal = []; _i = 0, _a = fs.readdirSync(dir); _d.label = 1; case 1: if (!(_i < _a.length)) return [3 /*break*/, 6]; f = _a[_i]; if (!(f[0] === ".")) return [3 /*break*/, 2]; return [3 /*break*/, 5]; case 2: f = path.join(dir, f); if (!fs.lstatSync(f).isDirectory()) return [3 /*break*/, 4]; _c = (_b = retVal).concat; return [4 /*yield*/, getFiles(f)]; case 3: retVal = _c.apply(_b, [_d.sent()]); return [3 /*break*/, 5]; case 4: if (f.endsWith(".htm") || f.endsWith(".html")) { retVal.push(f); } _d.label = 5; case 5: _i++; return [3 /*break*/, 1]; case 6: return [2 /*return*/, retVal]; } }); }); } function showHelp(config) { return __awaiter(this, void 0, void 0, function () { var lastArg, archiveInfo, _i, _a, archive, _b, _c, policy; return __generator(this, function (_d) { lastArg = config.inputFile; if (!lastArg || lastArg === "help") { console.log("Usage: achecker [flags] [command / file / directory / URL]\n\nCommands:\n archives : Display valid archive ids and policy ids\n\nFlags:\n Flags can be set via .achecker.yml or aceconfig.js files. Specifying the flags here\n will override those options.\n\n --ruleArchive : Archive id to use. Run \"achecker archives\" for valid ids\n --policies : Comma separated list of policies. Run \"achecker archives\"\n for valid ids\n --failLevels : Comma separated list of levels that will indicate\n a failure. Valid values: violation,\n potentialviolation, recommendation,\n potentialrecommendation, manual\n --reportLevels : Comma separated list of levels that will be included\n in reports. Valid values: violation,\n potentialviolation, recommendation,\n potentialrecommendation, manual, pass\n --outputFormat : Comma separated list of output report formats.\n Valid values: json, csv, xlsx, or html\n --label : Comma separated list of labels to include in reports\n --outputFolder : Folder to output results and reports\n --baselineFolder : Folder that includes baseline files\n"); process.exit(-1); } else if (lastArg === "archives") { archiveInfo = { "latest": [] }; console.log(); console.log("Archive [Archive Id]"); console.log(" - Policy [Policy Id]:"); console.log("-----------------------"); console.log(); for (_i = 0, _a = config.ruleArchiveSet; _i < _a.length; _i++) { archive = _a[_i]; if (archive.sunset) continue; console.log("".concat(archive.name, " [").concat(archive.id, "]")); for (_b = 0, _c = archive.policies; _b < _c.length; _b++) { policy = _c[_b]; console.log(" - ".concat(policy.name, " [").concat(policy.id, "]")); } archiveInfo[archive.id] = archive.policies; if (archive.latest) { archiveInfo['latest'] = archiveInfo[archive.id]; } } process.exit(-1); } return [2 /*return*/]; }); }); } function getInputFileList() { var _a, e_1, _b, _c; return __awaiter(this, void 0, void 0, function () { var config, inputs, filename, fileStream, rl, _d, rl_1, rl_1_1, line, e_1_1, retVal, _i, inputs_1, input, isDirectory, _e, _f; return __generator(this, function (_g) { switch (_g.label) { case 0: return [4 /*yield*/, aChecker.getConfig()]; case 1: config = _g.sent(); processCommandLine(config); return [4 /*yield*/, showHelp(config)]; case 2: _g.sent(); inputs = []; filename = config.inputFile.trim(); if (!filename.endsWith(".txt")) return [3 /*break*/, 15]; fileStream = fs.createReadStream(filename); rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity }); _g.label = 3; case 3: _g.trys.push([3, 8, 9, 14]); _d = true, rl_1 = __asyncValues(rl); _g.label = 4; case 4: return [4 /*yield*/, rl_1.next()]; case 5: if (!(rl_1_1 = _g.sent(), _a = rl_1_1.done, !_a)) return [3 /*break*/, 7]; _c = rl_1_1.value; _d = false; try { line = _c; if (line.trim().length === 0) { } else if (line.startsWith(path.sep)) { inputs.push(line); } else if (line.match(/[a-z]{4,5}:\/\//)) { inputs.push(line); } else { inputs.push(path.join(path.dirname(filename), line)); } } finally { _d = true; } _g.label = 6; case 6: return [3 /*break*/, 4]; case 7: return [3 /*break*/, 14]; case 8: e_1_1 = _g.sent(); e_1 = { error: e_1_1 }; return [3 /*break*/, 14]; case 9: _g.trys.push([9, , 12, 13]); if (!(!_d && !_a && (_b = rl_1.return))) return [3 /*break*/, 11]; return [4 /*yield*/, _b.call(rl_1)]; case 10: _g.sent(); _g.label = 11; case 11: return [3 /*break*/, 13]; case 12: if (e_1) throw e_1.error; return [7 /*endfinally*/]; case 13: return [7 /*endfinally*/]; case 14: return [3 /*break*/, 16]; case 15: inputs = [filename]; _g.label = 16; case 16: retVal = []; _i = 0, inputs_1 = inputs; _g.label = 17; case 17: if (!(_i < inputs_1.length)) return [3 /*break*/, 21]; input = inputs_1[_i]; isDirectory = false; try { isDirectory = fs.lstatSync(input).isDirectory(); } catch (e) { } if (!isDirectory) return [3 /*break*/, 19]; _f = (_e = retVal).concat; return [4 /*yield*/, getFiles(input)]; case 18: retVal = _f.apply(_e, [_g.sent()]); return [3 /*break*/, 20]; case 19: retVal.push(input); _g.label = 20; case 20: _i++; return [3 /*break*/, 17]; case 21: return [2 /*return*/, retVal]; } }); }); } // Prepare the configuration getInputFileList().then(function (rptInputFiles) { return __awaiter(void 0, void 0, void 0, function () { var idx, failures, errors, _i, rptInputFiles_1, f, result, isFile, _a, failures_1, fail; return __generator(this, function (_b) { switch (_b.label) { case 0: idx = 0; failures = []; errors = 0; _i = 0, rptInputFiles_1 = rptInputFiles; _b.label = 1; case 1: if (!(_i < rptInputFiles_1.length)) return [3 /*break*/, 7]; f = rptInputFiles_1[_i]; result = void 0; isFile = false; try { isFile = fs.lstatSync(f).isFile(); f = path.resolve(f); } catch (e) { } if (!isFile) return [3 /*break*/, 3]; return [4 /*yield*/, aChecker.getCompliance("file://" + f, f.replace(/^file:\/\//, "").replace(/[:?&=]/g, "_"))]; case 2: result = _b.sent(); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, aChecker.getCompliance(f, f.replace(/^(https?:|file:)\/\//, "").replace(/[:?&=]/g, "_"))]; case 4: result = _b.sent(); _b.label = 5; case 5: if (result) { if (aChecker.assertCompliance(result.report) === 0) { console.log("Passed:", f); } else { failures.push({ file: f, report: result.report }); console.log("Failed:", f); } } else { ++errors; console.log("Error:", f); } _b.label = 6; case 6: _i++; return [3 /*break*/, 1]; case 7: if (failures.length > 0) { console.log(); console.log("Failing scan details:"); console.log(); for (_a = 0, failures_1 = failures; _a < failures_1.length; _a++) { fail = failures_1[_a]; console.log(aChecker.stringifyResults(fail.report)); } } console.log(); console.log("".concat(rptInputFiles.length - failures.length - errors, " of ").concat(rptInputFiles.length, " passed.")); return [4 /*yield*/, aChecker.close()]; case 8: _b.sent(); if (failures.length !== 0 || errors !== 0) { process.exitCode = 1; } return [2 /*return*/]; } }); }); }); //# sourceMappingURL=achecker.js.map