Chromium Code Reviews| 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..a9fa4556c8ba695b8f0591a64765bdcfa56fa760 100644 |
| --- a/chrome/test/data/webui/test_api.js |
| +++ b/chrome/test/data/webui/test_api.js |
| @@ -122,6 +122,22 @@ 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, |
| + |
| + /** |
| * 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 +250,8 @@ var testing = {}; |
| function TestCase(name, fixture, body) { |
| this.name = name; |
| this.fixture = fixture; |
| + this.runAccessibilityChecks = fixture.runAccessibilityChecks; |
| + this.accessibilityIssuesAreErrors = fixture.accessibilityIssuesAreErrors; |
| this.body = body; |
| } |
| @@ -264,6 +282,24 @@ var testing = {}; |
| deferred_: false, |
| /** |
| + * @see Test.runAccessibilityChecks |
| + * TestCase-specific value for |Test.runAccessibilityChecks|. This allows an |
| + * individual test case to override the value in the test fixture, using |
| + * enableAccessibilityChecks() or disableAccessibilityChecks(). |
| + * @type {boolean} |
| + */ |
| + runAccessibilityChecks: true, |
| + |
| + /** |
| + * @see Test.accessibilityIssuesAreErrors |
| + * TestCase-specific value for |Test.accessibilityIssuesAreErrors|. This |
| + * allows an individual test case to override the value in the test |
| + * fixture, using accessibilityIssuesAreErrors(flag). |
| + * @type {boolean} |
| + */ |
| + accessibilityIssuesAreErrors: true, |
| + |
| + /** |
| * Called at preload time, proxies to the fixture. |
| * @type {Function} |
| */ |
| @@ -585,6 +621,38 @@ var testing = {}; |
| var errors = []; |
| /** |
| + * Holds any accessibility errors found during the accessibility audit. |
| + * Like |errors|, cleared when results are reported. |
| + * @type {Array.<string>} |
| + */ |
| + var a11yErrors_ = []; |
| + |
| + /** |
| + * Holds any accessibility warnings found during the accessibility audit. |
| + * Like |errors|, cleared when results are reported. |
| + * @type {Array.<string>} |
| + */ |
| + var a11yWarnings_ = []; |
| + |
| + /** |
| + * Gets the list of accessibility errors found during the accessibility |
| + * audit. Only for use in testing. |
| + * @return {Array.<string>} |
| + */ |
| + function getAccessibilityErrors() { |
| + return a11yErrors_; |
| + }; |
| + |
| + /** |
| + * Gets the list of accessibility warnings found during the accessibility |
| + * audit. Only for use in testing. |
| + * @return {Array.<string>} |
| + */ |
| + function getAccessibilityWarnings() { |
| + return a11yWarnings_; |
| + }; |
| + |
| + /** |
| * URL to dummy WebUI page for testing framework. |
| * @type {string} |
| */ |
| @@ -607,6 +675,22 @@ var testing = {}; |
| if (!testIsDone) { |
| testIsDone = true; |
| if (currentTestCase) { |
| + if (currentTestCase.runAccessibilityChecks) { |
| + var a11yOk = runAccessibilityAudit(a11yErrors_, a11yWarnings_); |
| + if (!a11yOk) { |
| + if (currentTestCase.accessibilityIssuesAreErrors && result) { |
| + result = [false, accessibilityAuditReport(a11yErrors_, |
| + a11yWarnings_, |
| + result[1])]; |
| + } else { |
| + console.warn(accessibilityAuditReport(a11yErrors_, |
| + a11yWarnings_)); |
| + } |
| + } |
| + } |
| + |
| + if (result) |
| + errors.splice(0, errors.length); |
| try { |
| currentTestCase.tearDown(); |
| } catch (e) { |
| @@ -616,10 +700,21 @@ var testing = {}; |
| if (result) |
| result = [false, errorsToMessage([e], result[1])]; |
| } |
| + if (!result) |
| + result = testResult(); |
| + else if (errors.length) { |
| + // Add errors generated in tearDown |
| + 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); |
| + a11yErrors_.splice(0, a11yErrors_.length); |
| + a11yWarnings_.splice(0, a11yWarnings_.length); |
| } else { |
| console.warn('testIsDone already'); |
| } |
| @@ -652,8 +747,15 @@ var testing = {}; |
| */ |
| function testResult(errorsOk) { |
| var result = [true, '']; |
| - if (errors.length) { |
| + if (errors.length) |
| result = [!!errorsOk, errorsToMessage(errors)]; |
| + |
| + if (currentTestCase && |
| + currentTestCase.accessibilityIssuesAreErrors && |
| + (a11yWarnings_.length || a11yErrors_.length)) { |
| + result = [!!errorsOk, accessibilityAuditReport(a11yErrors_, |
| + a11yWarnings_, |
| + result[1])]; |
| } |
| return result; |
| } |
| @@ -793,6 +895,127 @@ 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); |
| + } |
| + |
| + function disableAccessibilityChecks() { |
| + if (!currentTestCase) |
| + return; |
| + currentTestCase.runAccessibilityChecks = false; |
| + } |
| + |
| + function enableAccessibilityChecks() { |
| + if (!currentTestCase) |
| + return; |
| + currentTestCase.runAccessibilityChecks = true; |
| + } |
| + |
| + function accessibilityIssuesAreErrors(flag) { |
| + if (!currentTestCase) |
| + return; |
| + currentTestCase.accessibilityIssuesAreErrors = flag; |
| + } |
| + |
| + /** |
| + * 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, |
| @@ -1368,6 +1591,7 @@ var testing = {}; |
| // Exports. |
| testing.Test = Test; |
| exports.testDone = testDone; |
| + exports.accessibilityIssuesAreErrors = accessibilityIssuesAreErrors; |
| exports.assertTrue = assertTrue; |
| exports.assertFalse = assertFalse; |
| exports.assertGE = assertGE; |
| @@ -1377,9 +1601,12 @@ var testing = {}; |
| exports.assertLT = assertLT; |
| exports.assertNotEquals = assertNotEquals; |
| exports.assertNotReached = assertNotReached; |
| + exports.assertAccessibilityOk = assertAccessibilityOk; |
|
dmazzoni
2012/12/20 22:05:06
Nit: sort alphabetically
aboxhall
2012/12/20 23:01:41
I agree in principle, but they're actually not in
|
| exports.callFunction = callFunction; |
| exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs; |
| exports.callGlobalWithSavedArgs = callGlobalWithSavedArgs; |
| + exports.disableAccessibilityChecks = disableAccessibilityChecks; |
| + exports.enableAccessibilityChecks = enableAccessibilityChecks; |
| exports.expectTrue = createExpect(assertTrue); |
| exports.expectFalse = createExpect(assertFalse); |
| exports.expectGE = createExpect(assertGE); |
| @@ -1389,11 +1616,15 @@ var testing = {}; |
| exports.expectLT = createExpect(assertLT); |
| exports.expectNotEquals = createExpect(assertNotEquals); |
| exports.expectNotReached = createExpect(assertNotReached); |
| + exports.expectAccessibilityOk = createExpect(assertAccessibilityOk); |
| + exports.getAccessibilityErrors = getAccessibilityErrors; |
| + exports.getAccessibilityWarnings = getAccessibilityWarnings; |
| 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 +1633,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; |