Skip to content

Commit

Permalink
Merge pull request #2009 from IBMa/issue-2006
Browse files Browse the repository at this point in the history
fix(node|karma|cypress): Fix timeouts for large pages
  • Loading branch information
ErickRenteria authored Aug 27, 2024
2 parents 1f151da + 19f9112 commit b0e4ec2
Show file tree
Hide file tree
Showing 8 changed files with 351 additions and 58 deletions.
3 changes: 2 additions & 1 deletion accessibility-checker-engine/src/v4/api/IRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ export type Issue = RuleResult & {
ruleTime: number,
message: string,
bounds?: Bounds,
snippet: string
snippet: string,
level?: string
}

export type RuleContextHierarchy = { [namespace: string] : IMapResult[] };
Expand Down
207 changes: 201 additions & 6 deletions accessibility-checker/src-ts/lib/ACHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IConfigInternal } from "./common/config/IConfig";
import { ReporterManager } from "./common/report/ReporterManager";
import { existsSync, mkdirSync, writeFileSync } from "fs";
import { IAbstractAPI } from "./common/api-ext/IAbstractAPI";
import { IBaselineReport, IEngineReport } from "./common/engine/IReport";
import { EngineSummaryCounts, IBaselineReport, IEngineReport } from "./common/engine/IReport";
import { dirname, join, resolve as pathResolve } from "path";
import { BaselineManager, RefactorMap } from "./common/report/BaselineManager";

