| 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..61d459a14eded0a9a2984dcc6781ae76845ac149 100644
|
| --- a/chrome/test/data/webui/test_api.js
|
| +++ b/chrome/test/data/webui/test_api.js
|
| @@ -122,6 +122,66 @@ var testing = {};
|
| extraLibraries: [],
|
|
|
| /**
|
| + * Whether to run the accessibility checks.
|
| + * @type {boolean}
|
| + */
|
| + runAccessibilityChecks : true,
|
| +
|
| + /**
|
| + * Whether to treat accessibility issues (errors or warnings) as test
|
| + * failures. If true, any accessibility issues will cause the test to fail.
|
| + * If false, accessibility issues will cause a console.warn.
|
| + * Off by default to begin with; as we add the ability to suppress false
|
| + * positives, we will transition this to true.
|
| + * @type {boolean}
|
| + */
|
| + accessibilityIssuesAreErrors: false,
|
| +
|
| + /**
|
| + * Holds any accessibility errors found during the accessibility audit.
|
| + * @type {Array.<string>}
|
| + */
|
| + a11yErrors_: [],
|
| +
|
| + /**
|
| + * Holds any accessibility warnings found during the accessibility audit.
|
| + * @type {Array.<string>}
|
| + */
|
| + a11yWarnings_: [],
|
| +
|
| + /**
|
| + * Gets the list of accessibility errors found during the accessibility
|
| + * audit. Only for use in testing.
|
| + * @return {Array.<string>}
|
| + */
|
| + getAccessibilityErrors: function() {
|
| + return this.a11yErrors_;
|
| + },
|
| +
|
| + /**
|
| + * Gets the list of accessibility warnings found during the accessibility
|
| + * audit. Only for use in testing.
|
| + * @return {Array.<string>}
|
| + */
|
| + getAccessibilityWarnings: function() {
|
| + return this.a11yWarnings_;
|
| + },
|
| +
|
| + /**
|
| + * Run accessibility checks after this test completes.
|
| + */
|
| + enableAccessibilityChecks: function() {
|
| + this.runAccessibilityChecks = true;
|
| + },
|
| +
|
| + /**
|
| + * Don't run accessibility checks after this test completes.
|
| + */
|
| + disableAccessibilityChecks: function() {
|
| + this.runAccessibilityChecks = 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|.
|
| @@ -178,6 +238,24 @@ var testing = {};
|
| },
|
|
|
| /**
|
| + * Called to run the accessibility audit from the perspective of this
|
| + * fixture.
|
| + */
|
| + runAccessibilityAudit: function() {
|
| + if (!this.runAccessibilityChecks || typeof document === 'undefined')
|
| + return;
|
| +
|
| + if (!runAccessibilityAudit(this.a11yErrors_, this.a11yWarnings_)) {
|
| + var report = accessibilityAuditReport(this.a11yErrors_,
|
| + this.a11yWarnings_);
|
| + if (this.accessibilityIssuesAreErrors)
|
| + throw new Error(report);
|
| + else
|
| + console.warn(report);
|
| + }
|
| + },
|
| +
|
| + /**
|
| * Create a closure function for continuing the test at a later time. May be
|
| * used as a listener function.
|
| * @param {WhenTestDone} whenTestDone Call testDone() at the appropriate
|
| @@ -297,6 +375,14 @@ var testing = {};
|
| },
|
|
|
| /**
|
| + * Called after a test is run (in testDone) to test accessibility.
|
| + */
|
| + runAccessibilityAudit: function() {
|
| + if (this.fixture)
|
| + this.fixture.runAccessibilityAudit();
|
| + },
|
| +
|
| + /**
|
| * Runs this test case with |this| set to the |fixture|.
|
| *
|
| * Note: Tests created with TEST_F may depend upon |this| being set to an
|
| @@ -607,18 +693,20 @@ var testing = {};
|
| if (!testIsDone) {
|
| testIsDone = true;
|
| if (currentTestCase) {
|
| - try {
|
| - currentTestCase.tearDown();
|
| - } catch (e) {
|
| - // Caught an exception in tearDown; Register the error and recreate
|
| - // the result if it is passed in.
|
| - errors.push(e);
|
| - if (result)
|
| - result = [false, errorsToMessage([e], result[1])];
|
| - }
|
| + var ok = true;
|
| + ok = createExpect(currentTestCase.runAccessibilityAudit.bind(
|
| + currentTestCase)).call(null) && ok;
|
| + ok = createExpect(currentTestCase.tearDown.bind(
|
| + currentTestCase)).call(null) && ok;
|
| +
|
| + if (!ok && result)
|
| + result = [false, errorsToMessage(errors, result[1])];
|
| +
|
| 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 +740,9 @@ var testing = {};
|
| */
|
| function testResult(errorsOk) {
|
| var result = [true, ''];
|
| - if (errors.length) {
|
| + if (errors.length)
|
| result = [!!errorsOk, errorsToMessage(errors)];
|
| - }
|
| +
|
| return result;
|
| }
|
|
|
| @@ -793,6 +881,110 @@ var testing = {};
|
| }
|
|
|
| /**
|
| + * Run an accessibility audit on the current page state.
|
| + * @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 auditResult = auditResults[i];
|
| + if (auditResult.result == axs.constants.AuditResult.FAIL) {
|
| + var auditRule = auditResult.rule;
|
| + // TODO(aboxhall): more useful error messages (sadly non-trivial)
|
| + if (auditRule.severity == axs.constants.Severity.Severe)
|
| + a11yErrors.push(accessibilityErrorMessage(auditRule, auditResult));
|
| + else
|
| + a11yWarnings.push(accessibilityErrorMessage(auditRule, auditResult));
|
| + }
|
| + }
|
| +
|
| + // 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);
|
| + }
|
| +
|
| + /**
|
| + * Concatenates the accessibility error messages in |a11yErrors| and
|
| + * |a11yWarnings| in to an accessibility report, appends it to the given
|
| + * |message| and returns the resulting message string.
|
| + * @param {Array.<string>} a11yErrors The list of accessibility error messages
|
| + * @param {Array.<string>} a11yWarnings The list of accessibility warning
|
| + * messages.
|
| + * @return {string} |message| + accessibility report.
|
| + */
|
| + function accessibilityAuditReport(a11yErrors, a11yWarnings, message) {
|
| + message = message ? message + '\n' : '';
|
| + message += '\n*** Begin accessibility audit results ***';
|
| + message += '\nAn accessibility audit found ';
|
| +
|
| + if (a11yErrors.length > 0) {
|
| + message += a11yErrors.length +
|
| + (a11yErrors.length == 1 ? ' error ' : ' errors ');
|
| + if (a11yWarnings.length > 0)
|
| + message += 'and ';
|
| + }
|
| + if (a11yWarnings.length > 0) {
|
| + message += a11yWarnings.length +
|
| + (a11yWarnings.length == 1 ? ' warning ' : ' warnings ');
|
| + }
|
| + message += 'on this page.\n';
|
| + message += 'For more information, please see ' +
|
| + 'http://chromium.org/developers/accessibility/webui-accessibility-audit';
|
| +
|
| + for (var i = 0; i < a11yErrors.length; i++)
|
| + message += '\n\n' + a11yErrors[i];
|
| +
|
| + for (var i = 0; i < a11yWarnings.length; i++)
|
| + message += '\n\n' + a11yWarnings[i];
|
| + message += '\n*** End accessibility audit results ***';
|
| + return message;
|
| + }
|
| +
|
| + /**
|
| + * Creates an error message for a given accessibility audit rule and
|
| + * corresponding result.
|
| + * @param {axs.AuditRule} rule The audit rule which the result is for
|
| + * @param {Object.<string, (string|Array.<Element>)>} result The result
|
| + * object returned from the audit.
|
| + * @return {string} An error message describing the failure and listing
|
| + * up to five elements which failed the audit rule.
|
| + */
|
| + 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 + '):';
|
| + }
|
| +
|
| + var maxElements = Math.min(result.elements.length, 5);
|
| + for (var i = 0; i < maxElements; i++)
|
| + message += '\n' + axs.utils.getQuerySelectorText(result.elements[i]);
|
| + return message;
|
| + }
|
| +
|
| + /**
|
| + * Asserts that the current page state passes the accessibility audit.
|
| + */
|
| + function assertAccessibilityOk() {
|
| + helper.registerCall();
|
| + var a11yErrors = [];
|
| + var a11yWarnings = [];
|
| + if (!runAccessibilityAudit(a11yErrors, a11yWarnings))
|
| + throw new Error(accessibilityAuditReport(a11yErrors, a11yWarnings));
|
| + }
|
| +
|
| + /**
|
| * 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,
|
| @@ -1377,6 +1569,7 @@ var testing = {};
|
| exports.assertLT = assertLT;
|
| exports.assertNotEquals = assertNotEquals;
|
| exports.assertNotReached = assertNotReached;
|
| + exports.assertAccessibilityOk = assertAccessibilityOk;
|
| exports.callFunction = callFunction;
|
| exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
|
| exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs;
|
| @@ -1389,11 +1582,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 +1597,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;
|
|
|