Bug 1266456 - part10: fix tests for autocomplete-popup HTMLTooltip migration;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 01 Jul 2016 14:30:42 +0200
changeset 385566 7fe78b2e3c59581f752be458e8d45f402b13d4e2
parent 385565 d38da891efc2eb2ba49c82c1f8dbcd3861a49b75
child 385567 632f473f016acfd2e3ca48f999d9291a2d7f3e58
push id22536
push userjdescottes@mozilla.com
push dateFri, 08 Jul 2016 16:44:25 +0000
reviewersbgrins
bugs1266456
milestone50.0a1
Bug 1266456 - part10: fix tests for autocomplete-popup HTMLTooltip migration;r=bgrins Most test modifications deal with listening to the proper events. As mentioned in the parent commit, the keyboard navigation for the inspector-search changed a bit with this change, so the related test case is using a slightly different scenario. MozReview-Commit-ID: BgSa69bSSFB
devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_03.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_04.js
devtools/client/inspector/rules/test/browser_rules_completion-new-property_multiline.js
devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
devtools/client/inspector/test/browser_inspector_search-navigation.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
devtools/client/shared/test/helper_inplace_editor.js
devtools/client/webconsole/test/browser_webconsole_autocomplete_popup_close_on_tab_switch.js
devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
devtools/client/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
devtools/client/webconsole/test/browser_webconsole_bug_660806_history_nav.js
devtools/client/webconsole/test/browser_webconsole_split_escape_key.js
--- a/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
+++ b/devtools/client/inspector/markup/test/helper_style_attr_test_runner.js
@@ -115,27 +115,18 @@ function sendKey(key, editor, inspector)
  * Verify that the inplace editor is in the expected state for the provided
  * test data.
  */
 function* checkData(data, editor, inspector) {
   let [, completion, selStart, selEnd, popupOpen] = data;
 
   if (selEnd != -1) {
     is(editor.input.value, completion, "Completed value is correct");
-    is(editor.input.selectionStart, selStart,
-       "Selection start position is correct");
+    is(editor.input.selectionStart, selStart, "Selection start position is correct");
     is(editor.input.selectionEnd, selEnd, "Selection end position is correct");
-    if (popupOpen) {
-      ok(editor.popup.isOpen, "Popup is open");
-    } else {
-      ok(editor.popup._panel.state != "open" &&
-         editor.popup._panel.state != "showing",
-        "Popup is closed");
-    }
+    is(editor.popup.isOpen, popupOpen, "Popup is " + (popupOpen ? "open" : "closed"));
   } else {
     let nodeFront = yield getNodeFront("#node14", inspector);
     let container = getContainerForNodeFront(nodeFront, inspector);
-    let attr = container.editor.attrElements.get("style")
-                                            .querySelector(".editable");
-    is(attr.textContent, completion,
-       "Correct value is persisted after pressing Enter");
+    let attr = container.editor.attrElements.get("style").querySelector(".editable");
+    is(attr.textContent, completion, "Correct value is persisted after pressing Enter");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_01.js
@@ -80,31 +80,27 @@ add_task(function* () {
   yield runAutocompletionTest(toolbox, inspector, view);
 });
 
 function* runAutocompletionTest(toolbox, inspector, view) {
   info("Selecting the test node");
   yield selectNode("h1", inspector);
 
   info("Focusing the css property editable field");
-  let propertyName = view.styleDocument
-    .querySelectorAll(".ruleview-propertyname")[0];
+  let propertyName = view.styleDocument.querySelectorAll(".ruleview-propertyname")[0];
   let editor = yield focusEditableField(view, propertyName);
 
   info("Starting to test for css property completion");
-  let previousPopupSize = 0;
   for (let i = 0; i < testData.length; i++) {
-    let expectPopupHiddenEvent = previousPopupSize > 0 && testData[3] === 0;
-    yield testCompletion(testData[i], expectPopupHiddenEvent, editor, view);
-    previousPopupSize = testData[3];
+    yield testCompletion(testData[i], editor, view);
   }
 }
 
 function* testCompletion([key, completion, open, selected],
-                         expectPopupHiddenEvent, editor, view) {
+                         editor, view) {
   info("Pressing key " + key);
   info("Expecting " + completion);
   info("Is popup opened: " + open);
   info("Is item selected: " + selected);
 
   // Listening for the right event that will tell us when the key has been
   // entered and processed.
   let onSuggest;
@@ -112,31 +108,29 @@ function* testCompletion([key, completio
     info("Adding event listener for " +
       "left|right|back_space|escape|home|end|page_up|page_down keys");
     onSuggest = once(editor.input, "keypress");
   } else {
     info("Waiting for after-suggest event on the editor");
     onSuggest = editor.once("after-suggest");
   }
 
-  // Also listening for popup hiding if needed.
-  let onMaybePopupHidden = expectPopupHiddenEvent
-                           ? once(editor.popup._panel, "hidden")
-                           : null;
+  // Also listening for popup opened/closed events if needed.
+  let popupEvent = open ? "popup-opened" : "popup-closed";
+  let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
 
   info("Synthesizing key " + key);
   EventUtils.synthesizeKey(key, {}, view.styleWindow);
 
   yield onSuggest;
-  yield onMaybePopupHidden;
+  yield onPopupEvent;
 
   info("Checking the state");
-  if (completion != null) {
+  if (completion !== null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
   if (!open) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
-    ok(editor.popup._panel.state == "open" ||
-       editor.popup._panel.state == "showing", "Popup is open");
-    is(editor.popup.selectedIndex != -1, selected, "An item is selected");
+    ok(editor.popup.isOpen, "Popup is open");
+    is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-existing-property_02.js
@@ -87,28 +87,33 @@ function* testCompletion([key, modifiers
     // Otherwise, expect an after-suggest event (except if the popup gets
     // closed).
     onDone = key !== "VK_RIGHT" && key !== "VK_BACK_SPACE"
              ? editor.once("after-suggest")
              : null;
   }
 
   info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
+
+  // Also listening for popup opened/closed events if needed.
+  let popupEvent = open ? "popup-opened" : "popup-closed";
+  let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
+
   EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
   yield onDone;
+  yield onPopupEvent;
 
   // The key might have been a TAB or shift-TAB, in which case the editor will
   // be a new one
   editor = inplaceEditor(view.styleDocument.activeElement);
 
   info("Checking the state");
-  if (completion != null) {
+  if (completion !== null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
 
   if (!open) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
-    ok(editor.popup._panel.state == "open" ||
-       editor.popup._panel.state == "showing", "Popup is open");
-    is(editor.popup.selectedIndex != -1, selected, "An item is selected");
+    ok(editor.popup.isOpen, "Popup is open");
+    is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_01.js
@@ -58,42 +58,45 @@ function* runAutocompletionTest(toolbox,
   let editor = yield focusNewRuleViewProperty(ruleEditor);
 
   info("Starting to test for css property completion");
   for (let i = 0; i < testData.length; i++) {
     yield testCompletion(testData[i], editor, view);
   }
 }
 
-function* testCompletion([key, completion, isOpen, isSelected], editor, view) {
+function* testCompletion([key, completion, open, isSelected], editor, view) {
   info("Pressing key " + key);
   info("Expecting " + completion);
-  info("Is popup opened: " + isOpen);
+  info("Is popup opened: " + open);
   info("Is item selected: " + isSelected);
 
   let onSuggest;
 
   if (/(right|back_space|escape)/ig.test(key)) {
     info("Adding event listener for right|back_space|escape keys");
     onSuggest = once(editor.input, "keypress");
   } else {
     info("Waiting for after-suggest event on the editor");
     onSuggest = editor.once("after-suggest");
   }
 
+  // Also listening for popup opened/closed events if needed.
+  let popupEvent = open ? "popup-opened" : "popup-closed";
+  let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
+
   info("Synthesizing key " + key);
   EventUtils.synthesizeKey(key, {}, view.styleWindow);
 
   yield onSuggest;
-  yield waitForTick();
+  yield onPopupEvent;
 
   info("Checking the state");
-  if (completion != null) {
+  if (completion !== null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
-  if (!isOpen) {
+  if (!open) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
-    ok(editor.popup._panel.state == "open" ||
-       editor.popup._panel.state == "showing", "Popup is open");
-    is(editor.popup.selectedIndex != -1, isSelected, "An item is selected");
+    ok(editor.popup.isOpen, "Popup is open");
+    is(editor.popup.selectedIndex !== -1, isSelected, "An item is selected");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_02.js
@@ -95,27 +95,31 @@ function* testCompletion([key, modifiers
   } else {
     // Otherwise, expect an after-suggest event (except if the popup gets
     // closed).
     onDone = key !== "VK_RIGHT" && key !== "VK_BACK_SPACE"
              ? editor.once("after-suggest")
              : null;
   }
 
+  // Also listening for popup opened/closed events if needed.
+  let popupEvent = open ? "popup-opened" : "popup-closed";
+  let onPopupEvent = editor.popup.isOpen !== open ? once(editor.popup, popupEvent) : null;
+
   info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
   EventUtils.synthesizeKey(key, modifiers, view.styleWindow);
   yield onDone;
+  yield onPopupEvent;
 
   info("Checking the state");
-  if (completion != null) {
+  if (completion !== null) {
     // The key might have been a TAB or shift-TAB, in which case the editor will
     // be a new one
     editor = inplaceEditor(view.styleDocument.activeElement);
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
   if (!open) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
-    ok(editor.popup._panel.state == "open" ||
-       editor.popup._panel.state == "showing", "Popup is open");
-    is(editor.popup.selectedIndex != -1, selected, "An item is selected");
+    ok(editor.popup.isOpen, "Popup is open");
+    is(editor.popup.selectedIndex !== -1, selected, "An item is selected");
   }
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_03.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_03.js
@@ -36,12 +36,12 @@ function* runAutocompletionTest(toolbox,
 
   let bgcItem = editor.popup.getItemAtIndex(itemIndex);
   is(bgcItem.label, "background-color",
      "check the expected completion element");
 
   editor.popup.selectedIndex = itemIndex;
 
   let node = editor.popup._list.childNodes[itemIndex];
-  EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
+  EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
 
   is(editor.input.value, "background-color", "Correct value is autocompleted");
 }
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_04.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_04.js
@@ -34,18 +34,18 @@ add_task(function* () {
   const itemIndex = 4;
   let bgcItem = editor.popup.getItemAtIndex(itemIndex);
   is(bgcItem.label, "background-color",
     "Check the expected completion element is background-color.");
   editor.popup.selectedIndex = itemIndex;
 
   info("Select the background-color suggestion with a mouse click.");
   let onSuggest = editor.once("after-suggest");
-  let node = editor.popup._list.childNodes[itemIndex];
-  EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
+  let node = editor.popup.elements.get(bgcItem);
+  EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
   yield onSuggest;
   is(editor.input.value, "background-color", "Correct value is autocompleted");
 
   info("Press RETURN to move the focus to a property value editor.");
   let onModifications = waitForNEvents(view, "ruleview-changed", 2);
   EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
   yield onModifications;
 
--- a/devtools/client/inspector/rules/test/browser_rules_completion-new-property_multiline.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-new-property_multiline.js
@@ -55,17 +55,17 @@ add_task(function* () {
   info("Moving the caret next to a number");
   let pos = editor.input.value.indexOf("0deg") + 1;
   editor.input.setSelectionRange(pos, pos);
   is(editor.input.value[editor.input.selectionStart - 1], "0",
     "Input caret is after a 0");
 
   info("Check that UP/DOWN navigates in the input, even when next to a number");
   EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
-  ok(editor.input.selectionStart != pos, "Input caret moved");
+  ok(editor.input.selectionStart !== pos, "Input caret moved");
   is(editor.input.value, LONG_CSS_VALUE, "Input value was not decremented.");
 
   info("Move the caret to the end of the gradient definition.");
   pos = editor.input.value.indexOf("95%") + 3;
   editor.input.setSelectionRange(pos, pos);
 
   info("Sending \", re\" to the editable field.");
   for (let key of ", re") {
@@ -90,18 +90,20 @@ add_task(function* () {
   yield synthesizeKeyForAutocomplete("VK_UP", editor, view.styleWindow);
   is(editor.popup.selectedIndex, 1, "Using UP cycles autocomplete values.");
   item = editor.popup.getItemAtIndex(editor.popup.selectedIndex);
   is(item.label, "red", "Check autocomplete displays expected value.");
 
   info("Select the background-color suggestion with a mouse click.");
   let onRuleviewChanged = view.once("ruleview-changed");
   let onSuggest = editor.once("after-suggest");
+
   let node = editor.popup._list.childNodes[editor.popup.selectedIndex];
-  EventUtils.synthesizeMouseAtCenter(node, {}, view.styleWindow);
+  EventUtils.synthesizeMouseAtCenter(node, {}, editor.popup._window);
+
   yield onSuggest;
   yield onRuleviewChanged;
 
   is(editor.input.value, EXPECTED_CSS_VALUE,
     "Input value correctly autocompleted");
 
   info("Press ESCAPE to leave the input.");
   onRuleviewChanged = view.once("ruleview-changed");
--- a/devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
+++ b/devtools/client/inspector/rules/test/browser_rules_completion-popup-hidden-after-navigation.js
@@ -19,21 +19,23 @@ add_task(function* () {
 
   info("Focusing the css property editable field");
   let propertyName = view.styleDocument
     .querySelectorAll(".ruleview-propertyname")[0];
   let editor = yield focusEditableField(view, propertyName);
 
   info("Pressing key VK_DOWN");
   let onSuggest = once(editor.input, "keypress");
+  let onPopupOpened = once(editor.popup, "popup-opened");
+
   EventUtils.synthesizeKey("VK_DOWN", {}, view.styleWindow);
 
   info("Waiting for autocomplete popup to be displayed");
   yield onSuggest;
-  yield waitForTick();
+  yield onPopupOpened;
 
   ok(view.popup && view.popup.isOpen, "Popup should be opened");
 
   info("Reloading the page");
   yield reloadPage(inspector, testActor);
 
   ok(!(view.popup && view.popup.isOpen), "Popup should be closed");
 });
--- a/devtools/client/inspector/test/browser_inspector_search-navigation.js
+++ b/devtools/client/inspector/test/browser_inspector_search-navigation.js
@@ -9,43 +9,43 @@
 // Test data as pairs of [key to press, expected content of searchbox].
 const KEY_STATES = [
   ["d", "d"],
   ["i", "di"],
   ["v", "div"],
   [".", "div."],
   ["VK_UP", "div.c1"],
   ["VK_DOWN", "div.l1"],
-  ["VK_DOWN", "div.l1"],
   ["VK_BACK_SPACE", "div.l"],
   ["VK_TAB", "div.l1"],
   [" ", "div.l1 "],
   ["VK_UP", "div.l1 div"],
+  ["VK_UP", "div.l1 span"],
   ["VK_UP", "div.l1 div"],
   [".", "div.l1 div."],
   ["VK_TAB", "div.l1 div.c1"],
   ["VK_BACK_SPACE", "div.l1 div.c"],
   ["VK_BACK_SPACE", "div.l1 div."],
   ["VK_BACK_SPACE", "div.l1 div"],
   ["VK_BACK_SPACE", "div.l1 di"],
   ["VK_BACK_SPACE", "div.l1 d"],
   ["VK_BACK_SPACE", "div.l1 "],
   ["VK_UP", "div.l1 div"],
   ["VK_BACK_SPACE", "div.l1 di"],
   ["VK_BACK_SPACE", "div.l1 d"],
   ["VK_BACK_SPACE", "div.l1 "],
   ["VK_UP", "div.l1 div"],
+  ["VK_UP", "div.l1 span"],
   ["VK_UP", "div.l1 div"],
   ["VK_TAB", "div.l1 div"],
   ["VK_BACK_SPACE", "div.l1 di"],
   ["VK_BACK_SPACE", "div.l1 d"],
   ["VK_BACK_SPACE", "div.l1 "],
   ["VK_DOWN", "div.l1 div"],
   ["VK_DOWN", "div.l1 span"],
-  ["VK_DOWN", "div.l1 span"],
   ["VK_BACK_SPACE", "div.l1 spa"],
   ["VK_BACK_SPACE", "div.l1 sp"],
   ["VK_BACK_SPACE", "div.l1 s"],
   ["VK_BACK_SPACE", "div.l1 "],
   ["VK_BACK_SPACE", "div.l1"],
   ["VK_BACK_SPACE", "div.l"],
   ["VK_BACK_SPACE", "div."],
   ["VK_BACK_SPACE", "div"],
@@ -63,11 +63,14 @@ add_task(function* () {
 
   for (let [key, query] of KEY_STATES) {
     info("Pressing key " + key + " to get searchbox value as " + query);
 
     let done = inspector.searchSuggestions.once("processing-done");
     EventUtils.synthesizeKey(key, {}, inspector.panelWin);
     yield done;
 
-    is(inspector.searchBox.value, query, "The searchbox value is correct.");
+    info("Waiting for search query to complete");
+    yield inspector.searchSuggestions._lastQuery;
+
+    is(inspector.searchBox.value, query, "The searchbox value is correct");
   }
 });
--- a/devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
@@ -43,26 +43,27 @@ const mockGetCSSPropertyList = function 
 };
 
 add_task(function* () {
   yield addTab("data:text/html;charset=utf-8," +
     "inplace editor CSS property autocomplete");
   let [host, win, doc] = yield createHost();
 
   let xulDocument = win.top.document;
-  let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
+  let popup = new AutocompletePopup({ doc: xulDocument }, { autoSelect: true });
   yield new Promise(resolve => {
     createInplaceEditorAndClick({
       start: runPropertyAutocompletionTest,
       contentType: InplaceEditor.CONTENT_TYPES.CSS_PROPERTY,
       done: resolve,
       popup: popup
     }, doc);
   });
 
+  popup.destroy();
   host.destroy();
   gBrowser.removeCurrentTab();
 });
 
 let runPropertyAutocompletionTest = Task.async(function* (editor) {
   info("Starting to test for css property completion");
   editor._getCSSPropertyList = mockGetCSSPropertyList;
 
--- a/devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
@@ -44,30 +44,31 @@ const mockGetCSSValuesForPropertyName = 
 };
 
 add_task(function* () {
   yield addTab("data:text/html;charset=utf-8," +
     "inplace editor CSS value autocomplete");
   let [host, win, doc] = yield createHost();
 
   let xulDocument = win.top.document;
-  let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
+  let popup = new AutocompletePopup({ doc: xulDocument }, { autoSelect: true });
 
   yield new Promise(resolve => {
     createInplaceEditorAndClick({
       start: runAutocompletionTest,
       contentType: InplaceEditor.CONTENT_TYPES.CSS_VALUE,
       property: {
         name: "display"
       },
       done: resolve,
       popup: popup
     }, doc);
   });
 
+  popup.destroy();
   host.destroy();
   gBrowser.removeCurrentTab();
 });
 
 let runAutocompletionTest = Task.async(function* (editor) {
   info("Starting to test for css property completion");
   editor._getCSSValuesForPropertyName = mockGetCSSValuesForPropertyName;
 
--- a/devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
@@ -4,16 +4,24 @@
 /* import-globals-from helper_inplace_editor.js */
 
 "use strict";
 
 const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
 const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
 loadHelperScript("helper_inplace_editor.js");
 
+const TEST_URI = `data:text/xml;charset=UTF-8,<?xml version="1.0"?>
+  <?xml-stylesheet href="chrome://global/skin/global.css"?>
+  <?xml-stylesheet href="chrome://devtools/skin/common.css"?>
+  <?xml-stylesheet href="chrome://devtools/skin/tooltips.css"?>
+  <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+   title="Tooltip test">
+  </window>`;
+
 // Test the inplace-editor autocomplete popup is aligned with the completed query.
 // Which means when completing "style=display:flex; color:" the popup will aim to be
 // aligned with the ":" next to "color".
 
 // format :
 //  [
 //    what key to press,
 //    expected input box value after keypress,
@@ -54,32 +62,32 @@ const mockGetCSSValuesForPropertyName = 
     "color": ["blue", "red"],
     "display": ["block", "flex", "none"]
   };
   return values[propertyName] || [];
 };
 
 add_task(function* () {
   yield addTab("data:text/html;charset=utf-8,inplace editor CSS value autocomplete");
-  let [host, win, doc] = yield createHost();
+  let [host,, doc] = yield createHost("bottom", TEST_URI);
 
-  let xulDocument = win.top.document;
-  let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
+  let popup = new AutocompletePopup({ doc }, { autoSelect: true });
 
   info("Create a CSS_MIXED type autocomplete");
   yield new Promise(resolve => {
     createInplaceEditorAndClick({
       initial: "style=",
       start: runAutocompletionTest,
       contentType: InplaceEditor.CONTENT_TYPES.CSS_MIXED,
       done: resolve,
       popup: popup
     }, doc);
   });
 
+  popup.destroy();
   host.destroy();
   gBrowser.removeCurrentTab();
 });
 
 let runAutocompletionTest = Task.async(function* (editor) {
   info("Starting autocomplete test for inplace-editor popup offset");
   editor._getCSSPropertyList = mockGetCSSPropertyList;
   editor._getCSSValuesForPropertyName = mockGetCSSValuesForPropertyName;
--- a/devtools/client/shared/test/helper_inplace_editor.js
+++ b/devtools/client/shared/test/helper_inplace_editor.js
@@ -1,59 +1,70 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 /* eslint no-unused-vars: [2, {"vars": "local", "args": "none"}] */
+/* import-globals-from head.js */
 
 "use strict";
 
 /**
  * Helper methods for the HTMLTooltip integration tests.
  */
 
+const HTML_NS = "http://www.w3.org/1999/xhtml";
 const { editableField } = require("devtools/client/shared/inplace-editor");
 
 /**
  * Create an inplace editor linked to a span element and click on the span to
  * to turn to edit mode.
  *
  * @param {Object} options
  *        Options passed to the InplaceEditor/editableField constructor.
  * @param {Document} doc
  *        Document where the span element will be created.
  * @param {String} textContent
  *        (optional) String that will be used as the text content of the span.
  */
-function createInplaceEditorAndClick(options, doc, textContent) {
-  doc.body.innerHTML = "";
+const createInplaceEditorAndClick = Task.async(function* (options, doc, textContent) {
   let span = options.element = createSpan(doc);
   if (textContent) {
     span.textContent = textContent;
   }
 
   info("Creating an inplace-editor field");
   editableField(options);
 
   info("Clicking on the inplace-editor field to turn to edit mode");
   span.click();
-}
+});
 
 /**
  * Helper to create a span in the provided document.
  *
  * @param {Document} doc
  *        Document where the span element will be created.
  * @return {Element} the created span element.
  */
 function createSpan(doc) {
   info("Creating a new span element");
-  let span = doc.createElement("span");
+  let div = doc.createElementNS(HTML_NS, "div");
+  let span = doc.createElementNS(HTML_NS, "span");
   span.setAttribute("tabindex", "0");
   span.style.fontSize = "11px";
+  span.style.display = "inline-block";
+  span.style.width = "100px";
+  span.style.border = "1px solid red";
   span.style.fontFamily = "monospace";
-  doc.body.appendChild(span);
+
+  div.style.height = "100%";
+  div.style.position = "absolute";
+  div.appendChild(span);
+
+  let parent = doc.querySelector("window") || doc.body;
+  parent.appendChild(div);
   return span;
 }
 
 /**
  * Test helper simulating a key event in an InplaceEditor and checking that the
  * autocompletion works as expected.
  *
  * @param {Array} testData
@@ -63,37 +74,42 @@ function createSpan(doc) {
  *        - {Number} total, the total number of suggestions in the popup
  * @param {InplaceEditor} editor
  *        The InplaceEditor instance being tested
  */
 function* testCompletion([key, completion, index, total], editor) {
   info("Pressing key " + key);
   info("Expecting " + completion);
 
+  let onVisibilityChange = null;
+  let open = total > 0;
+  if (editor.popup.isOpen != open) {
+    onVisibilityChange = editor.popup.once(open ? "popup-opened" : "popup-closed");
+  }
+
   let onSuggest;
-
   if (/(left|right|back_space|escape)/ig.test(key)) {
     info("Adding event listener for right|back_space|escape keys");
     onSuggest = once(editor.input, "keypress");
   } else {
     info("Waiting for after-suggest event on the editor");
     onSuggest = editor.once("after-suggest");
   }
 
   info("Synthesizing key " + key);
   EventUtils.synthesizeKey(key, {}, editor.input.defaultView);
 
   yield onSuggest;
+  yield onVisibilityChange;
   yield waitForTick();
 
   info("Checking the state");
-  if (completion != null) {
+  if (completion !== null) {
     is(editor.input.value, completion, "Correct value is autocompleted");
   }
   if (total === 0) {
     ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
   } else {
-    ok(editor.popup._panel.state == "open" ||
-       editor.popup._panel.state == "showing", "Popup is open");
+    ok(editor.popup.isOpen, "Popup is open");
     is(editor.popup.getItems().length, total, "Number of suggestions match");
     is(editor.popup.selectedIndex, index, "Expected item is selected");
   }
 }
--- a/devtools/client/webconsole/test/browser_webconsole_autocomplete_popup_close_on_tab_switch.js
+++ b/devtools/client/webconsole/test/browser_webconsole_autocomplete_popup_close_on_tab_switch.js
@@ -9,17 +9,17 @@
 
 const TEST_URI = "data:text/html;charset=utf-8,<p>bug 900448 - autocomplete " +
                  "popup closes on tab switch";
 
 add_task(function* () {
   yield loadTab(TEST_URI);
   let hud = yield openConsole();
   let popup = hud.jsterm.autocompletePopup;
-  let popupShown = once(popup._panel, "popupshown");
+  let popupShown = once(popup, "popup-opened");
 
   hud.jsterm.setInputValue("sc");
   EventUtils.synthesizeKey("r", {});
 
   yield popupShown;
 
   yield loadTab("data:text/html;charset=utf-8,<p>testing autocomplete closes");
 
--- a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_keys.js
@@ -25,19 +25,19 @@ add_task(function* () {
   yield popupHideAfterReturnWithNoSelection();
   yield testCompletionInText();
   yield popupHideAfterCompletionInText();
 
   HUD = popup = jsterm = inputNode = completeNode = null;
   Services.prefs.setBoolPref(PREF_AUTO_MULTILINE, true);
 });
 
-var consoleOpened = Task.async(function* (aHud) {
+var consoleOpened = Task.async(function* (hud) {
   let deferred = promise.defer();
-  HUD = aHud;
+  HUD = hud;
   info("web console opened");
 
   jsterm = HUD.jsterm;
 
   yield jsterm.execute("window.foobarBug585991={" +
     "'item0': 'value0'," +
     "'item1': 'value1'," +
     "'item2': 'value2'," +
@@ -46,30 +46,29 @@ var consoleOpened = Task.async(function*
   yield jsterm.execute("window.testBug873250a = 'hello world';"
     + "window.testBug873250b = 'hello world 2';");
   popup = jsterm.autocompletePopup;
   completeNode = jsterm.completeNode;
   inputNode = jsterm.inputNode;
 
   ok(!popup.isOpen, "popup is not open");
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown, false);
-
+  popup.once("popup-opened", () => {
     ok(popup.isOpen, "popup is open");
 
     // 4 values, and the following properties:
     // __defineGetter__  __defineSetter__ __lookupGetter__ __lookupSetter__
     // __proto__ hasOwnProperty isPrototypeOf propertyIsEnumerable
     // toLocaleString toString toSource unwatch valueOf watch constructor.
     is(popup.itemCount, 19, "popup.itemCount is correct");
 
     let sameItems = popup.getItems().reverse().map(function (e) {
       return e.label;
     });
+
     ok(sameItems.every(function (prop, index) {
       return [
         "__defineGetter__",
         "__defineSetter__",
         "__lookupGetter__",
         "__lookupSetter__",
         "__proto__",
         "constructor",
@@ -129,24 +128,22 @@ var consoleOpened = Task.async(function*
 
     EventUtils.synthesizeKey("VK_END", {});
     is(popup.selectedIndex, 18, "index is last after End");
 
     EventUtils.synthesizeKey("VK_HOME", {});
     is(popup.selectedIndex, 0, "index is first after Home");
 
     info("press Tab and wait for popup to hide");
-    popup._panel.addEventListener("popuphidden", function popupHidden() {
-      popup._panel.removeEventListener("popuphidden", popupHidden, false);
+    popup.once("popup-closed", () => {
       deferred.resolve();
-    }, false);
+    });
     EventUtils.synthesizeKey("VK_TAB", {});
-  }, false);
+  });
 
-  info("wait for completion: window.foobarBug585991.");
   jsterm.setInputValue("window.foobarBug585991");
   EventUtils.synthesizeKey(".", {});
 
   return deferred.promise;
 });
 
 function popupHideAfterTab() {
   let deferred = promise.defer();
@@ -154,36 +151,32 @@ function popupHideAfterTab() {
   // At this point the completion suggestion should be accepted.
   ok(!popup.isOpen, "popup is not open");
 
   is(jsterm.getInputValue(), "window.foobarBug585991.watch",
      "completion was successful after VK_TAB");
 
   ok(!completeNode.value, "completeNode is empty");
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown, false);
-
+  popup.once("popup-opened", function onShown() {
     ok(popup.isOpen, "popup is open");
 
     is(popup.itemCount, 19, "popup.itemCount is correct");
 
     is(popup.selectedIndex, 18, "First index from bottom is selected");
     EventUtils.synthesizeKey("VK_DOWN", {});
 
     let prefix = jsterm.getInputValue().replace(/[\S]/g, " ");
 
     is(popup.selectedIndex, 0, "index 0 is selected");
     is(popup.selectedItem.label, "watch", "watch is selected");
     is(completeNode.value, prefix + "watch",
         "completeNode.value holds watch");
 
-    popup._panel.addEventListener("popuphidden", function onHidden() {
-      popup._panel.removeEventListener("popuphidden", onHidden, false);
-
+    popup.once("popup-closed", function onHidden() {
       ok(!popup.isOpen, "popup is not open after VK_ESCAPE");
 
       is(jsterm.getInputValue(), "window.foobarBug585991.",
          "completion was cancelled");
 
       ok(!completeNode.value, "completeNode is empty");
 
       deferred.resolve();
@@ -202,19 +195,17 @@ function popupHideAfterTab() {
   });
 
   return deferred.promise;
 }
 
 function testReturnKey() {
   let deferred = promise.defer();
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown, false);
-
+  popup.once("popup-opened", function onShown() {
     ok(popup.isOpen, "popup is open");
 
     is(popup.itemCount, 19, "popup.itemCount is correct");
 
     is(popup.selectedIndex, 18, "First index from bottom is selected");
     EventUtils.synthesizeKey("VK_DOWN", {});
 
     let prefix = jsterm.getInputValue().replace(/[\S]/g, " ");
@@ -226,19 +217,17 @@ function testReturnKey() {
 
     EventUtils.synthesizeKey("VK_DOWN", {});
 
     is(popup.selectedIndex, 1, "index 1 is selected");
     is(popup.selectedItem.label, "valueOf", "valueOf is selected");
     is(completeNode.value, prefix + "valueOf",
        "completeNode.value holds valueOf");
 
-    popup._panel.addEventListener("popuphidden", function onHidden() {
-      popup._panel.removeEventListener("popuphidden", onHidden, false);
-
+    popup.once("popup-closed", function onHidden() {
       ok(!popup.isOpen, "popup is not open after VK_RETURN");
 
       is(jsterm.getInputValue(), "window.foobarBug585991.valueOf",
          "completion was successful after VK_RETURN");
 
       ok(!completeNode.value, "completeNode is empty");
 
       deferred.resolve();
@@ -266,28 +255,25 @@ function* dontShowArrayNumbers() {
   info("dontShowArrayNumbers");
   yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
     content.wrappedJSObject.foobarBug585991 = ["Sherlock Holmes"];
   });
 
   jsterm = HUD.jsterm;
   popup = jsterm.autocompletePopup;
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown, false);
-
+  popup.once("popup-opened", function onShown() {
     let sameItems = popup.getItems().map(function (e) {
       return e.label;
     });
     ok(!sameItems.some(function (prop) {
       prop === "0";
     }), "Completing on an array doesn't show numbers.");
 
-    popup._panel.addEventListener("popuphidden", function popupHidden() {
-      popup._panel.removeEventListener("popuphidden", popupHidden, false);
+    popup.once("popup-closed", function popupHidden() {
       deferred.resolve();
     }, false);
 
     info("wait for popup to hide");
     executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {}));
   }, false);
 
   info("wait for popup to show");
@@ -299,26 +285,23 @@ function* dontShowArrayNumbers() {
   return deferred.promise;
 }
 
 function testReturnWithNoSelection() {
   let deferred = promise.defer();
 
   info("test pressing return with open popup, but no selection, see bug 873250");
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown);
-
+  popup.once("popup-opened", function onShown() {
     ok(popup.isOpen, "popup is open");
     is(popup.itemCount, 2, "popup.itemCount is correct");
     isnot(popup.selectedIndex, -1, "popup.selectedIndex is correct");
 
     info("press Return and wait for popup to hide");
-    popup._panel.addEventListener("popuphidden", function popupHidden() {
-      popup._panel.removeEventListener("popuphidden", popupHidden);
+    popup.once("popup-closed", function popupHidden() {
       deferred.resolve();
     });
     executeSoon(() => EventUtils.synthesizeKey("VK_RETURN", {}));
   });
 
   executeSoon(() => {
     info("wait for popup to show");
     jsterm.setInputValue("window.testBu");
@@ -339,34 +322,31 @@ function popupHideAfterReturnWithNoSelec
   return promise.resolve();
 }
 
 function testCompletionInText() {
   info("test that completion works inside text, see bug 812618");
 
   let deferred = promise.defer();
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown);
-
+  popup.once("popup-opened", function onShown() {
     ok(popup.isOpen, "popup is open");
     is(popup.itemCount, 2, "popup.itemCount is correct");
 
     EventUtils.synthesizeKey("VK_DOWN", {});
     is(popup.selectedIndex, 0, "popup.selectedIndex is correct");
     ok(!completeNode.value, "completeNode.value is empty");
 
     let items = popup.getItems().reverse().map(e => e.label);
     let sameItems = items.every((prop, index) =>
       ["testBug873250a", "testBug873250b"][index] === prop);
     ok(sameItems, "getItems returns the items we expect");
 
     info("press Tab and wait for popup to hide");
-    popup._panel.addEventListener("popuphidden", function popupHidden() {
-      popup._panel.removeEventListener("popuphidden", popupHidden);
+    popup.once("popup-closed", function popupHidden() {
       deferred.resolve();
     });
     EventUtils.synthesizeKey("VK_TAB", {});
   });
 
   jsterm.setInputValue("dump(window.testBu)");
   inputNode.selectionStart = inputNode.selectionEnd = 18;
   EventUtils.synthesizeKey("g", {});
--- a/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_585991_autocomplete_popup.js
@@ -21,99 +21,104 @@ function consoleOpened(HUD) {
   let items = [
     {label: "item0", value: "value0"},
     {label: "item1", value: "value1"},
     {label: "item2", value: "value2"},
   ];
 
   let popup = HUD.jsterm.autocompletePopup;
 
-  let input = popup._document.activeElement;
+  let input = popup._findActiveElement();
   function getActiveDescendant() {
-    return input.ownerDocument.getElementById(
-      input.getAttribute("aria-activedescendant"));
+    let descendantId = input.getAttribute("aria-activedescendant");
+    return popup._tooltip.panel.querySelector("#" + descendantId);
   }
 
   ok(!popup.isOpen, "popup is not open");
   ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
 
-  popup._panel.addEventListener("popupshown", function onPopupPanel() {
-    popup._panel.removeEventListener("popupshown", onPopupPanel, false);
-
+  popup.once("popup-opened", () => {
     ok(popup.isOpen, "popup is open");
 
     is(popup.itemCount, 0, "no items");
-    ok(!input.hasAttribute("aria-activedescendant"),
-       "no aria-activedescendant");
+    ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
 
     popup.setItems(items);
 
     is(popup.itemCount, items.length, "items added");
 
     let sameItems = popup.getItems();
-    is(sameItems.every(function (aItem, aIndex) {
-      return aItem === items[aIndex];
+    is(sameItems.every(function (item, index) {
+      return item === items[index];
     }), true, "getItems returns back the same items");
 
-    is(popup.selectedIndex, 2,
-       "Index of the first item from bottom is selected.");
+    is(popup.selectedIndex, 2, "Index of the first item from bottom is selected.");
     is(popup.selectedItem, items[2], "First item from bottom is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
     popup.selectedIndex = 1;
 
     is(popup.selectedIndex, 1, "index 1 is selected");
     is(popup.selectedItem, items[1], "item1 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
     popup.selectedItem = items[2];
 
     is(popup.selectedIndex, 2, "index 2 is selected");
     is(popup.selectedItem, items[2], "item2 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
     is(popup.selectPreviousItem(), items[1], "selectPreviousItem() works");
 
     is(popup.selectedIndex, 1, "index 1 is selected");
     is(popup.selectedItem, items[1], "item1 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
-    is(popup.selectNextItem(), items[2], "selectPreviousItem() works");
+    is(popup.selectNextItem(), items[2], "selectNextItem() works");
 
     is(popup.selectedIndex, 2, "index 2 is selected");
     is(popup.selectedItem, items[2], "item2 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
-    ok(popup.selectNextItem(), "selectPreviousItem() works");
+    ok(popup.selectNextItem(), "selectNextItem() works");
 
     is(popup.selectedIndex, 0, "index 0 is selected");
     is(popup.selectedItem, items[0], "item0 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
     items.push({label: "label3", value: "value3"});
     popup.appendItem(items[3]);
 
     is(popup.itemCount, items.length, "item3 appended");
 
     popup.selectedIndex = 3;
     is(popup.selectedItem, items[3], "item3 is selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
 
     popup.removeItem(items[2]);
 
     is(popup.selectedIndex, 2, "index2 is selected");
     is(popup.selectedItem, items[3], "item3 is still selected");
-    ok(getActiveDescendant().selected, "aria-activedescendant is correct");
+    ok(getActiveDescendant().classList.contains("autocomplete-selected"),
+      "aria-activedescendant is correct");
     is(popup.itemCount, items.length - 1, "item2 removed");
 
     popup.clearItems();
     is(popup.itemCount, 0, "items cleared");
-    ok(!input.hasAttribute("aria-activedescendant"),
-       "no aria-activedescendant");
+    ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
 
+    popup.once("popup-closed", () => {
+      deferred.resolve();
+    });
     popup.hidePopup();
-    deferred.resolve();
-  }, false);
+  });
 
-  popup.openPopup();
+  popup.openPopup(input);
 
   return deferred.promise;
 }
--- a/devtools/client/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_651501_document_body_autocomplete.js
@@ -28,51 +28,47 @@ add_task(function* () {
 function consoleOpened() {
   let deferred = promise.defer();
 
   let jsterm = gHUD.jsterm;
   let popup = jsterm.autocompletePopup;
 
   ok(!popup.isOpen, "popup is not open");
 
-  popup._panel.addEventListener("popupshown", function onShown() {
-    popup._panel.removeEventListener("popupshown", onShown, false);
-
+  popup.once("popup-opened", () => {
     ok(popup.isOpen, "popup is open");
 
     is(popup.itemCount, jsterm._autocompleteCache.length,
        "popup.itemCount is correct");
     isnot(jsterm._autocompleteCache.indexOf("addEventListener"), -1,
           "addEventListener is in the list of suggestions");
     isnot(jsterm._autocompleteCache.indexOf("bgColor"), -1,
           "bgColor is in the list of suggestions");
     isnot(jsterm._autocompleteCache.indexOf("ATTRIBUTE_NODE"), -1,
           "ATTRIBUTE_NODE is in the list of suggestions");
 
-    popup._panel.addEventListener("popuphidden", deferred.resolve, false);
-
+    popup.once("popup-closed", () => {
+      deferred.resolve();
+    });
     EventUtils.synthesizeKey("VK_ESCAPE", {});
-  }, false);
+  });
 
   jsterm.setInputValue("document.body");
   EventUtils.synthesizeKey(".", {});
 
   return deferred.promise;
 }
 
 function autocompletePopupHidden() {
   let deferred = promise.defer();
 
   let jsterm = gHUD.jsterm;
   let popup = jsterm.autocompletePopup;
   let completeNode = jsterm.completeNode;
 
-  popup._panel.removeEventListener("popuphidden", autocompletePopupHidden,
-                                   false);
-
   ok(!popup.isOpen, "popup is not open");
 
   jsterm.once("autocomplete-updated", function () {
     is(completeNode.value, testStr + "dy", "autocomplete shows document.body");
     deferred.resolve();
   });
 
   let inputStr = "document.b";
@@ -84,18 +80,18 @@ function autocompletePopupHidden() {
 }
 
 function testPropertyPanel() {
   let deferred = promise.defer();
 
   let jsterm = gHUD.jsterm;
   jsterm.clearOutput();
   jsterm.execute("document", (msg) => {
-    jsterm.once("variablesview-fetched", (aEvent, aView) => {
-      deferred.resolve(aView);
+    jsterm.once("variablesview-fetched", (evt, view) => {
+      deferred.resolve(view);
     });
     let anchor = msg.querySelector(".message-body a");
     EventUtils.synthesizeMouse(anchor, 2, 2, {}, gHUD.iframeWindow);
   });
 
   return deferred.promise;
 }
 
--- a/devtools/client/webconsole/test/browser_webconsole_bug_660806_history_nav.js
+++ b/devtools/client/webconsole/test/browser_webconsole_bug_660806_history_nav.js
@@ -20,35 +20,35 @@ function consoleOpened(HUD) {
   let deferred = promise.defer();
 
   let jsterm = HUD.jsterm;
   let popup = jsterm.autocompletePopup;
   let onShown = function () {
     ok(false, "popup shown");
   };
 
-  jsterm.execute("window.foobarBug660806 = {\
-    'location': 'value0',\
-    'locationbar': 'value1'\
-  }");
+  jsterm.execute(`window.foobarBug660806 = {
+    'location': 'value0',
+    'locationbar': 'value1'
+  }`);
 
-  popup._panel.addEventListener("popupshown", onShown, false);
+  popup.on("popup-opened", onShown);
 
   ok(!popup.isOpen, "popup is not open");
 
   ok(!jsterm.lastInputValue, "no lastInputValue");
   jsterm.setInputValue("window.foobarBug660806.location");
   is(jsterm.lastInputValue, "window.foobarBug660806.location",
      "lastInputValue is correct");
 
   EventUtils.synthesizeKey("VK_RETURN", {});
   EventUtils.synthesizeKey("VK_UP", {});
 
   is(jsterm.lastInputValue, "window.foobarBug660806.location",
      "lastInputValue is correct, again");
 
   executeSoon(function () {
     ok(!popup.isOpen, "popup is not open");
-    popup._panel.removeEventListener("popupshown", onShown, false);
+    popup.off("popup-opened", onShown);
     executeSoon(deferred.resolve);
   });
   return deferred.promise;
 }
--- a/devtools/client/webconsole/test/browser_webconsole_split_escape_key.js
+++ b/devtools/client/webconsole/test/browser_webconsole_split_escape_key.js
@@ -76,25 +76,24 @@
 
      return result;
    }
 
    function testHideAutoCompletePopupAfterEscape() {
      let deferred = promise.defer();
      let popup = jsterm.autocompletePopup;
 
-     popup._panel.addEventListener("popuphidden", function popupHidden() {
-       popup._panel.removeEventListener("popuphidden", popupHidden, false);
+     popup.once("popup-closed", () => {
        ok(!popup.isOpen,
         "Auto complete popup is hidden.");
        ok(toolbox.splitConsole,
         "Split console is open after hiding the autocomplete popup.");
 
        deferred.resolve();
-     }, false);
+     });
 
      EventUtils.sendKey("ESCAPE", toolbox.win);
 
      return deferred.promise;
    }
 
    function testCancelPropertyEditorAfterEscape() {
      EventUtils.sendKey("ESCAPE", variablesView.window);
@@ -131,29 +130,23 @@
      let results = yield findVariableViewProperties(variablesView, [
       {name: "bar", value: "baz"}
      ], {webconsole: hud});
      results[0].matchedProp.focus();
      EventUtils.synthesizeKey("VK_RETURN", variablesView.window);
    }
 
    function showAutoCompletePopoup() {
-     let deferred = promise.defer();
-     let popupPanel = jsterm.autocompletePopup._panel;
-
-     popupPanel.addEventListener("popupshown", function popupShown() {
-       popupPanel.removeEventListener("popupshown", popupShown, false);
-       deferred.resolve();
-     }, false);
+     let onPopupShown = jsterm.autocompletePopup.once("popup-opened");
 
      jsterm.focus();
      jsterm.setInputValue("document.location.");
      EventUtils.sendKey("TAB", hud.iframeWindow);
 
-     return deferred.promise;
+     return onPopupShown;
    }
 
    function finish() {
      toolbox.destroy().then(() => {
        toolbox = null;
        hud = null;
        jsterm = null;
        hudMessages = null;