Expand Down Expand Up @@ -229,6 +229,50 @@ async function getComplianceHelperSelenium(label, parsed, curPol) : Promise<IChe
let scriptStr =
`let cb = arguments[arguments.length - 1];
try {
const valueToLevel = (reportValue) => {
let reportLevel;
if (reportValue[1] === "PASS") {
reportLevel = "pass";
}
else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") {
reportLevel = "manual";
}
else if (reportValue[0] === "VIOLATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "violation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialviolation";
}
}
else if (reportValue[0] === "RECOMMENDATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "recommendation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialrecommendation";
}
}
return reportLevel;
}
const getCounts = (engineReport) => {
let counts = {
violation: 0,
potentialviolation: 0,
recommendation: 0,
potentialrecommendation: 0,
manual: 0,
pass: 0
}
for (const issue of engineReport.results) {
++counts[issue.level];
}
return counts;
}
let policies = ${JSON.stringify(Config.policies)};
let checker = new window.ace_ibma.Checker();
Expand All @@ -238,7 +282,14 @@ setTimeout(function() {
checker.check(document, policies).then(function(report) {
for (const result of report.results) {
delete result.node;
result.level = valueToLevel(result.value)
}
report.summary ||= {};
report.summary.counts ||= getCounts(report);
let reportLevels = ${JSON.stringify((Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()))};
// Filter out pass results unless they asked for them in reports
// We don't want to mess with baseline functions, but pass results can break the response object
report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass");
cb(report);
})
},0)
Expand Down Expand Up @@ -291,22 +342,70 @@ async function getComplianceHelperWebDriverIO(label, parsed, curPol) : Promise<I
const startScan = Date.now();
// NOTE: Engine should already be loaded
const page = parsed;
let report : IEngineReport = await page.executeAsync(({ policies, customRulesets }, done) => {
let report : IEngineReport = await page.executeAsync(({ policies, customRulesets, reportLevels }, done) => {

const valueToLevel = (reportValue) => {
let reportLevel;
if (reportValue[1] === "PASS") {
reportLevel = "pass";
}
else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") {
reportLevel = "manual";
}
else if (reportValue[0] === "VIOLATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "violation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialviolation";
}
}
else if (reportValue[0] === "RECOMMENDATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "recommendation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialrecommendation";
}
}
return reportLevel;
}

const getCounts = (engineReport) => {
let counts: EngineSummaryCounts = {
violation: 0,
potentialviolation: 0,
recommendation: 0,
potentialrecommendation: 0,
manual: 0,
pass: 0
}
for (const issue of engineReport.results) {
++counts[issue.level];
}
return counts;
}

let checker = new (window as any).ace_ibma.Checker();
customRulesets.forEach((rs) => checker.addRuleset(rs));
return new Promise<Report>((resolve, reject) => {
setTimeout(function () {
checker.check(document, policies).then(function (report) {
for (const result of report.results) {
delete result.node;
result.level = valueToLevel(result.value)
}
report.summary ||= {};
report.summary.counts ||= getCounts(report);
// Filter out pass results unless they asked for them in reports
// We don't want to mess with baseline functions, but pass results can break the response object
report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass");
resolve(report);
done(report);
})
}, 0)
})
}, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets });
}, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets, reportLevels: (Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()) });
if (curPol != null && !checkPolicy) {
const valPolicies = ACEngineManager.customRulesets.map(rs => rs.id).concat(await page.execute(() => (new (window as any).ace_ibma.Checker().rulesetIds)));
checkPolicy = true;
Expand Down Expand Up @@ -347,21 +446,68 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise<ICh
const startScan = Date.now();
// NOTE: Engine should already be loaded
const page = parsed;
let report : IEngineReport = await page.evaluate(({ policies, customRulesets }) => {

let report : IEngineReport = await page.evaluate(({ policies, customRulesets, reportLevels }) => {
const valueToLevel = (reportValue) => {
let reportLevel;
if (reportValue[1] === "PASS") {
reportLevel = "pass";
}
else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") {
reportLevel = "manual";
}
else if (reportValue[0] === "VIOLATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "violation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialviolation";
}
}
else if (reportValue[0] === "RECOMMENDATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "recommendation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialrecommendation";
}
}
return reportLevel;
}

const getCounts = (engineReport) => {
let counts: EngineSummaryCounts = {
violation: 0,
potentialviolation: 0,
recommendation: 0,
potentialrecommendation: 0,
manual: 0,
pass: 0
}
for (const issue of engineReport.results) {
++counts[issue.level];
}
return counts;
}

let checker = new (window as any).ace_ibma.Checker();
customRulesets.forEach((rs) => checker.addRuleset(rs));
return new Promise<Report>((resolve, reject) => {
setTimeout(function () {
checker.check(document, policies).then(function (report) {
for (const result of report.results) {
delete result.node;
result.level = valueToLevel(result.value)
}
report.summary ||= {};
report.summary.counts ||= getCounts(report);
// Filter out pass results unless they asked for them in reports
// We don't want to mess with baseline functions, but pass results can break the response object
report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass");
resolve(report);
})
}, 0)
})
}, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets });
}, { policies: Config.policies, customRulesets: ACEngineManager.customRulesets, reportLevels: (Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString()) });
if (curPol != null && !checkPolicy) {
const valPolicies = ACEngineManager.customRulesets.map(rs => rs.id).concat(await page.evaluate("new window.ace_ibma.Checker().rulesetIds"));
checkPolicy = true;
Expand Down Expand Up @@ -399,14 +545,63 @@ async function getComplianceHelperPuppeteer(label, parsed, curPol) : Promise<ICh

async function getComplianceHelperLocal(label, parsed, curPol) : Promise<ICheckerResult> {
try {
const valueToLevel = (reportValue) => {
let reportLevel;
if (reportValue[1] === "PASS") {
reportLevel = "pass";
}
else if ((reportValue[0] === "VIOLATION" || reportValue[0] === "RECOMMENDATION") && reportValue[1] === "MANUAL") {
reportLevel = "manual";
}
else if (reportValue[0] === "VIOLATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "violation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialviolation";
}
}
else if (reportValue[0] === "RECOMMENDATION") {
if (reportValue[1] === "FAIL") {
reportLevel = "recommendation";
}
else if (reportValue[1] === "POTENTIAL") {
reportLevel = "potentialrecommendation";
}
}
return reportLevel;
}

const getCounts = (engineReport) => {
let counts: EngineSummaryCounts = {
violation: 0,
potentialviolation: 0,
recommendation: 0,
potentialrecommendation: 0,
manual: 0,
pass: 0
}
for (const issue of engineReport.results) {
++counts[issue.level];
}
return counts;
}

let startScan = Date.now();
let checker = ACEngineManager.getChecker();
ACEngineManager.customRulesets.forEach((rs) => checker.addGuideline(rs));
let report : IEngineReport = await checker.check(parsed, Config.policies)
.then(function (report) {
for (const result of report.results) {
delete result.node;
result.level = valueToLevel(result.value)
}
report.summary ||= {};
report.summary.counts ||= getCounts(report);
let reportLevels = (Config.reportLevels || []).concat(Config.failLevels || []).map(lvl => lvl.toString());
// Filter out pass results unless they asked for them in reports
// We don't want to mess with baseline functions, but pass results can break the response object
report.results = report.results.filter(result => reportLevels.includes(result.level) || result.level !== "pass");
return report;
})

Expand Down
41 changes: 28 additions & 13 deletions common/module/src/engine/IReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export type IEngineReport = {
[ruleId: string]: {
[reasonId: string]: string
}
},
summary?: {
counts?: EngineSummaryCounts
}
}

Expand All @@ -76,6 +79,28 @@ export type IBaselineResult = IEngineResult & {
level: eRuleLevel
}

export type EngineSummaryCounts = {
violation: number,
potentialviolation: number,
recommendation: number,
potentialrecommendation: number,
manual: number,
pass: number
}

export type SummaryCounts = {
violation: number,
potentialviolation: number,
recommendation: number,
potentialrecommendation: number,
manual: number,
pass: number,
ignored: number,
elements: number,
elementsViolation: number,
elementsViolationReview: number
}

export type IBaselineReport = {
results: IBaselineResult[]
numExecuted: number,
Expand All @@ -85,18 +110,7 @@ export type IBaselineReport = {
}
}
summary: {
counts: {
violation: number,
potentialviolation: number,
recommendation: number,
potentialrecommendation: number,
manual: number,
pass: number,
ignored: number,
elements: number,
elementsViolation: number,
elementsViolationReview: number
}
counts: SummaryCounts,
scanTime: number,
ruleArchive: string
policies: string[]
Expand All @@ -120,7 +134,8 @@ export type CompressedReport = [
string, // ruleArchive
string[], // policies
string[], // reportLevels
CompressedIssue[]
CompressedIssue[],
SummaryCounts
]

export type CompressedIssue = [ // results
Expand Down
3 changes: 2 additions & 1 deletion common/module/src/engine/IRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ export type Issue = RuleResult & {
ruleTime: number,
message: string,
bounds?: Bounds,
snippet: string
snippet: string,
level?: string
}

export type RuleContextHierarchy = { [namespace: string] : IMapResult[] };
Expand Down
Loading

0 comments on commit b0e4ec2

Please sign in to comment.