WebKit Bugzilla
Attachment 360713 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-20190131023846.patch (text/plain), 41.33 KB, created by
Aaron Chu
on 2019-01-31 02:38:47 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Aaron Chu
Created:
2019-01-31 02:38:47 PST
Size:
41.33 KB
patch
obsolete
>Subversion Revision: 240772 >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index 964298fe61ad42b81e29ce5fdb0e8ae7bc98aedb..263738bf9b0d50b6ee1f8000cbb6cfd6ea9467bb 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,19 @@ >+2019-01-31 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): >+ (WI.AuditManager): >+ (WI.AuditManager.prototype.addDefaultTestsIfNeeded.): Deleted. >+ > 2019-01-30 Devin Rousso <drousso@apple.com> > > Web Inspector: Memory Timeline View should be responsive / resizable >diff --git a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js >index e7084f29858950b0cdc19f23810e34232d522986..d37d49f4d35f92b9bfc0c776cd3b893a44638f02 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,20 @@ 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 aria-hidden=\u0022%s\u0022 is not used"] = "Ensure aria-hidden=\u0022%s\u0022 is not used"; >+localizedStrings["Ensure that \u0022%s\u0022 is spelled correctly."] = "Ensure that \u0022%s\u0022 is spelled correctly."; >+localizedStrings["Ensure that buttons have accessible labels for assistive technology."] = "Ensure that buttons have accessible labels for assistive technology."; >+localizedStrings["Ensure that dialogs have accessible labels for assistive technology."] = "Ensure that dialogs have accessible labels for assistive technology."; >+localizedStrings["Ensure that dialogs have aria-modal set to true."] = "Ensure that dialogs have aria-modal set to true."; >+localizedStrings["Ensure that element of role \u0022%s\u0022 and \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."] = "Ensure that element of role \u0022%s\u0022 and \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."; >+localizedStrings["Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."] = "Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."; >+localizedStrings["Ensure that elements of role \u0022%s\u0022 have accessible labels for assistive technology."] = "Ensure that elements of role \u0022%s\u0022 have accessible labels for assistive technology."; >+localizedStrings["Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."] = "Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1."; >+localizedStrings["Ensure that links have accessible labels for assistive technology."] = "Ensure that links have accessible labels for assistive technology."; >+localizedStrings["Ensure that only one banner is used on the page."] = "Ensure that only one banner is used on the page."; >+localizedStrings["Ensure that only one live region is used on the page."] = "Ensure that only one live region is used on the page."; >+localizedStrings["Ensure that only one main content section is used on the page."] = "Ensure that only one main content section is used on the page."; >+localizedStrings["Ensure that values for \u0022%s\u0022 are valid."] = "Ensure that values for \u0022%s\u0022 are valid."; > 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 +950,6 @@ 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["Text"] = "Text"; > localizedStrings["Text Frame"] = "Text Frame"; > localizedStrings["Text Node"] = "Text Node"; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js b/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >index 815212d83dd4da48e18b5fa7592be4be3ffd187a..2148c55109e779c76ed7aa5b8c1fe43af8381dcc 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/AuditManager.js >@@ -305,6 +305,515 @@ 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 (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 (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 testForMultipleBanners = function() { >+ let domNodes = []; >+ let banners = WebInspectorAudit.Accessibility.getElementsByComputedRole("banner"); >+ if (banners.length > 1) { >+ domNodes = banners; >+ } >+ return {level: domNodes.length ? "fail" : "pass", domNodes}; >+ }; >+ >+ let testForLinksLabels = function() { >+ let links = WebInspectorAudit.Accessibility.getElementsByComputedRole("link"); >+ let domNodes = links.filter((link) => !WebInspectorAudit.Accessibility.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 (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 (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 testDialogForAriaModal = function() { >+ let dialogs = Array.from(WebInspectorAudit.Accessibility.getElementsByComputedRole("dialog")); >+ let domNodes = dialogs.filter((dialog) => !dialog.getAttribute("aria-modal") === "true"); >+ 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 (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 (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 (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 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 (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 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 (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 domNodes = []; >+ let liveRegionRoles = ["alert", "log", "status", "marquee", "timer"]; >+ let liveRegions = liveRegionRoles.reduce((a, b) => { >+ return a.concat(WebInspectorAudit.Accessibility.getElementsByComputedRole(b)); >+ }, []); >+ liveRegions = liveRegions.concat(Array.from(document.querySelectorAll("[aria-live=polite], [aria-live=assertive]"))); >+ if (liveRegions.length > 1) { >+ domNodes = liveRegions; >+ } >+ return {level: domNodes.length ? "fail" : "pass", domNodes}; >+ }; >+ >+ let testImagesLabels = function() { >+ let images = WebInspectorAudit.Accessibility.getElementsByComputedRole("img"); >+ let domNodes = images.filter((image) => !WebInspectorAudit.Accessibility.getComputedProperties(image).label); >+ return {level: domNodes.length ? "fail" : "pass", domNodes}; >+ }; >+ >+ let testButtonLabels = function() { >+ let buttons = WebInspectorAudit.Accessibility.getElementsByComputedRole("button"); >+ let domNodes = buttons.filter((button) => !WebInspectorAudit.Accessibility.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 (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 (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 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 testForMultipleMainContentSections = function() { >+ let domNodes = []; >+ let mainContentElements = WebInspectorAudit.Accessibility.getElementsByComputedRole("main"); >+ if (mainContentElements.length > 1) { >+ domNodes = mainContentElements; >+ } >+ return {level: domNodes.length ? "fail" : "pass", domNodes}; >+ }; >+ >+ let testDialogsForLabels = function() { >+ let dialogs = WebInspectorAudit.Accessibility.getElementsByComputedRole("dialog"); >+ let domNodes = dialogs.filter((dialog) => !WebInspectorAudit.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 (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 +830,30 @@ 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 that element of role \u0022%s\u0022 and \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("menu"), WI.unlocalizedString("menubar"))}), >+ new WI.AuditTestCase(`testGridRoleForRequiredChidren`, testGridRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("grid"))}), >+ new WI.AuditTestCase(`testForAriaLabelledBySpelling`, testForAriaLabelledBySpelling.toString(), {description: WI.UIString("Ensure that \u0022%s\u0022 is spelled correctly.").format(WI.unlocalizedString("aria-labelledby"))}), >+ new WI.AuditTestCase(`testForMultipleBanners`, testForMultipleBanners.toString(), {description: WI.UIString("Ensure that only one banner is used on the page.")}), >+ new WI.AuditTestCase(`testForLinksLabels`, testForLinksLabels.toString(), {description: WI.UIString("Ensure that links have accessible labels for assistive technology.")}), >+ new WI.AuditTestCase(`testRowGroupRoleForRequiredChidren`, testRowGroupRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("rowgroup"))}), >+ new WI.AuditTestCase(`testTableRoleForRequiredChidren`, testTableRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("table"))}), >+ new WI.AuditTestCase(`testDialogForAriaModal`, testDialogForAriaModal.toString(), {description: WI.UIString("Ensure that dialogs have aria-modal set to true.")}), >+ new WI.AuditTestCase(`testForAriaHiddenFalse`, testForAriaHiddenFalse.toString(), {description: WI.UIString("Ensure aria-hidden=\u0022%s\u0022 is not used").format(WI.unlocalizedString("false"))}), >+ new WI.AuditTestCase(`testTreeRoleForRequiredChidren`, testTreeRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("tree"))}), >+ new WI.AuditTestCase(`testRadioGroupRoleForRequiredChidren`, testRadioGroupRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("radiogroup"))}), >+ new WI.AuditTestCase(`testFeedRoleForRequiredChidren`, testFeedRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("feed"))}), >+ new WI.AuditTestCase(`testTabListRoleForRequiredChidren`, testTabListRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that element of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("tablist"))}), >+ new WI.AuditTestCase(`testComboboxRoleForRequiredChidren`, testComboboxRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("combobox"))}), >+ new WI.AuditTestCase(`testForMultupleLiveRegions`, testForMultupleLiveRegions.toString(), {description: WI.UIString("Ensure that only one live region is used on the page.")}), >+ new WI.AuditTestCase(`testImagesLabels`, testImagesLabels.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have accessible labels for assistive technology.").format(WI.unlocalizedString("img"))}), >+ new WI.AuditTestCase(`testButtonLabels`, testButtonLabels.toString(), {description: WI.UIString("Ensure that buttons have accessible labels for assistive technology.")}), >+ new WI.AuditTestCase(`testCellRoleForRequiredChidren`, testCellRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("cell"))}), >+ new WI.AuditTestCase(`testListRoleForRequiredChidren`, testListRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("list"))}), >+ new WI.AuditTestCase(`testForInvalidAriaHiddenValue`, testForInvalidAriaHiddenValue.toString(), {description: WI.UIString("Ensure that values for \u0022%s\u0022 are valid.").format(WI.unlocalizedString("aria-hidden"))}), >+ new WI.AuditTestCase(`testForMultipleMainContentSections`, testForMultipleMainContentSections.toString(), {description: WI.UIString("Ensure that only one main content section is used on the page.")}), >+ new WI.AuditTestCase(`testDialogsForLabels`, testDialogsForLabels.toString(), {description: WI.UIString("Ensure that dialogs have accessible labels for assistive technology.")}), >+ new WI.AuditTestCase(`testListboxRoleForRequiredChidren`, testListboxRoleForRequiredChidren.toString(), {description: WI.UIString("Ensure that elements of role \u0022%s\u0022 have required owned elements in accordance with WAI-ARIA 1.1.").format(WI.unlocalizedString("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