Bug 1497969 - Add a way to emulate :focus-within pseudo-class. r=pbro
authorTim Nguyen <ntim.bugs@gmail.com>
Fri, 12 Oct 2018 21:56:44 +0000
changeset 499400 0bad7b51e301e52d3887745546c569c0db412f3b
parent 499399 74a98c04cd54385d99b2a49842df0a9f14846bf4
child 499401 ddb585f4d9d751d42c3b69ebad15b9c3128efbab
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1497969
milestone64.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1497969 - Add a way to emulate :focus-within pseudo-class. r=pbro Differential Revision: https://phabricator.services.mozilla.com/D8275
devtools/client/inspector/index.xhtml
devtools/client/inspector/inspector.js
devtools/client/inspector/rules/rules.js
devtools/client/inspector/rules/test/browser_rules_add-rule-pseudo-class.js
devtools/client/inspector/rules/test/browser_rules_pseudo_lock_options.js
devtools/client/inspector/rules/views/rule-editor.js
devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
devtools/client/inspector/test/browser_inspector_pseudoclass-menu.js
devtools/client/themes/rules.css
devtools/server/actors/highlighters/box-model.js
devtools/server/actors/inspector/node.js
devtools/server/actors/inspector/walker.js
devtools/server/tests/mochitest/test_inspector-pseudoclass-lock.html
--- a/devtools/client/inspector/index.xhtml
+++ b/devtools/client/inspector/index.xhtml
@@ -99,16 +99,17 @@
               <button id="pseudo-class-panel-toggle" data-localization="title=inspector.togglePseudo.tooltip" class="devtools-button"></button>
               <button id="class-panel-toggle" data-localization="title=inspector.classPanel.toggleClass.tooltip" class="devtools-button"></button>
             </div>
           </div>
           <div id="pseudo-class-panel" class="ruleview-reveal-panel" hidden="true">
             <label><input id="pseudo-hover-toggle" type="checkbox" value=":hover" tabindex="-1" />:hover</label>
             <label><input id="pseudo-active-toggle" type="checkbox" value=":active" tabindex="-1" />:active</label>
             <label><input id="pseudo-focus-toggle" type="checkbox" value=":focus" tabindex="-1" />:focus</label>
+            <label><input id="pseudo-focus-within-toggle" type="checkbox" value=":focus-within" tabindex="-1" />:focus-within</label>
           </div>
           <div id="ruleview-class-panel" class="ruleview-reveal-panel" hidden="true"></div>
         </div>
 
         <div id="ruleview-container" class="ruleview">
           <div id="ruleview-container-focusable" tabindex="-1">
           </div>
         </div>
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -1580,17 +1580,17 @@ Inspector.prototype = {
       submenu: this._getAttributesSubmenu(isEditableElement),
     }));
 
     menu.append(new MenuItem({
       type: "separator",
     }));
 
     // Set the pseudo classes
