Bug 1184525 - Reset previous search results on markup-mutations to make sure we search again. r=pbrosset
authorAli Movahedi <ali_movahedi@aol.com>
Tue, 08 Sep 2015 02:17:00 +0200
changeset 295855 1d7734f397057e126e39e3cac433acc0edd97cf3
parent 295854 e5658e0e9c6dc4e23bdb47573b7c8f6c262a598a
child 295856 6e4be989548155ab1428bcc6bab2a2ca01c37fac
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbrosset
bugs1184525
milestone43.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 1184525 - Reset previous search results on markup-mutations to make sure we search again. r=pbrosset
browser/devtools/inspector/selector-search.js
browser/devtools/inspector/test/browser.ini
browser/devtools/inspector/test/browser_inspector_search-06.js
--- a/browser/devtools/inspector/selector-search.js
+++ b/browser/devtools/inspector/selector-search.js
@@ -41,16 +41,17 @@ function SelectorSearch(aInspector, aInp
   this._searchSuggestions = {};
   this._searchIndex = 0;
 
   // bind!
   this._showPopup = this._showPopup.bind(this);
   this._onHTMLSearch = this._onHTMLSearch.bind(this);
   this._onSearchKeypress = this._onSearchKeypress.bind(this);
   this._onListBoxKeypress = this._onListBoxKeypress.bind(this);
+  this._onMarkupMutation = this._onMarkupMutation.bind(this);
 
   // Options for the AutocompletePopup.
   let options = {
     panelId: "inspector-searchbox-panel",
     listBoxId: "searchbox-panel-listbox",
     autoSelect: true,
     position: "before_start",
     direction: "ltr",
@@ -58,16 +59,17 @@ function SelectorSearch(aInspector, aInp
     onClick: this._onListBoxKeypress,
     onKeypress: this._onListBoxKeypress
   };
   this.searchPopup = new AutocompletePopup(this.panelDoc, options);
 
   // event listeners.
   this.searchBox.addEventListener("command", this._onHTMLSearch, true);
   this.searchBox.addEventListener("keypress", this._onSearchKeypress, true);
+  this.inspector.on("markupmutation", this._onMarkupMutation);
 
   // For testing, we need to be able to wait for the most recent node request
   // to finish.  Tests can watch this promise for that.
   this._lastQuery = promise.resolve(null);
   EventEmitter.decorate(this);
 }
 
 exports.SelectorSearch = SelectorSearch;
@@ -165,16 +167,17 @@ SelectorSearch.prototype = {
 
   /**
    * Removes event listeners and cleans up references.
    */
   destroy: function() {
     // event listeners.
     this.searchBox.removeEventListener("command", this._onHTMLSearch, true);
     this.searchBox.removeEventListener("keypress", this._onSearchKeypress, true);
+    this.inspector.off("markupmutation", this._onMarkupMutation);
     this.searchPopup.destroy();
     this.searchPopup = null;
     this.searchBox = null;
     this.panelDoc = null;
     this._searchResults = null;
     this._searchSuggestions = null;
   },
 
@@ -419,16 +422,25 @@ SelectorSearch.prototype = {
                                  ["",""])[1];
         this._onHTMLSearch();
         break;
     }
     this.emit("processing-done");
   },
 
   /**
+   * Reset previous search results on markup-mutations to make sure we search
+   * again after nodes have been added/removed/changed.
+   */
+  _onMarkupMutation: function() {
+    this._searchResults = null;
+    this._lastSearched = null;
+  },
+
+  /**
    * Populates the suggestions list and show the suggestion popup.
    */
   _showPopup: function(aList, aFirstPart, aState) {
     let total = 0;
     let query = this.searchBox.value;
     let items = [];
 
     for (let [value, count, state] of aList) {
--- a/browser/devtools/inspector/test/browser.ini
+++ b/browser/devtools/inspector/test/browser.ini
@@ -97,14 +97,15 @@ skip-if = e10s # GCLI isn't e10s compati
 [browser_inspector_remove-iframe-during-load.js]
 [browser_inspector_scrolling.js]
 skip-if = e10s # Test synthesize scrolling events in content. Also, see bug 1035661.
 [browser_inspector_search-01.js]
 [browser_inspector_search-02.js]
 [browser_inspector_search-03.js]
 [browser_inspector_search-04.js]
 [browser_inspector_search-05.js]
+[browser_inspector_search-06.js]
 [browser_inspector_search-reserved.js]
 [browser_inspector_select-docshell.js]
 [browser_inspector_select-last-selected.js]
 [browser_inspector_search-navigation.js]
 [browser_inspector_sidebarstate.js]
 [browser_inspector_switch-to-inspector-on-pick.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/inspector/test/browser_inspector_search-06.js
@@ -0,0 +1,76 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+// Check that searching again for nodes after they are removed or added from the
+// DOM works correctly.
+
+const TEST_URL = TEST_URL_ROOT + "doc_inspector_search.html";
+
+add_task(function* () {
+  let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
+
+  info("Searching for test node #d1");
+  yield focusSearchBoxUsingShortcut(inspector.panelWin);
+  yield synthesizeKeys(["#", "d", "1"], inspector);
+
+  assertHasResult(inspector, true);
+
+  info("Removing node #d1");
+  yield mutatePage(inspector, testActor,
+                   "document.getElementById(\"d1\").remove()");
+
+  info("Pressing return button to search again for node #d1.");
+  yield synthesizeKeys("VK_RETURN", inspector);
+
+  assertHasResult(inspector, false);
+
+  info("Emptying the field and searching for a node that doesn't exist: #d3");
+  let keys = ["VK_BACK_SPACE", "VK_BACK_SPACE", "VK_BACK_SPACE", "#", "d", "3"];
+  yield synthesizeKeys(keys, inspector);
+
+  assertHasResult(inspector, false);
+
+  info("Create the #d3 node in the page");
+  yield mutatePage(inspector, testActor,
+                   `document.getElementById("d2").insertAdjacentHTML(
+                    "afterend", "<div id=d3></div>")`);
+
+  info("Pressing return button to search again for node #d3.");
+  yield synthesizeKeys("VK_RETURN", inspector);
+
+  assertHasResult(inspector, true);
+
+  // Catch-all event for remaining server requests when searching for the new
+  // node.
+  yield inspector.once("inspector-updated");
+});
+
+function* synthesizeKeys(keys, inspector) {
+  if (typeof keys === "string") {
+    keys = [keys];
+  }
+
+  for (let key of keys) {
+    info("Synthesizing key " + key + " in the search box");
+    let eventHandled = once(inspector.searchBox, "keypress", true);
+    EventUtils.synthesizeKey(key, {}, inspector.panelWin);
+    yield eventHandled;
+    info("Waiting for the search query to complete");
+    yield inspector.searchSuggestions._lastQuery;
+  }
+}
+
+function assertHasResult(inspector, expectResult) {
+  is(inspector.searchBox.classList.contains("devtools-no-search-result"),
+     !expectResult,
+     "There are" + (expectResult ? "" : " no") + " search results");
+}
+
+function* mutatePage(inspector, testActor, expression) {
+  let onUpdated = inspector.once("inspector-updated");
+  yield testActor.eval(expression);
+  yield onUpdated;
+}