| 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..fbe5640a5a9f6b80ecf31be64717a2a24480288e 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,13 @@ var testing = {};
|
| var errors = [];
|
|
|
| /**
|
| + * Hold the accessibility warnings and errors, respectively.
|
| + * Like errors, cleared when results are reported.
|
| + */
|
| + var a11y_warnings = [];
|
| + var a11y_errors = [];
|
| +
|
| + /**
|
| * URL to dummy WebUI page for testing framework.
|
| * @type {string}
|
| */
|
| @@ -607,6 +635,20 @@ var testing = {};
|
| if (!testIsDone) {
|
| testIsDone = true;
|
| if (currentTestCase) {
|
| + if (currentTestCase.runA11yChecks &&
|
| + !runAccessibilityAudit_(a11y_errors, a11y_warnings)) {
|
| + if (currentTestCase.a11yIssuesAreErrors) {
|
| + if (!result)
|
| + result = testResult();
|
| + result = [false, accessibilityErrorsToMessage(a11y_errors,
|
| + a11y_warnings,
|
| + result[1])];
|
| + } else { /* a11yIssuesAreErrors */
|
| + console.warn(accessibilityErrorsToMessage(a11y_errors,
|
| + a11y_warnings));
|
| + }
|
| + }
|
| +
|
| try {
|
| currentTestCase.tearDown();
|
| } catch (e) {
|
| @@ -618,7 +660,9 @@ var testing = {};
|
| }
|
| currentTestCase = null;
|
| }
|
| - chrome.send('testResult', result ? result : testResult());
|
| + if (!result)
|
| + result = testResult();
|
| + chrome.send('testResult', result);
|
| errors.splice(0, errors.length);
|
| } else {
|
| console.warn('testIsDone already');
|
| @@ -652,9 +696,9 @@ var testing = {};
|
| */
|
| function testResult(errorsOk) {
|
| var result = [true, ''];
|
| - if (errors.length) {
|
| + if (errors.length)
|
| result = [!!errorsOk, errorsToMessage(errors)];
|
| - }
|
| +
|
| return result;
|
| }
|
|
|
| @@ -792,6 +836,126 @@ var testing = {};
|
| throw new Error(helper.getCallMessage(message));
|
| }
|
|
|
| + 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 accessibilityErrorsToMessage(a11y_errors, a11y_warnings, message) {
|
| + 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';
|
| + if (!currentTestCase.a11yIssuesAreErrors) {
|
| + message += 'These are currently for information only, but will become ' +
|
| + 'errors at a later date.\n'
|
| + }
|
| + message += 'For more information, please see ' +
|
| + 'https://sites.google.com/a/chromium.org/dev/webui-accessibility-audit';
|
| +
|
| + 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++)
|
| + message += '\n' + axs.utils.getQuerySelectorText(result.elements[i]);
|
| + return message;
|
| + }
|
| +
|
| + /**
|
| + * FIXME(aboxhall) documentation
|
| + */
|
| + function assertAccessibilityOk() {
|
| + helper.registerCall();
|
| + var a11y_errors = [];
|
| + var a11y_warnings = [];
|
| + if (!runAccessibilityAudit_(a11y_errors, a11y_warnings))
|
| + throw new Error(accessibilityErrorsToMessage(a11y_errors,
|
| + a11y_warnings));
|
| + }
|
| +
|
| + /**
|
| + * 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) {
|
| + for (var auditRuleName in axs.AuditRule.specs) {
|
| + var auditRule = axs.AuditRules.getRule(auditRuleName);
|
| + if (!auditRule)
|
| + continue; // Shouldn't happen, but fail silently if it does.
|
| +
|
| + if (auditRule.disabled || auditRule.requiresConsoleAPI)
|
| + continue;
|
| +
|
| + var result = auditRule.run();
|
| + if (result.result == axs.constants.AuditResult.FAIL) {
|
| + // 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);
|
| + }
|
| +
|
| /**
|
| * Creates a function based upon a function that thows an exception on
|
| * failure. The new function stuffs any errors into the |errors| array for
|
| @@ -1368,6 +1532,7 @@ var testing = {};
|
| // Exports.
|
| testing.Test = Test;
|
| exports.testDone = testDone;
|
| + exports.a11yIssuesAreErrors = a11yIssuesAreErrors;
|
| exports.assertTrue = assertTrue;
|
| exports.assertFalse = assertFalse;
|
| exports.assertGE = assertGE;
|
| @@ -1377,9 +1542,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 +1557,13 @@ var testing = {};
|
| exports.expectLT = createExpect(assertLT);
|
| exports.expectNotEquals = createExpect(assertNotEquals);
|
| exports.expectNotReached = createExpect(assertNotReached);
|
| + exports.expectAccessibilityOk = createExpect(assertAccessibilityOk);
|
| 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 +1572,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;
|
|
|