Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8952)

Unified Diff: chrome/test/data/webui/test_api.js

Issue 11363170: Add an accessibility audit test for WebUI pages (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Working test for a11y audit Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/test/data/webui/test_api.js
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js
index 03c6721d51d55bf0baf4641caa2e6d9955c31802..dfa2f85ebe320431e0097aed3352e958c43e09b6 100644
--- a/chrome/test/data/webui/test_api.js
+++ b/chrome/test/data/webui/test_api.js
@@ -122,6 +122,18 @@ var testing = {};
extraLibraries: [],
/**
+ * FIXME(aboxhall)
+ */
+ runA11yChecks : true,
+
+ /**
+ * FIXME(aboxhall)
+ * Off by default to begin with; as we add the ability to suppress false
+ * positives, we will transition this to true.
+ */
+ a11yIssuesAreErrors: false,
+
+ /**
* Create a new class to handle |messageNames|, assign it to
* |this.mockHandler|, register its messages and return it.
* @return {Mock} Mock handler class assigned to |this.mockHandler|.
@@ -234,6 +246,8 @@ var testing = {};
function TestCase(name, fixture, body) {
this.name = name;
this.fixture = fixture;
+ this.runA11yChecks = fixture.runA11yChecks;
+ this.a11yIssuesAreErrors = fixture.a11yIssuesAreErrors;
this.body = body;
}
@@ -263,6 +277,13 @@ var testing = {};
*/
deferred_: false,
+ runA11yChecks: true,
+
+ /**
+ * FIXME(aboxhall)
+ */
+ a11yIssuesAreErrors: true,
+
/**
* Called at preload time, proxies to the fixture.
* @type {Function}
@@ -585,6 +606,21 @@ var testing = {};
var errors = [];
/**
+ * Hold the accessibility warnings and errors, respectively.
+ * Like errors, cleared when results are reported.
+ */
+ var a11y_warnings = [];
dmazzoni 2012/12/14 18:45:41 Use camelCase but make it a private variable with
aboxhall 2012/12/14 23:26:44 Done.
+ var a11y_errors = [];
+
+ function getA11yWarnings() {
dmazzoni 2012/12/14 18:45:41 Should you use js getters? http://stackoverflow.c
aboxhall 2012/12/14 23:26:44 It won't work in this case as it's not a property
+ return a11y_warnings;
+ };
+
+ function getA11yErrors() {
+ return a11y_errors;
+ };
+
+ /**
* URL to dummy WebUI page for testing framework.
* @type {string}
*/
@@ -607,6 +643,18 @@ var testing = {};
if (!testIsDone) {
testIsDone = true;
if (currentTestCase) {
+ if (currentTestCase.runA11yChecks) {
+ var a11yOk = runAccessibilityAudit(a11y_errors, a11y_warnings);
+ if (!a11yOk) {
+ if (currentTestCase.a11yIssuesAreErrors && result) {
+ result = [false, a11yIssuesToMessage(a11y_errors,
+ a11y_warnings,
+ result[1])];
+ } else
+ console.warn(a11yIssuesToMessage(a11y_errors, a11y_warnings));
+ }
+ }
+
try {
currentTestCase.tearDown();
} catch (e) {
@@ -616,10 +664,15 @@ var testing = {};
if (result)
result = [false, errorsToMessage([e], result[1])];
}
+ if (!result)
+ result = testResult();
currentTestCase = null;
}
- chrome.send('testResult', result ? result : testResult());
+ if (!result)
+ result = testResult();
+ chrome.send('testResult', result);
errors.splice(0, errors.length);
+ a11y_errors.splice(0, a11y_errors.length);
} else {
console.warn('testIsDone already');
}
@@ -652,8 +705,15 @@ var testing = {};
*/
function testResult(errorsOk) {
var result = [true, ''];
- if (errors.length) {
+ if (errors.length)
result = [!!errorsOk, errorsToMessage(errors)];
+
+ if (currentTestCase &&
+ currentTestCase.a11yIssuesAreErrors &&
+ (a11y_warnings.length || a11y_errors.length)) {
+ result = [!!errorsOk, a11yIssuesToMessage(a11y_errors,
+ a11y_warnings,
+ result[1])];
}
return result;
}
@@ -793,6 +853,117 @@ var testing = {};
}
/**
+ * Run an accessibility audit on the current page state.
+ * FIXME(aboxhall) documentation
+ * @type {Function}
+ * @return {boolean} Whether there were any errors or warnings
+ * @private
+ */
+ function runAccessibilityAudit(a11yErrors, a11yWarnings) {
+ var auditResults = axs.Audit.run();
+ for (var i = 0; i < auditResults.length; i++) {
+ var result = auditResults[i];
+ if (result.result == axs.constants.AuditResult.FAIL) {
dmazzoni 2012/12/14 18:45:41 result.result is confusing - i wonder if it should
aboxhall 2012/12/14 23:26:44 Or I could change result to auditResult? Changing
+ var auditRule = result.rule;
+ // TODO(aboxhall): more useful error messages (sadly non-trivial)
+ if (auditRule.severity == axs.constants.Severity.Severe)
+ a11yErrors.push(accessibilityErrorMessage(auditRule, result));
+ else
+ a11yWarnings.push(accessibilityErrorMessage(auditRule, result));
+ }
+ }
+
+ // TODO(aboxhall): have strict (no errors or warnings) vs non-strict
+ // (warnings ok)
+ // TODO(aboxhall): some kind of info logging for warnings only??
+ return (a11yErrors.length == 0 && a11yWarnings.length == 0);
+ }
+
+ function disableA11yChecks() {
+ if (!currentTestCase)
+ return;
+ currentTestCase.runA11yChecks = false;
+ }
+
+ function enableA11yChecks() {
+ if (!currentTestCase)
+ return;
+ currentTestCase.runA11yChecks = true;
+ }
+
+ function a11yIssuesAreErrors(flag) {
+ if (!currentTestCase)
+ return;
+ currentTestCase.a11yIssuesAreErrors = flag;
+ }
+
+ /**
+ * FIXME(aboxhall) documentation
+ */
+ function a11yIssuesToMessage(a11y_errors, a11y_warnings, message) {
dmazzoni 2012/12/14 18:45:41 It might be cleaner here to just have this functio
aboxhall 2012/12/14 23:26:44 I collapsed it into one line; hopefully that's a b
+ if (message)
+ message += '\n\n';
+ else
+ message = '\n';
+
+ message += 'An accessibility audit found ';
+
+ if (a11y_errors.length > 0) {
+ message += a11y_errors.length +
+ (a11y_errors.length == 1 ? ' error ' : ' errors ');
+ if (a11y_warnings.length > 0)
+ message += 'and ';
+ }
+ if (a11y_warnings.length > 0) {
+ message += a11y_warnings.length +
+ (a11y_warnings.length == 1 ? ' warning ' : ' warnings ');
+ }
+ message += 'on this page.\n';
+ message += 'For more information, please see ' +
+ 'https://sites.google.com/a/chromium.org/dev/webui-accessibility-audit';
dmazzoni 2012/12/14 18:45:41 This url is shorter and should be the same: http:
aboxhall 2012/12/14 23:26:44 Done.
+
+ for (var i = 0; i < a11y_errors.length; i++)
+ message += '\n\n' + a11y_errors[i];
+
+ for (var i = 0; i < a11y_warnings.length; i++)
+ message += '\n\n' + a11y_warnings[i];
+ return message;
+ }
+
+ /**
+ * FIXME(aboxhall): documentation
+ */
+ function accessibilityErrorMessage(rule, result) {
+ if (rule.severity == axs.constants.Severity.Severe)
+ var message = 'Error: '
+ else
+ var message = 'Warning: '
+ message += rule.name + ' failed on the following ' +
+ (result.elements.length == 1 ? 'element' : 'elements');
+
+ if (result.elements.length == 1)
+ message += ':'
+ else
+ message += ' (1 - ' + Math.min(5, result.elements.length) +
+ ' of ' + result.elements.length + '):';
+
+ for (var i = 0; i < Math.min(result.elements.length, 5); i++)
dmazzoni 2012/12/14 18:45:41 Do the Math.min just once
aboxhall 2012/12/14 23:26:44 Done.
+ message += '\n' + axs.utils.getQuerySelectorText(result.elements[i]);
+ return message;
+ }
+
+ /**
+ * FIXME(aboxhall) documentation
+ */
+ function assertAccessibilityOk() {
+ helper.registerCall();
+ var a11y_errors = [];
dmazzoni 2012/12/14 18:45:41 var a11yErrors (no underscores in js variables nor
aboxhall 2012/12/14 23:26:44 Done.
+ var a11y_warnings = [];
+ if (!runAccessibilityAudit(a11y_errors, a11y_warnings))
+ throw new Error(a11yIssuesToMessage(a11y_errors, a11y_warnings));
+ }
+
+ /**
* Creates a function based upon a function that thows an exception on
* failure. The new function stuffs any errors into the |errors| array for
* checking by runTest. This allows tests to continue running other checks,
@@ -1368,6 +1539,7 @@ var testing = {};
// Exports.
testing.Test = Test;
exports.testDone = testDone;
+ exports.a11yIssuesAreErrors = a11yIssuesAreErrors;
exports.assertTrue = assertTrue;
exports.assertFalse = assertFalse;
exports.assertGE = assertGE;
@@ -1377,9 +1549,12 @@ var testing = {};
exports.assertLT = assertLT;
exports.assertNotEquals = assertNotEquals;
exports.assertNotReached = assertNotReached;
+ exports.assertAccessibilityOk = assertAccessibilityOk;
exports.callFunction = callFunction;
exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs;
+ exports.disableA11yChecks = disableA11yChecks;
+ exports.enableA11yChecks = enableA11yChecks;
exports.expectTrue = createExpect(assertTrue);
exports.expectFalse = createExpect(assertFalse);
exports.expectGE = createExpect(assertGE);
@@ -1389,11 +1564,15 @@ var testing = {};
exports.expectLT = createExpect(assertLT);
exports.expectNotEquals = createExpect(assertNotEquals);
exports.expectNotReached = createExpect(assertNotReached);
+ exports.expectAccessibilityOk = createExpect(assertAccessibilityOk);
+ exports.getA11yErrors = getA11yErrors;
+ exports.getA11yWarnings = getA11yWarnings;
exports.preloadJavascriptLibraries = preloadJavascriptLibraries;
exports.registerMessageCallback = registerMessageCallback;
exports.registerMockGlobals = registerMockGlobals;
exports.registerMockMessageCallbacks = registerMockMessageCallbacks;
exports.resetTestState = resetTestState;
+ exports.runAccessibilityAudit = runAccessibilityAudit;
exports.runAllActions = runAllActions;
exports.runAllActionsAsync = runAllActionsAsync;
exports.runTest = runTest;
@@ -1402,6 +1581,7 @@ var testing = {};
exports.DUMMY_URL = DUMMY_URL;
exports.TEST = TEST;
exports.TEST_F = TEST_F;
+ exports.RUNTIME_TEST_F = TEST_F;
exports.GEN = GEN;
exports.GEN_INCLUDE = GEN_INCLUDE;
exports.WhenTestDone = WhenTestDone;

Powered by Google App Engine
This is Rietveld 408576698