Bug 913983 - Split browser_telemetry_buttonsandsidebar.js into 5 tests due to timeouts. r=jwalker, a=test-only
authorMichael Ratcliffe <mratcliffe@mozilla.com>
Fri, 27 Sep 2013 17:48:37 +0100
changeset 160533 061938a3b99001b032890d55400c38760f0ac0bf
parent 160532 3eeec6a3090d56cea4ce0e3299367c363fb7b2a5
child 160534 acdf04eaaceb6ac55cadbdb40affec2b0a55ebb4
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalker, test-only
bugs913983
milestone26.0a2
Bug 913983 - Split browser_telemetry_buttonsandsidebar.js into 5 tests due to timeouts. r=jwalker, a=test-only
browser/devtools/shared/test/Makefile.in
browser/devtools/shared/test/browser_telemetry_button_paintflashing.js
browser/devtools/shared/test/browser_telemetry_button_responsive.js
browser/devtools/shared/test/browser_telemetry_button_scratchpad.js
browser/devtools/shared/test/browser_telemetry_button_tilt.js
browser/devtools/shared/test/browser_telemetry_buttonsandsidebar.js
browser/devtools/shared/test/browser_telemetry_sidebar.js
browser/devtools/shared/test/head.js
--- a/browser/devtools/shared/test/Makefile.in
+++ b/browser/devtools/shared/test/Makefile.in
@@ -3,17 +3,21 @@
 # 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/.
 
 MOCHITEST_BROWSER_FILES = \
 		browser_eventemitter_basic.js \
 		browser_observableobject.js \
 		browser_layoutHelpers.js \
 		browser_require_basic.js \
