Bug 1295564 - fixing aria-activedescendant handling in breadcrumbs when they are unchecked. r=bgrins draft
authorYura Zenevich <yzenevich@mozilla.com>
Tue, 16 Aug 2016 16:37:12 -0400
changeset 401286 57d2ecb951036b5285f4db92c0450bc767ca4e0a
parent 400825 054d4856cea6150a6638e5daf7913713281af97d
child 528453 2d21f2a2c2cbcd91cae253ccd45aff66054c1a69
push id26421
push useryura.zenevich@gmail.com
push dateTue, 16 Aug 2016 20:37:45 +0000
reviewersbgrins
bugs1295564
milestone51.0a1
Bug 1295564 - fixing aria-activedescendant handling in breadcrumbs when they are unchecked. r=bgrins MozReview-Commit-ID: OzhA1o8ja9
devtools/client/inspector/breadcrumbs.js
devtools/client/inspector/test/browser_inspector_breadcrumbs.js
devtools/client/inspector/test/doc_inspector_breadcrumbs.html
--- a/devtools/client/inspector/breadcrumbs.js
+++ b/devtools/client/inspector/breadcrumbs.js
@@ -490,18 +490,22 @@ HTMLBreadcrumbs.prototype = {
    * Focus event handler. When breadcrumbs container gets focus,
    * aria-activedescendant needs to be updated to currently selected
    * breadcrumb. Ensures that the focus stays on the container at all times.
    * @param {DOMEvent} event.
    */
   handleFocus: function (event) {
     event.stopPropagation();
 
-    this.outer.setAttribute("aria-activedescendant",
-      this.nodeHierarchy[this.currentIndex].button.id);
+    if (this.currentIndex > -1) {
+      this.outer.setAttribute("aria-activedescendant",
+        this.nodeHierarchy[this.currentIndex].button.id);
+    } else {
+      this.outer.removeAttribute("aria-activedescendant");
+    }
 
     this.outer.focus();
   },
 
   /**
    * On click navigate to the correct node.
    * @param {DOMEvent} event.
    */
@@ -610,16 +614,19 @@ HTMLBreadcrumbs.prototype = {
         && this.currentIndex < this.nodeHierarchy.length) {
       this.nodeHierarchy[this.currentIndex].button.removeAttribute("checked");
     }
     if (index > -1) {
       this.nodeHierarchy[index].button.setAttribute("checked", "true");
       if (this.hadFocus) {
         this.nodeHierarchy[index].button.focus();
       }
+    } else {
+      // Unset active active descendant when all buttons are unselected.
+      this.outer.removeAttribute("aria-activedescendant");
     }
     this.currentIndex = index;
   },
 
   /**
    * Get the index of the node in the cache.
    * @param {NodeFront} node.
    * @returns {Number} The index for this node or -1 if not found.
--- a/devtools/client/inspector/test/browser_inspector_breadcrumbs.js
+++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs.js
@@ -63,16 +63,17 @@ add_task(function* () {
     is(labelTag.textContent, node.nodeName,
       "Node " + node.selector + " has the expected tag name");
 
     is(checkedButton.getAttribute("title"), node.title,
       "Node " + node.selector + " has the expected tooltip");
   }
 
   yield testPseudoElements(inspector, container);
+  yield testComments(inspector, container);
 });
 
 function* testPseudoElements(inspector, container) {
   info("Checking for pseudo elements");
 
   let pseudoParent = yield getNodeFront("#pseudo-container", inspector);
   let children = yield inspector.walker.children(pseudoParent);
   is(children.nodes.length, 2, "Pseudo children returned from walker");
@@ -86,8 +87,46 @@ function* testPseudoElements(inspector, 
 
   let afterElement = children.nodes[1];
   breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
   yield selectNode(afterElement, inspector);
   yield breadcrumbsUpdated;
   is(container.childNodes[3].textContent, "::after",
      "::before shows up in breadcrumb");
 }
+
+function* testComments(inspector, container) {
+  info("Checking for comment elements");
+
+  let breadcrumbs = inspector.breadcrumbs;
+  let checkedButtonIndex = 2;
+  let button = container.childNodes[checkedButtonIndex];
+
+  let onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
+  button.click();
+  yield onBreadcrumbsUpdated;
+
+  is(breadcrumbs.currentIndex, checkedButtonIndex, "New button is selected");
+  ok(breadcrumbs.outer.hasAttribute("aria-activedescendant"),
+    "Active descendant must be set");
+
+  let comment = [...inspector.markup._containers].find(([node]) =>
+    node.nodeType === Ci.nsIDOMNode.COMMENT_NODE)[0];
+
+  let onInspectorUpdated = inspector.once("inspector-updated");
+  inspector.selection.setNodeFront(comment);
+  yield onInspectorUpdated;
+
+  is(breadcrumbs.currentIndex, -1,
+    "When comment is selected no breadcrumb should be checked");
+  ok(!breadcrumbs.outer.hasAttribute("aria-activedescendant"),
+    "Active descendant must not be set");
+
+  onInspectorUpdated = inspector.once("inspector-updated");
+  onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
+  button.click();
+  yield Promise.all([onInspectorUpdated, onBreadcrumbsUpdated]);
+
+  is(breadcrumbs.currentIndex, checkedButtonIndex,
+    "Same button is selected again");
+  ok(breadcrumbs.outer.hasAttribute("aria-activedescendant"),
+    "Active descendant must be set again");
+}
--- a/devtools/client/inspector/test/doc_inspector_breadcrumbs.html
+++ b/devtools/client/inspector/test/doc_inspector_breadcrumbs.html
@@ -59,16 +59,17 @@
       <link />
       <link />
       <link />
       <link />
       <link />
       <link />
     </article>
     <div id='pseudo-container'></div>
+    <!-- This is a comment node -->
     <svg id="vector" viewBox="0 0 10 10">
       <clipPath id="clip">
         <rect id="rectangle" x="0" y="0" width="10" height="5"></rect>
       </clipPath>
       <circle cx="5" cy="5" r="5" fill="blue" clip-path="url(#clip)"></circle>
     </svg>
   </body>
 </html>