-    for (const name of ["hover", "active", "focus"]) {
+    for (const name of ["hover", "active", "focus", "focus-within"]) {
       const menuitem = new MenuItem({
         id: "node-menu-pseudo-" + name,
         label: name,
         type: "checkbox",
         click: this.togglePseudoClass.bind(this, ":" + name),
       });
 
       if (isSelectionElement) {
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -134,16 +134,17 @@ function CssRuleView(inspector, document
   this.searchClearButton = doc.getElementById("ruleview-searchinput-clear");
   this.pseudoClassPanel = doc.getElementById("pseudo-class-panel");
   this.pseudoClassToggle = doc.getElementById("pseudo-class-panel-toggle");
   this.classPanel = doc.getElementById("ruleview-class-panel");
   this.classToggle = doc.getElementById("class-panel-toggle");
   this.hoverCheckbox = doc.getElementById("pseudo-hover-toggle");
   this.activeCheckbox = doc.getElementById("pseudo-active-toggle");
   this.focusCheckbox = doc.getElementById("pseudo-focus-toggle");
+  this.focusWithinCheckbox = doc.getElementById("pseudo-focus-within-toggle");
 
   this.searchClearButton.hidden = true;
 
   this.shortcuts = new KeyShortcuts({ window: this.styleWindow });
   this._onShortcut = this._onShortcut.bind(this);
   this.shortcuts.on("Escape", event => this._onShortcut("Escape", event));
   this.shortcuts.on("Return", event => this._onShortcut("Return", event));
   this.shortcuts.on("Space", event => this._onShortcut("Space", event));
@@ -153,16 +154,17 @@ function CssRuleView(inspector, document
   this.addRuleButton.addEventListener("click", this._onAddRule);
   this.searchField.addEventListener("input", this._onFilterStyles);
   this.searchClearButton.addEventListener("click", this._onClearSearch);
   this.pseudoClassToggle.addEventListener("click", this._onTogglePseudoClassPanel);
   this.classToggle.addEventListener("click", this._onToggleClassPanel);
   this.hoverCheckbox.addEventListener("click", this._onTogglePseudoClass);
   this.activeCheckbox.addEventListener("click", this._onTogglePseudoClass);
   this.focusCheckbox.addEventListener("click", this._onTogglePseudoClass);
+  this.focusWithinCheckbox.addEventListener("click", this._onTogglePseudoClass);
 
   if (flags.testing) {
     // In tests, we start listening immediately to avoid having to simulate a mousemove.
     this.highlighters.addToView(this);
   } else {
     this.element.addEventListener("mousemove", () => {
       this.highlighters.addToView(this);
     }, { once: true });
@@ -773,26 +775,28 @@ CssRuleView.prototype = {
     this.addRuleButton.removeEventListener("click", this._onAddRule);
     this.searchField.removeEventListener("input", this._onFilterStyles);
     this.searchClearButton.removeEventListener("click", this._onClearSearch);
     this.pseudoClassToggle.removeEventListener("click", this._onTogglePseudoClassPanel);
     this.classToggle.removeEventListener("click", this._onToggleClassPanel);
     this.hoverCheckbox.removeEventListener("click", this._onTogglePseudoClass);
     this.activeCheckbox.removeEventListener("click", this._onTogglePseudoClass);
     this.focusCheckbox.removeEventListener("click", this._onTogglePseudoClass);
+    this.focusWithinCheckbox.removeEventListener("click", this._onTogglePseudoClass);
 
     this.searchField = null;
     this.searchClearButton = null;
     this.pseudoClassPanel = null;
     this.pseudoClassToggle = null;
     this.classPanel = null;
     this.classToggle = null;
     this.hoverCheckbox = null;
     this.activeCheckbox = null;
     this.focusCheckbox = null;
+    this.focusWithinCheckbox = null;
 
     this.inspector = null;
     this.styleDocument = null;
     this.styleWindow = null;
 
     if (this.element.parentNode) {
       this.element.remove();
     }
@@ -922,26 +926,28 @@ CssRuleView.prototype = {
   /**
    * Clear the pseudo class options panel by removing the checked and disabled
    * attributes for each checkbox.
    */
   clearPseudoClassPanel: function() {
     this.hoverCheckbox.checked = this.hoverCheckbox.disabled = false;
     this.activeCheckbox.checked = this.activeCheckbox.disabled = false;
     this.focusCheckbox.checked = this.focusCheckbox.disabled = false;
+    this.focusWithinCheckbox.checked = this.focusWithinCheckbox.disabled = false;
   },
 
   /**
    * Update the pseudo class options for the currently highlighted element.
    */
   refreshPseudoClassPanel: function() {
     if (!this._elementStyle || !this.inspector.selection.isElementNode()) {
       this.hoverCheckbox.disabled = true;
       this.activeCheckbox.disabled = true;
       this.focusCheckbox.disabled = true;
+      this.focusWithinCheckbox.disabled = true;
       return;
     }
 
     for (const pseudoClassLock of this._elementStyle.element.pseudoClassLocks) {
       switch (pseudoClassLock) {
         case ":hover": {
           this.hoverCheckbox.checked = true;
           break;
@@ -949,16 +955,20 @@ CssRuleView.prototype = {
         case ":active": {
           this.activeCheckbox.checked = true;
           break;
         }
         case ":focus": {
           this.focusCheckbox.checked = true;
           break;
         }
+        case ":focus-within": {
+          this.focusWithinCheckbox.checked = true;
+          break;
+        }
       }
     }
   },
 
   _populate: function() {
     const elementStyle = this._elementStyle;
     return this._elementStyle.populate().then(() => {
       if (this._elementStyle !== elementStyle || this.isDestroyed) {
@@ -1564,25 +1574,27 @@ CssRuleView.prototype = {
 
   showPseudoClassPanel: function() {
     this.hideClassPanel();
 
     this.pseudoClassToggle.classList.add("checked");
     this.hoverCheckbox.setAttribute("tabindex", "0");
     this.activeCheckbox.setAttribute("tabindex", "0");
     this.focusCheckbox.setAttribute("tabindex", "0");
+    this.focusWithinCheckbox.setAttribute("tabindex", "0");
 
     this.pseudoClassPanel.hidden = false;
   },
 
   hidePseudoClassPanel: function() {
     this.pseudoClassToggle.classList.remove("checked");
     this.hoverCheckbox.setAttribute("tabindex", "-1");
     this.activeCheckbox.setAttribute("tabindex", "-1");
     this.focusCheckbox.setAttribute("tabindex", "-1");
+    this.focusWithinCheckbox.setAttribute("tabindex", "-1");
 
     this.pseudoClassPanel.hidden = true;
   },
 
   /**
    * Called when a pseudo class checkbox is clicked and toggles
    * the pseudo class for the current selected element.
    */
--- a/devtools/client/inspector/rules/test/browser_rules_add-rule-pseudo-class.js
+++ b/devtools/client/inspector/rules/test/browser_rules_add-rule-pseudo-class.js
@@ -11,17 +11,20 @@ const TEST_URI = "<p id='element'>Test e
 const EXPECTED_SELECTOR = "#element";
 const TEST_DATA = [
   [],
   [":hover"],
   [":hover", ":active"],
   [":hover", ":active", ":focus"],
   [":active"],
   [":active", ":focus"],
-  [":focus"]
+  [":focus"],
+  [":focus-within"],
+  [":hover", ":focus-within"],
+  [":hover", ":active", ":focus-within"],
 ];
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const {inspector, view} = await openRuleView();
   await selectNode("#element", inspector);
 
   for (const data of TEST_DATA) {
@@ -52,31 +55,40 @@ async function setPseudoLocks(inspector,
       case ":active":
         view.activeCheckbox.click();
         await inspector.once("rule-view-refreshed");
         break;
       case ":focus":
         view.focusCheckbox.click();
         await inspector.once("rule-view-refreshed");
         break;
+      case ":focus-within":
+        view.focusWithinCheckbox.click();
+        await inspector.once("rule-view-refreshed");
+        break;
     }
   }
 }
 
 async function resetPseudoLocks(inspector, view) {
   if (!view.hoverCheckbox.checked &&
       !view.activeCheckbox.checked &&
-      !view.focusCheckbox.checked) {
+      !view.focusCheckbox.checked &&
+      !view.focusWithinCheckbox.checked) {
     return;
   }
   if (view.hoverCheckbox.checked) {
     view.hoverCheckbox.click();
     await inspector.once("rule-view-refreshed");
   }
   if (view.activeCheckbox.checked) {
     view.activeCheckbox.click();
     await inspector.once("rule-view-refreshed");
   }
   if (view.focusCheckbox.checked) {
     view.focusCheckbox.click();
     await inspector.once("rule-view-refreshed");
   }
+  if (view.focusWithinCheckbox.checked) {
+    view.focusWithinCheckbox.click();
+    await inspector.once("rule-view-refreshed");
+  }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_pseudo_lock_options.js
+++ b/devtools/client/inspector/rules/test/browser_rules_pseudo_lock_options.js
@@ -15,16 +15,19 @@ const TEST_URI = `
       color: blue;
     }
     div:active {
       color: yellow;
     }
     div:focus {
       color: green;
     }
+    div:focus-within {
+      color: papayawhip;
+    }
   </style>
   <div>test div</div>
 `;
 
 add_task(async function() {
   await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   const {inspector, view} = await openRuleView();
   await selectNode("div", inspector);
@@ -46,16 +49,21 @@ add_task(async function() {
   await togglePseudoClass(inspector, view.activeCheckbox);
   await assertPseudoRemoved(inspector, view, 2);
 
   await togglePseudoClass(inspector, view.focusCheckbox);
   await assertPseudoAdded(inspector, view, ":focus", 3, 1);
   await togglePseudoClass(inspector, view.focusCheckbox);
   await assertPseudoRemoved(inspector, view, 2);
 
+  await togglePseudoClass(inspector, view.focusWithinCheckbox);
+  await assertPseudoAdded(inspector, view, ":focus-within", 3, 1);
+  await togglePseudoClass(inspector, view.focusWithinCheckbox);
+  await assertPseudoRemoved(inspector, view, 2);
+
   info("Toggle all pseudo lock and check that the pseudo lock is added");
   await togglePseudoClass(inspector, view.hoverCheckbox);
   await togglePseudoClass(inspector, view.activeCheckbox);
   await togglePseudoClass(inspector, view.focusCheckbox);
   await assertPseudoAdded(inspector, view, ":focus", 5, 1);
   await assertPseudoAdded(inspector, view, ":active", 5, 2);
   await assertPseudoAdded(inspector, view, ":hover", 5, 3);
   await togglePseudoClass(inspector, view.hoverCheckbox);
@@ -66,16 +74,18 @@ add_task(async function() {
   info("Select a null element");
   await view.selectElement(null);
   ok(!view.hoverCheckbox.checked && view.hoverCheckbox.disabled,
     ":hover checkbox is unchecked and disabled");
   ok(!view.activeCheckbox.checked && view.activeCheckbox.disabled,
     ":active checkbox is unchecked and disabled");
   ok(!view.focusCheckbox.checked && view.focusCheckbox.disabled,
     ":focus checkbox is unchecked and disabled");
+  ok(!view.focusWithinCheckbox.checked && view.focusWithinCheckbox.disabled,
+    ":focus-within checkbox is unchecked and disabled");
 
   info("Toggle the pseudo class panel close");
   view.pseudoClassToggle.click();
   await assertPseudoPanelClosed(view);
 });
 
 async function togglePseudoClass(inspector, pseudoClassOption) {
   info("Toggle the pseudoclass, wait for it to be applied");
@@ -103,29 +113,34 @@ function assertPseudoRemoved(inspector, 
 
 function assertPseudoPanelOpened(view) {
   info("Check the opened state of the pseudo class panel");
 
   ok(!view.pseudoClassPanel.hidden, "Pseudo Class Panel Opened");
   ok(!view.hoverCheckbox.disabled, ":hover checkbox is not disabled");
   ok(!view.activeCheckbox.disabled, ":active checkbox is not disabled");
   ok(!view.focusCheckbox.disabled, ":focus checkbox is not disabled");
+  ok(!view.focusWithinCheckbox.disabled, ":focus-within checkbox is not disabled");
 
   is(view.hoverCheckbox.getAttribute("tabindex"), "0",
     ":hover checkbox has a tabindex of 0");
   is(view.activeCheckbox.getAttribute("tabindex"), "0",
     ":active checkbox has a tabindex of 0");
   is(view.focusCheckbox.getAttribute("tabindex"), "0",
     ":focus checkbox has a tabindex of 0");
+  is(view.focusWithinCheckbox.getAttribute("tabindex"), "0",
+    ":focus-within checkbox has a tabindex of 0");
 }
 
 function assertPseudoPanelClosed(view) {
   info("Check the closed state of the pseudo clas panel");
 
   ok(view.pseudoClassPanel.hidden, "Pseudo Class Panel Hidden");
 
   is(view.hoverCheckbox.getAttribute("tabindex"), "-1",
     ":hover checkbox has a tabindex of -1");
   is(view.activeCheckbox.getAttribute("tabindex"), "-1",
     ":active checkbox has a tabindex of -1");
   is(view.focusCheckbox.getAttribute("tabindex"), "-1",
     ":focus checkbox has a tabindex of -1");
+  is(view.focusWithinCheckbox.getAttribute("tabindex"), "-1",
+    ":focus-within checkbox has a tabindex of -1");
 }
--- a/devtools/client/inspector/rules/views/rule-editor.js
+++ b/devtools/client/inspector/rules/views/rule-editor.js
@@ -430,17 +430,17 @@ RuleEditor.prototype = {
           switch (selectorText.type) {
             case SELECTOR_ATTRIBUTE:
               selectorClass = "ruleview-selector-attribute";
               break;
             case SELECTOR_ELEMENT:
               selectorClass = "ruleview-selector";
               break;
             case SELECTOR_PSEUDO_CLASS:
-              selectorClass = [":active", ":focus", ":hover"].some(
+              selectorClass = [":active", ":focus", ":focus-within", ":hover"].some(
                   pseudo => selectorText.value === pseudo) ?
                 "ruleview-selector-pseudo-class-lock" :
                 "ruleview-selector-pseudo-class";
               break;
             default:
               break;
           }
 
--- a/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
+++ b/devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js
@@ -28,16 +28,17 @@ const ALL_MENU_ITEMS = [
   "node-menu-copyuniqueselector",
   "node-menu-copycsspath",
   "node-menu-copyxpath",
   "node-menu-copyimagedatauri",
   "node-menu-delete",
   "node-menu-pseudo-hover",
   "node-menu-pseudo-active",
   "node-menu-pseudo-focus",
+  "node-menu-pseudo-focus-within",
   "node-menu-scrollnodeintoview",
   "node-menu-screenshotnode",
   "node-menu-add-attribute",
   "node-menu-copy-attribute",
   "node-menu-edit-attribute",
   "node-menu-remove-attribute"
 ].concat(PASTE_MENU_ITEMS, ACTIVE_ON_DOCTYPE_ITEMS);
 
--- a/devtools/client/inspector/test/browser_inspector_pseudoclass-menu.js
+++ b/devtools/client/inspector/test/browser_inspector_pseudoclass-menu.js
@@ -4,17 +4,17 @@
 "use strict";
 
 // Test that the inspector has the correct pseudo-class locking menu items and
 // that these items actually work
 
 const TEST_URI = "data:text/html;charset=UTF-8," +
                  "pseudo-class lock node menu tests" +
                  "<div>test div</div>";
-const PSEUDOS = ["hover", "active", "focus"];
+const PSEUDOS = ["hover", "active", "focus", "focus-within"];
 
 add_task(async function() {
   const {inspector, testActor} = await openInspectorForURL(TEST_URI);
   await selectNode("div", inspector);
 
   const allMenuItems = openContextMenuAndGetAllItems(inspector);
 
   await testMenuItems(testActor, allMenuItems, inspector);
--- a/devtools/client/themes/rules.css
+++ b/devtools/client/themes/rules.css
@@ -50,16 +50,17 @@
 
 #ruleview-command-toolbar {
   display: flex;
 }
 
 .ruleview-reveal-panel {
   display: flex;
   overflow: hidden;
+  flex-wrap: wrap;
 }
 
 .ruleview-reveal-panel[hidden] {
   display: none;
 }
 
 .ruleview-reveal-panel label {
   -moz-user-select: none;
--- a/devtools/server/actors/highlighters/box-model.js
+++ b/devtools/server/actors/highlighters/box-model.js
@@ -23,17 +23,17 @@ const nodeConstants = require("devtools/
 
 // Note that the order of items in this array is important because it is used
 // for drawing the BoxModelHighlighter's path elements correctly.
 const BOX_MODEL_REGIONS = ["margin", "border", "padding", "content"];
 const BOX_MODEL_SIDES = ["top", "right", "bottom", "left"];
 // Width of boxmodelhighlighter guides
 const GUIDE_STROKE_WIDTH = 1;
 // FIXME: add ":visited" and ":link" after bug 713106 is fixed
-const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
+const PSEUDO_CLASSES = [":hover", ":active", ":focus", ":focus-within"];
 
 /**
  * The BoxModelHighlighter draws the box model regions on top of a node.
  * If the node is a block box, then each region will be displayed as 1 polygon.
  * If the node is an inline box though, each region may be represented by 1 or
  * more polygons, depending on how many line boxes the inline element has.
  *
  * Usage example:
--- a/devtools/server/actors/inspector/node.js
+++ b/devtools/server/actors/inspector/node.js
@@ -29,17 +29,17 @@ loader.lazyRequireGetter(this, "Inspecto
 loader.lazyRequireGetter(this, "LongStringActor", "devtools/server/actors/string", true);
 loader.lazyRequireGetter(this, "getFontPreviewData", "devtools/server/actors/styles", true);
 loader.lazyRequireGetter(this, "CssLogic", "devtools/server/actors/inspector/css-logic", true);
 loader.lazyRequireGetter(this, "EventParsers", "devtools/server/actors/inspector/event-parsers", true);
 
 const SUBGRID_ENABLED =
   Services.prefs.getBoolPref("layout.css.grid-template-subgrid-value.enabled");
 
-const PSEUDO_CLASSES = [":hover", ":active", ":focus"];
+const PSEUDO_CLASSES = [":hover", ":active", ":focus", ":focus-within"];
 const FONT_FAMILY_PREVIEW_TEXT = "The quick brown fox jumps over the lazy dog";
 const FONT_FAMILY_PREVIEW_TEXT_SIZE = 20;
 
 /**
  * Server side of the node actor.
  */
 const NodeActor = protocol.ActorClassWithSpec(nodeSpec, {
   initialize: function(walker, node) {
--- a/devtools/server/actors/inspector/walker.js
+++ b/devtools/server/actors/inspector/walker.js
@@ -1162,17 +1162,17 @@ var WalkerActor = protocol.ActorClassWit
     };
   },
 
   /**
    * Add a pseudo-class lock to a node.
    *
    * @param NodeActor node
    * @param string pseudo
-   *    A pseudoclass: ':hover', ':active', ':focus'
+   *    A pseudoclass: ':hover', ':active', ':focus', ':focus-within'
    * @param options
    *    Options object:
    *    `parents`: True if the pseudo-class should be added
    *      to parent nodes.
    *    `enabled`: False if the pseudo-class should be locked
    *      to 'off'. Defaults to true.
    *
    * @returns An empty packet.  A "pseudoClassLock" mutation will
@@ -1242,17 +1242,17 @@ var WalkerActor = protocol.ActorClassWit
     node.rawNode.classList.remove(HIDDEN_CLASS);
   },
 
   /**
    * Remove a pseudo-class lock from a node.
    *
    * @param NodeActor node
    * @param string pseudo
-   *    A pseudoclass: ':hover', ':active', ':focus'
+   *    A pseudoclass: ':hover', ':active', ':focus', ':focus-within'
    * @param options
    *    Options object:
    *    `parents`: True if the pseudo-class should be removed
    *      from parent nodes.
    *
    * @returns An empty response.  "pseudoClassLock" mutations
    *    will be emitted for any changed nodes.
    */
--- a/devtools/server/tests/mochitest/test_inspector-pseudoclass-lock.html
+++ b/devtools/server/tests/mochitest/test_inspector-pseudoclass-lock.html
@@ -8,17 +8,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   <title>Test for Bug </title>
 
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css">
   <script type="application/javascript" src="inspector-helpers.js"></script>
   <script type="application/javascript">
 "use strict";
 
-const KNOWN_PSEUDOCLASSES = [":hover", ":active", ":focus"];
+const KNOWN_PSEUDOCLASSES = [":hover", ":active", ":focus", ":focus-within"];
 
 window.onload = function() {
   SimpleTest.waitForExplicitFinish();
   runNextTest();
 };
 
 const InspectorUtils = require("InspectorUtils");