-		browser_telemetry_buttonsandsidebar.js \
+		browser_telemetry_sidebar.js \
+		browser_telemetry_button_responsive.js \
+		browser_telemetry_button_scratchpad.js \
+		browser_telemetry_button_tilt.js \
+		browser_telemetry_button_paintflashing.js \
 		browser_telemetry_toolboxtabs_inspector.js \
 		browser_telemetry_toolboxtabs_jsdebugger.js \
 		browser_telemetry_toolboxtabs_jsprofiler.js \
 		browser_telemetry_toolboxtabs_netmonitor.js \
 		browser_telemetry_toolboxtabs_options.js \
 		browser_telemetry_toolboxtabs_styleeditor.js \
 		browser_telemetry_toolboxtabs_webconsole.js \
 		browser_templater_basic.js \
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_telemetry_button_paintflashing.js
@@ -0,0 +1,127 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_paintflashing.js</p>";
+
+// Because we need to gather stats for the period of time that a tool has been
+// opened we make use of setTimeout() to create tool active times.
+const TOOL_DELAY = 200;
+
+let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
+let Telemetry = require("devtools/shared/telemetry");
+
+function init() {
+  Telemetry.prototype.telemetryInfo = {};
+  Telemetry.prototype._oldlog = Telemetry.prototype.log;
+  Telemetry.prototype.log = function(histogramId, value) {
+    if (histogramId) {
+      if (!this.telemetryInfo[histogramId]) {
+        this.telemetryInfo[histogramId] = [];
+      }
+
+      this.telemetryInfo[histogramId].push(value);
+    }
+  };
+
+  testButton("command-button-paintflashing");
+}
+
+function testButton(id) {
+  info("Testing " + id);
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+    info("inspector opened");
+
+    let button = toolbox.doc.querySelector("#" + id);
+    ok(button, "Captain, we have the button");
+
+    delayedClicks(button, 4).then(function() {
+      checkResults("_PAINTFLASHING_");
+    });
+  }).then(null, console.error);
+}
+
+function delayedClicks(node, clicks) {
+  let deferred = promise.defer();
+  let clicked = 0;
+
+  // See TOOL_DELAY for why we need setTimeout here
+  setTimeout(function delayedClick() {
+    info("Clicking button " + node.id);
+    node.click();
+    clicked++;
+
+    if (clicked >= clicks) {
+      deferred.resolve(node);
+    } else {
+      setTimeout(delayedClick, TOOL_DELAY);
+    }
+  }, TOOL_DELAY);
+
+  return deferred.promise;
+}
+
+function checkResults(histIdFocus) {
+  let result = Telemetry.prototype.telemetryInfo;
+
+  for (let [histId, value] of Iterator(result)) {
+    if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
+        !histId.contains(histIdFocus)) {
+      // Inspector stats are tested in
+      // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
+      // because we only open the inspector once for this test.
+      continue;
+    }
+
+    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
+      ok(value.length === 1 && value[0] === true,
+         "Per user value " + histId + " has a single value of true");
+    } else if (histId.endsWith("OPENED_BOOLEAN")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element === true;
+      });
+
+      ok(okay, "All " + histId + " entries are === true");
+    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element > 0;
+      });
+
+      ok(okay, "All " + histId + " entries have time > 0");
+    }
+  }
+
+  finishUp();
+}
+
+function finishUp() {
+  gBrowser.removeCurrentTab();
+
+  Telemetry.prototype.log = Telemetry.prototype._oldlog;
+  delete Telemetry.prototype._oldlog;
+  delete Telemetry.prototype.telemetryInfo;
+
+  TargetFactory = Services = promise = require = null;
+
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    waitForFocus(init, content);
+  }, true);
+
+  content.location = TEST_URI;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_telemetry_button_responsive.js
@@ -0,0 +1,127 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_responsive.js</p>";
+
+// Because we need to gather stats for the period of time that a tool has been
+// opened we make use of setTimeout() to create tool active times.
+const TOOL_DELAY = 200;
+
+let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
+let Telemetry = require("devtools/shared/telemetry");
+
+function init() {
+  Telemetry.prototype.telemetryInfo = {};
+  Telemetry.prototype._oldlog = Telemetry.prototype.log;
+  Telemetry.prototype.log = function(histogramId, value) {
+    if (histogramId) {
+      if (!this.telemetryInfo[histogramId]) {
+        this.telemetryInfo[histogramId] = [];
+      }
+
+      this.telemetryInfo[histogramId].push(value);
+    }
+  };
+
+  testButton("command-button-responsive");
+}
+
+function testButton(id) {
+  info("Testing " + id);
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+    info("inspector opened");
+
+    let button = toolbox.doc.querySelector("#" + id);
+    ok(button, "Captain, we have the button");
+
+    delayedClicks(button, 4).then(function() {
+      checkResults("_RESPONSIVE_");
+    });
+  }).then(null, console.error);
+}
+
+function delayedClicks(node, clicks) {
+  let deferred = promise.defer();
+  let clicked = 0;
+
+  // See TOOL_DELAY for why we need setTimeout here
+  setTimeout(function delayedClick() {
+    info("Clicking button " + node.id);
+    node.click();
+    clicked++;
+
+    if (clicked >= clicks) {
+      deferred.resolve(node);
+    } else {
+      setTimeout(delayedClick, TOOL_DELAY);
+    }
+  }, TOOL_DELAY);
+
+  return deferred.promise;
+}
+
+function checkResults(histIdFocus) {
+  let result = Telemetry.prototype.telemetryInfo;
+
+  for (let [histId, value] of Iterator(result)) {
+    if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
+        !histId.contains(histIdFocus)) {
+      // Inspector stats are tested in
+      // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
+      // because we only open the inspector once for this test.
+      continue;
+    }
+
+    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
+      ok(value.length === 1 && value[0] === true,
+         "Per user value " + histId + " has a single value of true");
+    } else if (histId.endsWith("OPENED_BOOLEAN")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element === true;
+      });
+
+      ok(okay, "All " + histId + " entries are === true");
+    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element > 0;
+      });
+
+      ok(okay, "All " + histId + " entries have time > 0");
+    }
+  }
+
+  finishUp();
+}
+
+function finishUp() {
+  gBrowser.removeCurrentTab();
+
+  Telemetry.prototype.log = Telemetry.prototype._oldlog;
+  delete Telemetry.prototype._oldlog;
+  delete Telemetry.prototype.telemetryInfo;
+
+  TargetFactory = Services = promise = require = null;
+
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    waitForFocus(init, content);
+  }, true);
+
+  content.location = TEST_URI;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_telemetry_button_scratchpad.js
@@ -0,0 +1,155 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_scratchpad.js</p>";
+
+// Because we need to gather stats for the period of time that a tool has been
+// opened we make use of setTimeout() to create tool active times.
+const TOOL_DELAY = 200;
+
+let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
+let Telemetry = require("devtools/shared/telemetry");
+
+let numScratchpads = 0;
+
+function init() {
+  Telemetry.prototype.telemetryInfo = {};
+  Telemetry.prototype._oldlog = Telemetry.prototype.log;
+  Telemetry.prototype.log = function(histogramId, value) {
+    if (histogramId) {
+      if (!this.telemetryInfo[histogramId]) {
+        this.telemetryInfo[histogramId] = [];
+      }
+
+      this.telemetryInfo[histogramId].push(value);
+    }
+  };
+
+  Services.ww.registerNotification(windowObserver);
+  testButton("command-button-scratchpad");
+}
+
+function testButton(id) {
+  info("Testing " + id);
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+    info("inspector opened");
+
+    let button = toolbox.doc.querySelector("#" + id);
+    ok(button, "Captain, we have the button");
+
+    delayedClicks(button, 4).then(null, console.error);
+  }).then(null, console.error);
+}
+
+function windowObserver(aSubject, aTopic, aData) {
+  if (aTopic == "domwindowopened") {
+    let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
+    win.addEventListener("load", function onLoad() {
+      win.removeEventListener("load", onLoad, false);
+
+      if (win.Scratchpad) {
+        win.Scratchpad.addObserver({
+          onReady: function() {
+            win.Scratchpad.removeObserver(this);
+            numScratchpads++;
+            win.close();
+
+            info("another scratchpad was opened and closed, count is now " + numScratchpads);
+
+            if (numScratchpads === 4) {
+              Services.ww.unregisterNotification(windowObserver);
+              info("4 scratchpads have been opened and closed, checking results");
+              checkResults("_SCRATCHPAD_");
+            }
+          },
+        });
+      }
+    }, false);
+  }
+}
+
+function delayedClicks(node, clicks) {
+  let deferred = promise.defer();
+  let clicked = 0;
+
+  // See TOOL_DELAY for why we need setTimeout here
+  setTimeout(function delayedClick() {
+    info("Clicking button " + node.id);
+    node.click();
+    clicked++;
+
+    if (clicked >= clicks) {
+      deferred.resolve(node);
+    } else {
+      setTimeout(delayedClick, TOOL_DELAY);
+    }
+  }, TOOL_DELAY);
+
+  return deferred.promise;
+}
+
+function checkResults(histIdFocus) {
+  let result = Telemetry.prototype.telemetryInfo;
+
+  for (let [histId, value] of Iterator(result)) {
+    if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
+        !histId.contains(histIdFocus)) {
+      // Inspector stats are tested in
+      // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
+      // because we only open the inspector once for this test.
+      continue;
+    }
+
+    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
+      ok(value.length === 1 && value[0] === true,
+         "Per user value " + histId + " has a single value of true");
+    } else if (histId.endsWith("OPENED_BOOLEAN")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element === true;
+      });
+
+      ok(okay, "All " + histId + " entries are === true");
+    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element > 0;
+      });
+
+      ok(okay, "All " + histId + " entries have time > 0");
+    }
+  }
+
+  finishUp();
+}
+
+function finishUp() {
+  gBrowser.removeCurrentTab();
+
+  Telemetry.prototype.log = Telemetry.prototype._oldlog;
+  delete Telemetry.prototype._oldlog;
+  delete Telemetry.prototype.telemetryInfo;
+
+  TargetFactory = Services = promise = require = numScratchpads = null;
+
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    waitForFocus(init, content);
+  }, true);
+
+  content.location = TEST_URI;
+}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_telemetry_button_tilt.js
@@ -0,0 +1,127 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_button_tilt.js</p>";
+
+// Because we need to gather stats for the period of time that a tool has been
+// opened we make use of setTimeout() to create tool active times.
+const TOOL_DELAY = 200;
+
+let promise = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {}).Promise;
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
+let Telemetry = require("devtools/shared/telemetry");
+
+function init() {
+  Telemetry.prototype.telemetryInfo = {};
+  Telemetry.prototype._oldlog = Telemetry.prototype.log;
+  Telemetry.prototype.log = function(histogramId, value) {
+    if (histogramId) {
+      if (!this.telemetryInfo[histogramId]) {
+        this.telemetryInfo[histogramId] = [];
+      }
+
+      this.telemetryInfo[histogramId].push(value);
+    }
+  };
+
+  testButton("command-button-tilt");
+}
+
+function testButton(id) {
+  info("Testing " + id);
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+    info("inspector opened");
+
+    let button = toolbox.doc.querySelector("#" + id);
+    ok(button, "Captain, we have the button");
+
+    delayedClicks(button, 4).then(function() {
+      checkResults("_TILT_");
+    });
+  }).then(null, console.error);
+}
+
+function delayedClicks(node, clicks) {
+  let deferred = promise.defer();
+  let clicked = 0;
+
+  // See TOOL_DELAY for why we need setTimeout here
+  setTimeout(function delayedClick() {
+    info("Clicking button " + node.id);
+    node.click();
+    clicked++;
+
+    if (clicked >= clicks) {
+      deferred.resolve(node);
+    } else {
+      setTimeout(delayedClick, TOOL_DELAY);
+    }
+  }, TOOL_DELAY);
+
+  return deferred.promise;
+}
+
+function checkResults(histIdFocus) {
+  let result = Telemetry.prototype.telemetryInfo;
+
+  for (let [histId, value] of Iterator(result)) {
+    if (histId.startsWith("DEVTOOLS_INSPECTOR_") ||
+        !histId.contains(histIdFocus)) {
+      // Inspector stats are tested in
+      // browser_telemetry_toolboxtabs_{toolname}.js so we skip them here
+      // because we only open the inspector once for this test.
+      continue;
+    }
+
+    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
+      ok(value.length === 1 && value[0] === true,
+         "Per user value " + histId + " has a single value of true");
+    } else if (histId.endsWith("OPENED_BOOLEAN")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element === true;
+      });
+
+      ok(okay, "All " + histId + " entries are === true");
+    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element > 0;
+      });
+
+      ok(okay, "All " + histId + " entries have time > 0");
+    }
+  }
+
+  finishUp();
+}
+
+function finishUp() {
+  gBrowser.removeCurrentTab();
+
+  Telemetry.prototype.log = Telemetry.prototype._oldlog;
+  delete Telemetry.prototype._oldlog;
+  delete Telemetry.prototype.telemetryInfo;
+
+  TargetFactory = Services = promise = require = null;
+
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    waitForFocus(init, content);
+  }, true);
+
+  content.location = TEST_URI;
+}
deleted file mode 100644
--- a/browser/devtools/shared/test/browser_telemetry_buttonsandsidebar.js
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_buttonsandsidebar.js</p>";
-
-// Because we need to gather stats for the period of time that a tool has been
-// opened we make use of setTimeout() to create tool active times.
-const TOOL_DELAY = 200;
-
-let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
-let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
-
-let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
-let Telemetry = require("devtools/shared/telemetry");
-
-function init() {
-  Telemetry.prototype.telemetryInfo = {};
-  Telemetry.prototype._oldlog = Telemetry.prototype.log;
-  Telemetry.prototype.log = function(histogramId, value) {
-    if (histogramId) {
-      if (!this.telemetryInfo[histogramId]) {
-        this.telemetryInfo[histogramId] = [];
-      }
-
-      this.telemetryInfo[histogramId].push(value);
-    }
-  }
-
-  testButtons();
-}
-
-function testButtons() {
-  info("Testing buttons");
-
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    let container = toolbox.doc.getElementById("toolbox-buttons");
-    let buttons = container.getElementsByTagName("toolbarbutton");
-
-    // Copy HTMLCollection to array.
-    buttons = Array.prototype.slice.call(buttons);
-
-    (function testButton() {
-      let button = buttons.pop();
-
-      if (button) {
-        info("Clicking button " + button.id);
-        button.click();
-        delayedClicks(button, 3).then(function(button) {
-          if (buttons.length == 0) {
-            // Remove scratchpads
-            let wins = Services.wm.getEnumerator("devtools:scratchpad");
-            while (wins.hasMoreElements()) {
-              let win = wins.getNext();
-              info("Closing scratchpad window");
-              win.close();
-            }
-
-            testSidebar();
-          } else {
-            setTimeout(testButton, TOOL_DELAY);
-          }
-        });
-      }
-    })();
-  }).then(null, reportError);
-}
-
-function delayedClicks(node, clicks) {
-  let deferred = promise.defer();
-  let clicked = 0;
-
-  setTimeout(function delayedClick() {
-    info("Clicking button " + node.id);
-    node.click();
-    clicked++;
-
-    if (clicked >= clicks) {
-      deferred.resolve(node);
-    } else {
-      setTimeout(delayedClick, TOOL_DELAY);
-    }
-  }, TOOL_DELAY);
-
-  return deferred.promise;
-}
-
-function testSidebar() {
-  info("Testing sidebar");
-
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    let inspector = toolbox.getCurrentPanel();
-    let sidebarTools = ["ruleview", "computedview", "fontinspector", "layoutview"];
-
-    // Concatenate the array with itself so that we can open each tool twice.
-    sidebarTools.push.apply(sidebarTools, sidebarTools);
-
-    setTimeout(function selectSidebarTab() {
-      let tool = sidebarTools.pop();
-      if (tool) {
-        inspector.sidebar.select(tool);
-        setTimeout(function() {
-          setTimeout(selectSidebarTab, TOOL_DELAY);
-        }, TOOL_DELAY);
-      } else {
-        checkResults();
-      }
-    }, TOOL_DELAY);
-  });
-}
-
-function checkResults() {
-  let result = Telemetry.prototype.telemetryInfo;
-
-  for (let [histId, value] of Iterator(result)) {
-    if (histId.startsWith("DEVTOOLS_INSPECTOR_")) {
-      // Inspector stats are tested in browser_telemetry_toolboxtabs.js so we
-      // skip them here because we only open the inspector once for this test.
-      continue;
-    }
-
-    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
-      ok(value.length === 1 && value[0] === true,
-         "Per user value " + histId + " has a single value of true");
-    } else if (histId.endsWith("OPENED_BOOLEAN")) {
-      ok(value.length > 1, histId + " has more than one entry");
-
-      let okay = value.every(function(element) {
-        return element === true;
-      });
-
-      ok(okay, "All " + histId + " entries are === true");
-    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
-      ok(value.length > 1, histId + " has more than one entry");
-
-      let okay = value.every(function(element) {
-        return element > 0;
-      });
-
-      ok(okay, "All " + histId + " entries have time > 0");
-    }
-  }
-
-  finishUp();
-}
-
-function reportError(error) {
-  let stack = "    " + error.stack.replace(/\n?.*?@/g, "\n    JS frame :: ");
-
-  ok(false, "ERROR: " + error + " at " + error.fileName + ":" +
-            error.lineNumber + "\n\nStack trace:" + stack);
-  finishUp();
-}
-
-function finishUp() {
-  gBrowser.removeCurrentTab();
-
-  Telemetry.prototype.log = Telemetry.prototype._oldlog;
-  delete Telemetry.prototype._oldlog;
-  delete Telemetry.prototype.telemetryInfo;
-
-  TargetFactory = Services = promise = require = null;
-
-  finish();
-}
-
-function test() {
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
-    waitForFocus(init, content);
-  }, true);
-
-  content.location = TEST_URI;
-}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_telemetry_sidebar.js
@@ -0,0 +1,115 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_URI = "data:text/html;charset=utf-8,<p>browser_telemetry_sidebar.js</p>";
+
+// Because we need to gather stats for the period of time that a tool has been
+// opened we make use of setTimeout() to create tool active times.
+const TOOL_DELAY = 200;
+
+let {Promise: promise} = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
+let {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
+
+let require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
+let Telemetry = require("devtools/shared/telemetry");
+
+function init() {
+  Telemetry.prototype.telemetryInfo = {};
+  Telemetry.prototype._oldlog = Telemetry.prototype.log;
+  Telemetry.prototype.log = function(histogramId, value) {
+    if (histogramId) {
+      if (!this.telemetryInfo[histogramId]) {
+        this.telemetryInfo[histogramId] = [];
+      }
+
+      this.telemetryInfo[histogramId].push(value);
+    }
+  };
+
+  testSidebar();
+}
+
+function testSidebar() {
+  info("Testing sidebar");
+
+  let target = TargetFactory.forTab(gBrowser.selectedTab);
+
+  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
+    let inspector = toolbox.getCurrentPanel();
+    let sidebarTools = ["ruleview", "computedview", "fontinspector", "layoutview"];
+
+    // Concatenate the array with itself so that we can open each tool twice.
+    sidebarTools.push.apply(sidebarTools, sidebarTools);
+
+    // See TOOL_DELAY for why we need setTimeout here
+    setTimeout(function selectSidebarTab() {
+      let tool = sidebarTools.pop();
+      if (tool) {
+        inspector.sidebar.select(tool);
+        setTimeout(function() {
+          setTimeout(selectSidebarTab, TOOL_DELAY);
+        }, TOOL_DELAY);
+      } else {
+        checkResults();
+      }
+    }, TOOL_DELAY);
+  });
+}
+
+function checkResults() {
+  let result = Telemetry.prototype.telemetryInfo;
+
+  for (let [histId, value] of Iterator(result)) {
+    if (histId.startsWith("DEVTOOLS_INSPECTOR_")) {
+      // Inspector stats are tested in browser_telemetry_toolboxtabs.js so we
+      // skip them here because we only open the inspector once for this test.
+      continue;
+    }
+
+    if (histId.endsWith("OPENED_PER_USER_FLAG")) {
+      ok(value.length === 1 && value[0] === true,
+         "Per user value " + histId + " has a single value of true");
+    } else if (histId.endsWith("OPENED_BOOLEAN")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element === true;
+      });
+
+      ok(okay, "All " + histId + " entries are === true");
+    } else if (histId.endsWith("TIME_ACTIVE_SECONDS")) {
+      ok(value.length > 1, histId + " has more than one entry");
+
+      let okay = value.every(function(element) {
+        return element > 0;
+      });
+
+      ok(okay, "All " + histId + " entries have time > 0");
+    }
+  }
+
+  finishUp();
+}
+
+function finishUp() {
+  gBrowser.removeCurrentTab();
+
+  Telemetry.prototype.log = Telemetry.prototype._oldlog;
+  delete Telemetry.prototype._oldlog;
+  delete Telemetry.prototype.telemetryInfo;
+
+  TargetFactory = Services = promise = require = null;
+
+  finish();
+}
+
+function test() {
+  waitForExplicitFinish();
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function() {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+    waitForFocus(init, content);
+  }, true);
+
+  content.location = TEST_URI;
+}
--- a/browser/devtools/shared/test/head.js
+++ b/browser/devtools/shared/test/head.js
@@ -1,14 +1,15 @@
 /* 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/. */
 
 let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let TargetFactory = devtools.TargetFactory;
+let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
 
 /**
  * Open a new tab at a URL and call a callback on load
  */
 function addTab(aURL, aCallback)
 {
   waitForExplicitFinish();