WebKit Bugzilla
Attachment 360681 Details for
Bug 194005
: AX: Audit tab should have built-in accessibility tests.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-194005-20190130195227.patch (text/plain), 41.65 KB, created by
Aaron Chu
on 2019-01-30 19:52:28 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Aaron Chu
Created:
2019-01-30 19:52:28 PST
Size:
41.65 KB
patch
obsolete
>Subversion Revision: 240755 >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index b7204a2e7bd31ddfe006b175234fefcff8110da3..57639ff9cb5651a8df787cf9b109499b9cce1f60 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,42 @@ >+2019-01-30 Aaron Chu <aaron_chu@apple.com> >+ >+ AX: Audit tab should have built-in accessibility tests. >+ https://bugs.webkit.org/show_bug.cgi?id=194005 >+ <rdar://problem/47657503> >+ >+ Updated built-in accessibility audits test suite. >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Localizations/en.lproj/localizedStrings.js: >+ * UserInterface/Controllers/AuditManager.js: >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.hasChildWithRole): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testMenuRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testGridRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForMultipleBanners): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testDialogToHaveAriaModal): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForLinksLabels): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testRowGroupRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testTableRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForAriaLabelledbySpelling): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForInvalidAriaHiddenValue): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForAriaHiddenFalse): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testTreeRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testRadioGroupRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testFeedRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testImagesLabels): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testComboboxRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testForMultupleLiveRegions): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testButtonLabels): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testCellRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testListRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testTablistRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testDialogsForLabels): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.let.testListboxRoleForRequiredChidren): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded): >+ (WI.AuditManager): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.): Deleted. >+ > 2019-01-30 Nikita Vasilyev <nvasilyev@apple.com> > > Web Inspector: Changes: group CSS rules by resource >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index e7084f29858950b0cdc19f23810e34232d522986..955aa33d5c6c77d54949eb1c8aab4e18837d0903 100644 >--- a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >+++ b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >@@ -301,6 +301,7 @@ localizedStrings["Detach into separate window"] = "Detach into separate window"; > localizedStrings["Detached"] = "Detached"; > localizedStrings["Details"] = "Details"; > localizedStrings["Device Settings"] = "Device Settings"; >+localizedStrings["Diagnoses common accessibility problems affecting screen readers and other assistive technology."] = "Diagnoses common accessibility problems affecting screen readers and other assistive technology."; > localizedStrings["Dimensions"] = "Dimensions"; > localizedStrings["Disable Breakpoint"] = "Disable Breakpoint"; > localizedStrings["Disable Breakpoints"] = "Disable Breakpoints"; >@@ -382,18 +383,12 @@ localizedStrings["Enable source maps"] = "Enable source maps"; > localizedStrings["Enabled"] = "Enabled"; > localizedStrings["Encoded"] = "Encoded"; > localizedStrings["Encoding"] = "Encoding"; >-localizedStrings["Ensure <area> elements have alternate text."] = "Ensure <area> elements have alternate text."; >-localizedStrings["Ensure <blink> is not used."] = "Ensure <blink> is not used."; >-localizedStrings["Ensure <dt> and <dd> elements are contained by a <dl>."] = "Ensure <dt> and <dd> elements are contained by a <dl>."; >-localizedStrings["Ensure <form>s have at least one input."] = "Ensure <form>s have at least one input."; >-localizedStrings["Ensure <frame> elements have a title."] = "Ensure <frame> elements have a title."; >-localizedStrings["Ensure <img> elements have alternate text."] = "Ensure <img> elements have alternate text."; >-localizedStrings["Ensure <marquee> is not used."] = "Ensure <marquee> is not used."; >-localizedStrings["Ensure <meta http-equiv=refresh> is not used."] = "Ensure <meta http-equiv=refresh> is not used."; >-localizedStrings["Ensure exactly one <legend> exists per <form>."] = "Ensure exactly one <legend> exists per <form>."; >-localizedStrings["Ensure hidden=true is not present on the <body>."] = "Ensure hidden=true is not present on the <body>."; >-localizedStrings["Ensure tabindex is a number."] = "Ensure tabindex is a number."; >-localizedStrings["Ensure that the <legend> is the first child in the <form>."] = "Ensure that the <legend> is the first child in the <form>."; >+localizedStrings["Ensure \u0022%s\u0022 and \u0022%s\u0022 to have required children."] = "Ensure \u0022%s\u0022 and \u0022%s\u0022 to have required children."; >+localizedStrings["Ensure \u0022%s\u0022 is spelled correctly."] = "Ensure \u0022%s\u0022 is spelled correctly."; >+localizedStrings["Ensure \u0022%s\u0022 to have required children."] = "Ensure \u0022%s\u0022 to have required children."; >+localizedStrings["Ensure aria-hidden=\u0022%s\u0022 is not used"] = "Ensure aria-hidden=\u0022%s\u0022 is not used"; >+localizedStrings["Ensure elements of accessibility role \u0022%s\u0022 to have required children."] = "Ensure elements of accessibility role \u0022%s\u0022 to have required children."; >+localizedStrings["Ensure elements of role \u0022%s\u0022 to have labels."] = "Ensure elements of role \u0022%s\u0022 to have labels."; > localizedStrings["Entered Full-Screen Mode"] = "Entered Full-Screen Mode"; > localizedStrings["Entered Low-Power Mode"] = "Entered Low-Power Mode"; > localizedStrings["Entire Recording"] = "Entire Recording"; >@@ -947,10 +942,13 @@ localizedStrings["Tabs"] = "Tabs"; > localizedStrings["Tag"] = "Tag"; > localizedStrings["Take snapshot"] = "Take snapshot"; > localizedStrings["Template Content"] = "Template Content"; >-localizedStrings["Tests for element accessibility issues."] = "Tests for element accessibility issues."; >-localizedStrings["Tests for element attribute accessibility issues."] = "Tests for element attribute accessibility issues."; >-localizedStrings["Tests for ways to improve accessibility."] = "Tests for ways to improve accessibility."; >-localizedStrings["Tests the accessibility of form elements."] = "Tests the accessibility of form elements."; >+localizedStrings["Test for buttons with labels."] = "Test for buttons with labels."; >+localizedStrings["Test for invalid \u0022%s\u0022 values."] = "Test for invalid \u0022%s\u0022 values."; >+localizedStrings["Test for links to have labels."] = "Test for links to have labels."; >+localizedStrings["Test for multiple banners on the page."] = "Test for multiple banners on the page."; >+localizedStrings["Test for multiple live regions."] = "Test for multiple live regions."; >+localizedStrings["Test that all Dialogs have aria-modal set to true."] = "Test that all Dialogs have aria-modal set to true."; >+localizedStrings["Test that all dialogs have labels."] = "Test that all dialogs have labels."; > localizedStrings["Text"] = "Text"; > localizedStrings["Text Frame"] = "Text Frame"; > localizedStrings["Text Node"] = "Text Node"; >@@ -1082,6 +1080,11 @@ localizedStrings["\u0022%s\u0022 must be an %s"] = "\u0022%s\u0022 must be an %s > localizedStrings["\u0022%s\u0022 threw an error"] = "\u0022%s\u0022 threw an error"; > localizedStrings["\u201C%s\u201D Event Fired"] = "\u201C%s\u201D Event Fired"; > localizedStrings["\u201C%s\u201D Profile Recorded"] = "\u201C%s\u201D Profile Recorded"; >+localizedStrings["\u0022%s\u0022 and \u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."] = "\u0022%s\u0022 and \u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."; >+localizedStrings["\u0022%s\u0022 must contain at least one \u0022%s\u0022 or \u0022%s\u0022."] = "\u0022%s\u0022 must contain at least one \u0022%s\u0022 or \u0022%s\u0022."; >+localizedStrings["\u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."] = "\u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."; >+localizedStrings["\u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."] = "\u0022%s\u0022 must contain at least one \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022, \u0022%s\u0022 or \u0022%s\u0022."; >+localizedStrings["\u0022%s\u0022 must contain at least one \u0022%s\u0022."] = "\u0022%s\u0022 must contain at least one \u0022%s\u0022."; > localizedStrings["computed"] = "computed"; > localizedStrings["default"] = "default"; > localizedStrings["for changes to take effect"] = "for changes to take effect"; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js b/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >index 815212d83dd4da48e18b5fa7592be4be3ffd187a..cd0a641f21dcdb955b7883e2adaff0a83765d231 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >@@ -305,6 +305,506 @@ WI.AuditManager = class AuditManager extends WI.Object > if (this._tests.length) > return; > >+ let testMenuRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "menu": ["menuitem", "menuitemcheckbox", "menuitemradio"], >+ "menubar": ["menuitem", "menuitemcheckbox", "menuitemradio"] >+ } >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testGridRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "grid": ["row", "rowgroup"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testForMultipleBanners = function() { >+ let banners = Array.from(WebInspectorAudit.Accessibility.getElementsByComputedRole("banner")); >+ let domNodes = banners.slice(1); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testDialogToHaveAriaModal = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let dialogs = Array.from(audit.getElementsByComputedRole("dialog")); >+ let domNodes = dialogs.filter(dialog => { >+ return !dialog.getAttribute("aria-modal") === "true"; >+ }); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testForLinksLabels = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let links = Array.from(audit.getElementsByComputedRole("link")); >+ let domNodes = links.filter(link => { >+ return !audit.getComputedProperties(link).label; >+ }); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testRowGroupRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "rowgroup": ["row"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testTableRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "table": ["row", "rowgroup"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testForAriaLabelledbySpelling = function() { >+ let domNodes = Array.from(document.querySelectorAll("[aria-labeledby]")); >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["aria-labeledby"] } >+ } >+ let testForInvalidAriaHiddenValue = function() { >+ let domNodes = Array.from(document.querySelectorAll("[aria-hidden]:not([aria-hidden=true]):not([aria-hidden=false])")); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testForAriaHiddenFalse = function() { >+ let domNodes = Array.from(document.querySelectorAll("[aria-hidden=false]")); >+ return { level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["aria-hidden"] } >+ } >+ let testTreeRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "tree": ["treeitem", "group"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testRadioGroupRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "radiogroup": ["radio"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testFeedRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "feed": ["article"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testImagesLabels = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let images = Array.from(audit.getElementsByComputedRole("img")); >+ let domNodes = images.filter(image => { >+ return !audit.getComputedProperties(image).label; >+ }); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testComboboxRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "combobox": ["textbox", "listbox", "tree", "grid", "dialog"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testForMultupleLiveRegions = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let liveRegionRoles = ["alert", "log", "status", "marquee", "timer"]; >+ let liveRegions = liveRegionRoles.reduce((a, b) => { >+ return a.concat(audit.getElementsByComputedRole(b)); >+ }, []); >+ let domNodes = liveRegions.concat(Array.from(document.querySelectorAll("[aria-live=polite], [aria-live=assertive]"))); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testButtonLabels = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let buttons = Array.from(audit.getElementsByComputedRole("button")); >+ let domNodes = buttons.filter(button => { >+ return !audit.getComputedProperties(button).label; >+ }); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testCellRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "cell": ["row"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testListRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "list": ["listitem", "group"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testTablistRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "tablist": ["tab"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ let testDialogsForLabels = function() { >+ let audit = WebInspectorAudit.Accessibility; >+ let dialogs = Array.from(audit.getElementsByComputedRole("dialog")); >+ let domNodes = dialogs.filter(dialog => { >+ return !WebInspectorWebInspectorAudit.Accessibility.getComputedProperties(dialog).label; >+ }); >+ return { level: domNodes.length ? "fail" : "pass", domNodes } >+ } >+ let testListboxRoleForRequiredChidren = function() { >+ let domNodes = []; >+ const Relationships = { >+ "listbox": ["option"] >+ }; >+ let audit = WebInspectorAudit.Accessibility; >+ let visitedParents = new Set; >+ for (let role in Relationships) { >+ for (let parentNode of audit.getElementsByComputedRole(role)) { >+ if (visitedParents.has(parentNode)) >+ continue; >+ >+ if (!hasChildWithRole(parentNode.firstChild, Relationships[role])) >+ domNodes.push(parentNode); >+ } >+ } >+ function hasChildWithRole(node, expectedRoles){ >+ let childNode = node; >+ if (childNode.parentNode) >+ visitedParents.add(childNode.parentNode); >+ >+ while(childNode) { >+ let properties = audit.getComputedProperties(childNode); >+ if (childNode.nodeType === 1 && properties) { >+ if (properties.role !== "" && expectedRoles.includes(properties.role)) >+ return true; >+ >+ if (childNode.hasChildNodes() && hasChildWithRole(childNode.firstChild, expectedRoles)) >+ return true; >+ } >+ childNode = childNode.nextSibling; >+ } >+ return false; >+ } >+ return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["role"] } >+ } >+ > const defaultTests = [ > new WI.AuditTestGroup(WI.UIString("Demo Audit"), [ > new WI.AuditTestGroup(WI.UIString("Result Levels"), [ >@@ -321,25 +821,29 @@ WI.AuditManager = class AuditManager extends WI.Object > ], {description: WI.UIString("These are all of the different types of data that can be returned with the test result.")}), > ], {description: WI.UIString("These tests serve as a demonstration of the functionality and structure of audits.")}), > new WI.AuditTestGroup(WI.UIString("Accessibility"), [ >- new WI.AuditTestGroup(WI.UIString("Attributes"), [ >- new WI.AuditTestCase(`img-alt`, `function() { let domNodes = Array.from(document.getElementsByTagName("img")).filter((img) => !img.alt || !img.alt.length); return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["alt"] }; }`, {description: WI.UIString("Ensure <img> elements have alternate text.")}), >- new WI.AuditTestCase(`area-alt`, `function() { let domNodes = Array.from(document.getElementsByTagName("area")).filter((area) => !area.alt || !area.alt.length); return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["alt"] }; }`, {description: WI.UIString("Ensure <area> elements have alternate text.")}), >- new WI.AuditTestCase(`valid-tabindex`, `function() { let domNodes = Array.from(document.querySelectorAll("*[tabindex]")) .filter((node) => { let tabindex = node.getAttribute("tabindex"); if (!tabindex) return false; tabindex = parseInt(tabindex); return isNaN(tabindex) || (tabindex !== 0 && tabindex !== -1); }); return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["tabindex"] }; }`, {description: WI.UIString("Ensure tabindex is a number.")}), >- new WI.AuditTestCase(`frame-title`, `function() { let domNodes = Array.from(document.querySelectorAll("iframe, frame")) .filter((node) => { let title = node.getAttribute("title"); return !title || !title.trim().length; }); return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["title"] }; }`, {description: WI.UIString("Ensure <frame> elements have a title.")}), >- new WI.AuditTestCase(`hidden-body`, `function() { let domNodes = Array.from(document.querySelectorAll("body[hidden]")).filter((body) => body.hidden); return { level: domNodes.length ? "fail" : "pass", domNodes, domAttributes: ["hidden"] }; }`, {description: WI.UIString("Ensure hidden=true is not present on the <body>.")}), >- new WI.AuditTestCase(`meta-refresh`, `function() { let domNodes = Array.from(document.querySelectorAll("meta[http-equiv=refresh]")); return { level: domNodes.length ? "warn" : "pass", domNodes, domAttributes: ["http-equiv"] }; }`, {description: WI.UIString("Ensure <meta http-equiv=refresh> is not used.")}), >- ], {description: WI.UIString("Tests for element attribute accessibility issues.")}), >- new WI.AuditTestGroup(WI.UIString("Elements"), [ >- new WI.AuditTestCase(`blink`, `function() { let domNodes = Array.from(document.getElementsByTagName("blink")); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure <blink> is not used.")}), >- new WI.AuditTestCase(`marquee`, `function() { let domNodes = Array.from(document.getElementsByTagName("marquee")); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure <marquee> is not used.")}), >- new WI.AuditTestCase(`dlitem`, `function() { function check(node) { if (!node) { return false; } if (node.nodeName === "DD") { return true; } return check(node.parentNode); } let domNodes = Array.from(document.querySelectorAll("dt, dd")).filter(check); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure <dt> and <dd> elements are contained by a <dl>.")}), >- ], {description: WI.UIString("Tests for element accessibility issues.")}), >- new WI.AuditTestGroup(WI.UIString("Forms"), [ >- new WI.AuditTestCase(`one-legend`, `function() { let formLegendsMap = Array.from(document.querySelectorAll("form legend")).reduce((accumulator, node) => { let existing = accumulator.get(node.form); if (!existing) { existing = []; accumulator.set(node.form, existing); } existing.push(node); return accumulator; }, new Map); let domNodes = Array.from(formLegendsMap.values()).reduce((accumulator, legends) => accumulator.concat(legends), []); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure exactly one <legend> exists per <form>.")}), >- new WI.AuditTestCase(`legend-first-child`, `function() { let domNodes = Array.from(document.querySelectorAll("form > legend:not(:first-child)")); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure that the <legend> is the first child in the <form>.")}), >- new WI.AuditTestCase(`form-input`, `function() { let domNodes = Array.from(document.getElementsByTagName("form")) .filter(node => !node.elements.length); return { level: domNodes.length ? "warn" : "pass", domNodes }; }`, {description: WI.UIString("Ensure <form>s have at least one input.")}), >- ], {description: WI.UIString("Tests the accessibility of form elements.")}), >- ], {description: WI.UIString("Tests for ways to improve accessibility.")}), >+ new WI.AuditTestCase(`testMenuRoleForRequiredChidren`, testMenuRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 and \u0022%s\u0022 to have required children.").format("menu","menubar")}), >+ new WI.AuditTestCase(`testGridRoleForRequiredChidren`, testGridRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("grid")}), >+ new WI.AuditTestCase(`testForMultipleBanners`, testForMultipleBanners.toString(), {description: WI.UIString("Test for multiple banners on the page.")}), >+ new WI.AuditTestCase(`testDialogToHaveAriaModal`, testDialogToHaveAriaModal.toString(), {description: WI.UIString("Test that all Dialogs have aria-modal set to true.")}), >+ new WI.AuditTestCase(`testForLinksLabels`, testForLinksLabels.toString(), {description: WI.UIString("Test for links to have labels.")}), >+ new WI.AuditTestCase(`testRowGroupRoleForRequiredChidren`, testRowGroupRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("rowgroup")}), >+ new WI.AuditTestCase(`testTableRoleForRequiredChidren`, testTableRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure elements of accessibility role \u0022%s\u0022 to have required children.").format("table")}), >+ new WI.AuditTestCase(`testForAriaLabelledbySpelling`, testForAriaLabelledbySpelling.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 is spelled correctly.").format("aria-labelledby")}), >+ new WI.AuditTestCase(`testForInvalidAriaHiddenValue`, testForInvalidAriaHiddenValue.toString(), {description: WI.UIString("Test for invalid \u0022%s\u0022 values.").format("aria-hidden")}), >+ new WI.AuditTestCase(`testForAriaHiddenFalse`, testForAriaHiddenFalse.toString(), {description: WI.UIString("Ensure aria-hidden=\u0022%s\u0022 is not used").format("false")}), >+ new WI.AuditTestCase(`testTreeRoleForRequiredChidren`, testTreeRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("tree")}), >+ new WI.AuditTestCase(`testRadioGroupRoleForRequiredChidren`, testRadioGroupRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("radiogroup")}), >+ new WI.AuditTestCase(`testFeedRoleForRequiredChidren`, testFeedRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure elements of accessibility role \u0022%s\u0022 to have required children.").format("feed")}), >+ new WI.AuditTestCase(`testImagesLabels`, testImagesLabels.toString(), {description: WI.UIString("Ensure elements of role \u0022%s\u0022 to have labels.").format("img")}), >+ new WI.AuditTestCase(`testComboboxRoleForRequiredChidren`, testComboboxRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure elements of accessibility role \u0022%s\u0022 to have required children.").format("combobox")}), >+ new WI.AuditTestCase(`testForMultupleLiveRegions`, testForMultupleLiveRegions.toString(), {description: WI.UIString("Test for multiple live regions.")}), >+ new WI.AuditTestCase(`testButtonLabels`, testButtonLabels.toString(), {description: WI.UIString("Test for buttons with labels.")}), >+ new WI.AuditTestCase(`testCellRoleForRequiredChidren`, testCellRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("cell")}), >+ new WI.AuditTestCase(`testListRoleForRequiredChidren`, testListRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure elements of accessibility role \u0022%s\u0022 to have required children.").format("list")}), >+ new WI.AuditTestCase(`testTablistRoleForRequiredChidren`, testTablistRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure \u0022%s\u0022 to have required children.").format("tablist")}), >+ new WI.AuditTestCase(`testDialogsForLabels`, testDialogsForLabels.toString(), {description: WI.UIString("Test that all dialogs have labels.")}), >+ new WI.AuditTestCase(`testListboxRoleForRequiredChidren`, testListboxRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure elements of accessibility role \u0022%s\u0022 to have required children.").format("listbox")}) >+ ], {description: WI.UIString("Diagnoses common accessibility problems affecting screen readers and other assistive technology.")}), > ]; > > let checkDisabledDefaultTest = (test) => {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194005
:
360553
|
360601
|
360681
|
360703
|
360713
|
360714
|
360750
|
361376
|
361381
|
361426
|
361442
|
362155