Bug 988313 - Rewriting all devtools/styleinspector tests to be shorter, less prone to failures and more consistent; r=miker
☠☠ backed out by ecfe03732faf ☠ ☠
authorPatrick Brosset <pbrosset@mozilla.com>
Mon, 07 Apr 2014 21:27:24 +0200
changeset 177276 070988f9345877f81cfa8c985ec4e08024a1597a
parent 177275 552787e99ae66b1ea8e414823e7d361650a3caf0
child 177277 13c7239294aa9e520e867cf1d5fc3e14a5e00d84
push id6181
push userpbrosset@mozilla.com
push dateMon, 07 Apr 2014 19:32:01 +0000
treeherderfx-team@ebcad2bf9017 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmiker
bugs988313
milestone31.0a1
Bug 988313 - Rewriting all devtools/styleinspector tests to be shorter, less prone to failures and more consistent; r=miker
browser/devtools/styleinspector/test/browser.ini
browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
browser/devtools/styleinspector/test/browser_bug683672.js
browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js
browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_shorthand.js
browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.js
browser/devtools/styleinspector/test/browser_bug722196_property_view_media_queries.js
browser/devtools/styleinspector/test/browser_bug722196_rule_view_media_queries.js
browser/devtools/styleinspector/test/browser_bug722691_rule_view_increment.js
browser/devtools/styleinspector/test/browser_bug726427_csstransform_tooltip.js
browser/devtools/styleinspector/test/browser_bug765105_background_image_tooltip.js
browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_existing_property.js
browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_new_property.js
browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_existing_property_value_pair.js
browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_new_property_value_pair.js
browser/devtools/styleinspector/test/browser_bug913014_matched_expand.js
browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js
browser/devtools/styleinspector/test/browser_bug942297_user_property_reset.js
browser/devtools/styleinspector/test/browser_bug946331_close_tooltip_on_new_selection.js
browser/devtools/styleinspector/test/browser_bug970532_mathml_element.js
browser/devtools/styleinspector/test/browser_bug_592743_specificity.js
browser/devtools/styleinspector/test/browser_bug_692400_element_style.js
browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js
browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js
browser/devtools/styleinspector/test/browser_computedview_copy.js
browser/devtools/styleinspector/test/browser_computedview_original_source_link.js
browser/devtools/styleinspector/test/browser_csslogic_inherited.js
browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js
browser/devtools/styleinspector/test/browser_ruleview_add_property_01.js
browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-commit-on-ENTER.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-hides-on-tooltip.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-multiple-changes.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-swatch-displayed.js
browser/devtools/styleinspector/test/browser_ruleview_copy.js
browser/devtools/styleinspector/test/browser_ruleview_editor.js
browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js
browser/devtools/styleinspector/test/browser_ruleview_focus.js
browser/devtools/styleinspector/test/browser_ruleview_inherit.js
browser/devtools/styleinspector/test/browser_ruleview_livepreview.js
browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js
browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js
browser/devtools/styleinspector/test/browser_ruleview_override.js
browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js
browser/devtools/styleinspector/test/browser_ruleview_ui.js
browser/devtools/styleinspector/test/browser_ruleview_update.js
browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js
browser/devtools/styleinspector/test/browser_styleinspector_bug_672746_default_styles.js
browser/devtools/styleinspector/test/browser_styleinspector_bug_677930_urls_clickable.js
browser/devtools/styleinspector/test/browser_styleinspector_bug_689759_no_results_placeholder.js
browser/devtools/styleinspector/test/browser_styleinspector_outputparser.js
browser/devtools/styleinspector/test/head.js
--- a/browser/devtools/styleinspector/test/browser.ini
+++ b/browser/devtools/styleinspector/test/browser.ini
@@ -1,82 +1,78 @@
 [DEFAULT]
 skip-if = e10s # Bug ?????? - devtools tests disabled with e10s
 support-files =
   head.js
   browser_bug722196_identify_media_queries.html
   browser_styleinspector_bug_677930_urls_clickable/browser_styleinspector_bug_677930_urls_clickable.css
+  browser_bug683672.html
+  browser_bug705707_is_content_stylesheet.html
+  browser_bug705707_is_content_stylesheet_imported.css
+  browser_bug705707_is_content_stylesheet_imported2.css
+  browser_bug705707_is_content_stylesheet_linked.css
+  browser_bug705707_is_content_stylesheet_script.css
+  browser_bug705707_is_content_stylesheet.xul
+  browser_bug705707_is_content_stylesheet_xul.css
+  test-image.png
+  browser_styleinspector_bug_677930_urls_clickable.html
+  browser_ruleview_pseudoelement.html
+  sourcemaps.html
+  sourcemaps.css
+  sourcemaps.css.map
+  sourcemaps.scss
+  browser_ruleview_734259_style_editor_link.css
 
 [browser_bug683672.js]
-support-files = browser_bug683672.html
 [browser_styleinspector_bug_672746_default_styles.js]
 [browser_styleinspector_bug_672744_search_filter.js]
 [browser_bug589375_keybindings.js]
-skip-if = true # awaiting promise-based init
 [browser_styleinspector_bug_689759_no_results_placeholder.js]
 [browser_bug_692400_element_style.js]
 [browser_csslogic_inherited.js]
 [browser_ruleview_734259_style_editor_link.js]
-support-files =
-  browser_ruleview_734259_style_editor_link.css
 [browser_ruleview_editor.js]
 [browser_ruleview_editor_changedvalues.js]
 [browser_ruleview_copy.js]
 [browser_ruleview_focus.js]
 [browser_ruleview_inherit.js]
 [browser_ruleview_manipulation.js]
 [browser_ruleview_multiple_properties.js]
 [browser_ruleview_override.js]
 [browser_ruleview_ui.js]
 [browser_ruleview_update.js]
 [browser_ruleview_livepreview.js]
 [browser_bug705707_is_content_stylesheet.js]
-support-files =
-  browser_bug705707_is_content_stylesheet.html
-  browser_bug705707_is_content_stylesheet_imported.css
-  browser_bug705707_is_content_stylesheet_imported2.css
-  browser_bug705707_is_content_stylesheet_linked.css
-  browser_bug705707_is_content_stylesheet_script.css
-  browser_bug705707_is_content_stylesheet.xul
-  browser_bug705707_is_content_stylesheet_xul.css
 [browser_bug722196_property_view_media_queries.js]
 [browser_bug722196_rule_view_media_queries.js]
 [browser_bug_592743_specificity.js]
 [browser_bug722691_rule_view_increment.js]
 [browser_computedview_734259_style_editor_link.js]
 [browser_computedview_copy.js]
 [browser_styleinspector_bug_677930_urls_clickable.js]
-support-files =
-  test-image.png
-  browser_styleinspector_bug_677930_urls_clickable.html
 [browser_bug893965_css_property_completion_new_property.js]
 [browser_bug893965_css_property_completion_existing_property.js]
 [browser_bug894376_css_value_completion_new_property_value_pair.js]
 [browser_bug894376_css_value_completion_existing_property_value_pair.js]
 [browser_ruleview_bug_902966_revert_value_on_ESC.js]
 [browser_ruleview_pseudoelement.js]
-support-files = browser_ruleview_pseudoelement.html
 [browser_computedview_bug835808_keyboard_nav.js]
 [browser_bug913014_matched_expand.js]
 [browser_bug765105_background_image_tooltip.js]
 [browser_bug726427_csstransform_tooltip.js]
 [browser_bug702577_fontfamily_tooltip_shorthand.js]
 [browser_bug702577_fontfamily_tooltip_longhand.js]
 [browser_bug940500_rule_view_pick_gradient_color.js]
 [browser_ruleview_original_source_link.js]
-support-files =
-  sourcemaps.html
-  sourcemaps.css
-  sourcemaps.css.map
-  sourcemaps.scss
 [browser_computedview_original_source_link.js]
 [browser_bug946331_close_tooltip_on_new_selection.js]
 [browser_bug942297_user_property_reset.js]
 [browser_styleinspector_outputparser.js]
 [browser_bug970532_mathml_element.js]
 [browser_ruleview_colorpicker-swatch-displayed.js]
 [browser_ruleview_colorpicker-appears-on-swatch-click.js]
 [browser_ruleview_colorpicker-hides-on-tooltip.js]
 [browser_ruleview_colorpicker-revert-on-ESC.js]
 [browser_ruleview_colorpicker-commit-on-ENTER.js]
 [browser_ruleview_colorpicker-and-image-tooltip_01.js]
 [browser_ruleview_colorpicker-and-image-tooltip_02.js]
 [browser_ruleview_colorpicker-multiple-changes.js]
+[browser_ruleview_add_property_01.js]
--- a/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
+++ b/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js
@@ -1,141 +1,79 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests that the key bindings work properly.
+"use strict";
+
+// Test computed view key bindings
 
-let doc;
-let inspector;
-let computedView;
-let iframe;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,default styles test");
 
-function createDocument()
-{
-  doc.body.innerHTML = '<style type="text/css"> ' +
+  info("Adding content to the test page");
+  content.document.body.innerHTML = '<style type="text/css"> ' +
     '.matches {color: #F00;}</style>' +
     '<span class="matches">Some styled text</span>' +
     '</div>';
-  doc.title = "Style Inspector key binding test";
 
-  openInspector(openComputedView);
-}
-
-function openComputedView(aInspector)
-{
-  inspector = aInspector;
-  iframe = inspector._toolbox.frame;
-
-  Services.obs.addObserver(runTests, "StyleInspector-populated", false);
-
-  inspector.sidebar.select("computedview");
-}
+  let {toolbox, inspector, view} = yield openComputedView();
 
-function runTests()
-{
-  Services.obs.removeObserver(runTests, "StyleInspector-populated");
-  computedView = getComputedView();
-
-  var span = doc.querySelector(".matches");
-  ok(span, "captain, we have the matches span");
-
-  inspector.selection.setNode(span);
+  info("Selecting the test node");
+  yield selectNode(".matches", inspector);
 
-  is(span, computedView.viewedElement,
-    "style inspector node matches the selected node");
-  is(computedView.viewedElement, computedView.cssLogic.viewedElement,
-     "cssLogic node matches the cssHtmlTree node");
-
-  info("checking keybindings");
-
-  let searchbar = computedView.searchField;
-  let propView = getFirstVisiblePropertyView();
+  let propView = getFirstVisiblePropertyView(view);
   let rulesTable = propView.matchedSelectorsContainer;
-  let matchedExpander = propView.matchedExpander;
+  let matchedExpander = propView.element;
 
-  info("Adding focus event handler to search filter");
-  searchbar.addEventListener("focus", function searchbarFocused() {
-    searchbar.removeEventListener("focus", searchbarFocused);
-    info("search filter is focused");
-    info("tabbing to property expander node");
-    EventUtils.synthesizeKey("VK_TAB", {}, iframe.contentWindow);
-  });
-
-  info("Adding focus event handler to property expander");
-  matchedExpander.addEventListener("focus", function expanderFocused() {
-    matchedExpander.removeEventListener("focus", expanderFocused);
-    info("property expander is focused");
-    info("checking expand / collapse");
-    testKey(iframe.contentWindow, "VK_SPACE", rulesTable);
-    testKey(iframe.contentWindow, "VK_RETURN", rulesTable);
+  info("Focusing the property");
+  let onMatchedExpanderFocus = once(matchedExpander, "focus", true);
+  EventUtils.synthesizeMouseAtCenter(matchedExpander, {}, view.styleWindow);
+  yield onMatchedExpanderFocus;
 
-    checkHelpLinkKeybinding();
-    computedView.destroy();
-    finishUp();
-  });
+  yield checkToggleKeyBinding(view.styleWindow, "VK_SPACE", rulesTable, inspector);
+  yield checkToggleKeyBinding(view.styleWindow, "VK_RETURN", rulesTable, inspector);
+  yield checkHelpLinkKeybinding(view);
+});
 
-  info("Making sure that the style inspector panel is focused");
-  SimpleTest.waitForFocus(function windowFocused() {
-    info("window is focused");
-    info("focusing search filter");
-    searchbar.focus();
-  }, iframe.contentWindow);
-}
-
-function getFirstVisiblePropertyView()
-{
+function getFirstVisiblePropertyView(view) {
   let propView = null;
-  computedView.propertyViews.some(function(aPropView) {
-    if (aPropView.visible) {
-      propView = aPropView;
+  view.propertyViews.some(p => {
+    if (p.visible) {
+      propView = p;
       return true;
     }
     return false;
   });
 
   return propView;
 }
 
-function testKey(aContext, aVirtKey, aRulesTable)
-{
-  info("testing " + aVirtKey + " key");
-  info("expanding rules table");
-  EventUtils.synthesizeKey(aVirtKey, {}, aContext);
-  isnot(aRulesTable.innerHTML, "", "rules Table is populated");
-  info("collapsing rules table");
-  EventUtils.synthesizeKey(aVirtKey, {}, aContext);
-  is(aRulesTable.innerHTML, "", "rules Table is not populated");
+function* checkToggleKeyBinding(win, key, rulesTable, inspector) {
+  info("Pressing " + key + " key a couple of times to check that the property gets expanded/collapsed");
+
+  let onExpand = inspector.once("computed-view-property-expanded");
+  let onCollapse = inspector.once("computed-view-property-collapsed");
+
+  info("Expanding the property");
+  EventUtils.synthesizeKey(key, {}, win);
+  yield onExpand;
+  isnot(rulesTable.innerHTML, "", "The property has been expanded");
+
+  info("Collapsing the property");
+  EventUtils.synthesizeKey(key, {}, win);
+  yield onCollapse;
+  is(rulesTable.innerHTML, "", "The property has been collapsed");
 }
 
-function checkHelpLinkKeybinding()
-{
-  info("checking help link keybinding");
-  let propView = getFirstVisiblePropertyView();
-
-  info("check that MDN link is opened on \"F1\"");
-  let linkClicked = false;
-  propView.mdnLinkClick = function(aEvent) {
-    linkClicked = true;
-  };
-  EventUtils.synthesizeKey("VK_F1", {}, iframe.contentWindow);
-  is(linkClicked, true, "MDN link will be shown");
-}
+function checkHelpLinkKeybinding(view) {
+  info("Check that MDN link is opened on \"F1\"");
+  let def = promise.defer();
 
-function finishUp()
-{
-  doc = inspector = iframe = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  let propView = getFirstVisiblePropertyView(view);
+  propView.mdnLinkClick = function(aEvent) {
+    ok(true, "Pressing F1 opened the MDN link");
+    def.resolve();
+  };
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,default styles test";
+  EventUtils.synthesizeKey("VK_F1", {}, view.styleWindow);
+  return def.promise;
 }
--- a/browser/devtools/styleinspector/test/browser_bug683672.js
+++ b/browser/devtools/styleinspector/test/browser_bug683672.js
@@ -1,79 +1,36 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that the style inspector works properly
-
-let doc;
-let inspector;
-let div;
-let computedView;
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/test/browser_bug683672.html";
-
-let tempScope = {};
-let {CssHtmlTree, PropertyView} = devtools.require("devtools/styleinspector/computed-view");
-let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {});
+"use strict";
 
-function test()
-{
-  waitForExplicitFinish();
-  addTab(TEST_URI);
-  browser.addEventListener("load", tabLoaded, true);
-}
+// Checking selector counts, matched rules and titles in the computed-view
 
-function tabLoaded()
-{
-  browser.removeEventListener("load", tabLoaded, true);
-  doc = content.document;
-  openComputedView(selectNode);
-}
-
-function selectNode(aInspector, aComputedView)
-{
-  inspector = aInspector;
-  computedView = aComputedView;
-
-  div = content.document.getElementById("test");
-  ok(div, "captain, we have the div");
+const {PropertyView} = devtools.require("devtools/styleinspector/computed-view");
+const TEST_URI = TEST_URL_ROOT + "browser_bug683672.html";
 
-  inspector.selection.setNode(div);
-  inspector.once("inspector-updated", runTests);
-}
+let test = asyncTest(function*() {
+  yield addTab(TEST_URI);
+  let {toolbox, inspector, view} = yield openComputedView();
 
-function runTests()
-{
-  testMatchedSelectors().then(() => {
-    info("finishing up");
-    finishUp();
-  });
-}
+  yield selectNode("#test", inspector);
+  yield testMatchedSelectors(view);
+});
 
-function testMatchedSelectors()
-{
+function* testMatchedSelectors(view) {
   info("checking selector counts, matched rules and titles");
 
-  is(div, computedView.viewedElement.rawNode(),
+  is(getNode("#test"), view.viewedElement.rawNode(),
       "style inspector node matches the selected node");
 
-  let propertyView = new PropertyView(computedView, "color");
+  let propertyView = new PropertyView(view, "color");
   propertyView.buildMain();
   propertyView.buildSelectorContainer();
   propertyView.matchedExpanded = true;
-  return propertyView.refreshMatchedSelectors().then(() => {
-    let numMatchedSelectors = propertyView.matchedSelectors.length;
 
-    is(numMatchedSelectors, 6,
-        "CssLogic returns the correct number of matched selectors for div");
+  yield propertyView.refreshMatchedSelectors();
 
-    is(propertyView.hasMatchedSelectors, true,
-        "hasMatchedSelectors returns true");
-  }).then(null, (err) => console.error(err));
+  let numMatchedSelectors = propertyView.matchedSelectors.length;
+  is(numMatchedSelectors, 6, "CssLogic returns the correct number of matched selectors for div");
+  is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors returns true");
 }
-
-function finishUp()
-{
-  doc = inspector = div = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js
+++ b/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js
@@ -1,118 +1,69 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let contentDoc;
-let inspector;
-let ruleView;
-let computedView;
+"use strict";
+
+// Test the fontfamily tooltip on longhand properties
 
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  #testElement {',
   '    font-family: cursive;',
   '    color: #333;',
   '    padding-left: 70px;',
   '  }',
   '</style>',
   '<div id="testElement">test element</div>'
 ].join("\n");
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,font family longhand tooltip test");
+
+  info("Creating the test document");
+  content.document.body.innerHTML = PAGE_CONTENT;
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
+  info("Opening the rule view");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  content.location = "data:text/html;charset=utf-8,font family longhand tooltip test";
-}
+  info("Selecting the test node");
+  yield selectNode("#testElement", inspector);
 
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  yield testRuleView(view);
+
+  info("Opening the computed view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    startTests();
-  });
-}
+  yield testComputedView(view);
+});
+
+function* testRuleView(ruleView) {
+  info("Testing font-family tooltips in the rule view");
+
+  let panel = ruleView.previewTooltip.panel;
 
-function startTests() {
-  inspector.selection.setNode(contentDoc.querySelector("#testElement"));
-  inspector.once("inspector-updated", testRuleView);
-}
+  // Check that the rule view has a tooltip and that a XUL panel has been created
+  ok(ruleView.previewTooltip, "Tooltip instance exists");
+  ok(panel, "XUL panel exists");
 
-function endTests() {
-  contentDoc = inspector = ruleView = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  // Get the font family property inside the rule view
+  let {valueSpan} = getRuleViewProperty(ruleView, "#testElement", "font-family");
+
+  // And verify that the tooltip gets shown on this property
+  yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
+
+  let description = panel.getElementsByTagName("description")[0];
+  is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
 }
 
-function testRuleView() {
-  Task.spawn(function*() {
-    info("Testing font-family tooltips in the rule view");
-
-    let panel = ruleView.previewTooltip.panel;
-
-    // Check that the rule view has a tooltip and that a XUL panel has been created
-    ok(ruleView.previewTooltip, "Tooltip instance exists");
-    ok(panel, "XUL panel exists");
-
-    // Get the font family property inside the rule view
-    let {valueSpan} = getRuleViewProperty("font-family");
-
-    // And verify that the tooltip gets shown on this property
-    assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
+function* testComputedView(computedView) {
+  info("Testing font-family tooltips in the computed view");
 
-    let description = panel.getElementsByTagName("description")[0];
-    is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
-  }).then(testComputedView);
-}
-
-function testComputedView() {
-  Task.spawn(function*() {
-    info("Testing font-family tooltips in the computed view");
-
-    inspector.sidebar.select("computedview");
-    computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
-    let doc = computedView.styleDocument;
-
-    let panel = computedView.tooltip.panel;
-    let {valueSpan} = getComputedViewProperty("font-family");
+  let panel = computedView.tooltip.panel;
+  let {valueSpan} = getComputedViewProperty(computedView, "font-family");
 
-    assertTooltipShownOn(computedView.tooltip, valueSpan);
-
-    let description = panel.getElementsByTagName("description")[0];
-    is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
-  }).then(endTests);
-}
-
-function getRuleViewProperty(name) {
-  let prop = null;
-  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
-    let nameSpan = property.querySelector(".ruleview-propertyname");
-    let valueSpan = property.querySelector(".ruleview-propertyvalue");
+  yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
 
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
+  let description = panel.getElementsByTagName("description")[0];
+  is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
 }
-
-function getComputedViewProperty(name) {
-  let prop = null;
-  [].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
-    let nameSpan = property.querySelector(".property-name");
-    let valueSpan = property.querySelector(".property-value");
-
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
-}
--- a/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_shorthand.js
+++ b/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_shorthand.js
@@ -1,121 +1,72 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let contentDoc;
-let inspector;
-let ruleView;
-let computedView;
+"use strict";
+
+// Test the fontfamily tooltip on shorthand properties
 
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  #testElement {',
   '    font: italic bold .8em/1.2 Arial;',
   '  }',
   '</style>',
   '<div id="testElement">test element</div>'
 ].join("\n");
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,font family shorthand tooltip test");
+
+  info("Creating the test document");
+  content.document.body.innerHTML = PAGE_CONTENT;
+
+  info("Opening the rule view");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
+  info("Selecting the test node");
+  yield selectNode("#testElement", inspector);
+
+  yield testRuleView(view);
 
-  content.location = "data:text/html;charset=utf-8,font family shorthand tooltip test";
-}
+  info("Opening the computed view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  yield testComputedView(view);
+});
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    startTests();
-  });
-}
+function* testRuleView(ruleView) {
+  info("Testing font-family tooltips in the rule view");
+
+  let panel = ruleView.previewTooltip.panel;
+
+  // Check that the rule view has a tooltip and that a XUL panel has been created
+  ok(ruleView.previewTooltip, "Tooltip instance exists");
+  ok(panel, "XUL panel exists");
 
-function startTests() {
-  inspector.selection.setNode(contentDoc.querySelector("#testElement"));
-  inspector.once("inspector-updated", testRuleView);
-}
+  // Get the computed font family property inside the font rule view
+  let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
+  let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
+  fontExpander.click();
 
-function endTests() {
-  contentDoc = inspector = ruleView = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  let rule = getRuleViewRule(ruleView, "#testElement");
+  let valueSpan = rule.querySelector(".ruleview-computed .ruleview-propertyvalue");
+
+  // And verify that the tooltip gets shown on this property
+  yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
+
+  let description = panel.getElementsByTagName("description")[0];
+  is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
 }
 
-function testRuleView() {
-  Task.spawn(function*() {
-    info("Testing font-family tooltips in the rule view");
-
-    let panel = ruleView.previewTooltip.panel;
-
-    // Check that the rule view has a tooltip and that a XUL panel has been created
-    ok(ruleView.previewTooltip, "Tooltip instance exists");
-    ok(panel, "XUL panel exists");
-
-    // Get the computed font family property inside the font rule view
-    let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
-    let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
-    fontExpander.click();
-
-    let {valueSpan} = getRuleViewProperty("font-family");
+function* testComputedView(computedView) {
+  info("Testing font-family tooltips in the computed view");
 
-    // And verify that the tooltip gets shown on this property
-    yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
-
-    // And that it has the right content
-    let description = panel.getElementsByTagName("description")[0];
-    is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
-  }).then(testComputedView);
-}
-
-function testComputedView() {
-  Task.spawn(function*() {
-    info("Testing font-family tooltips in the computed view");
-
-    inspector.sidebar.select("computedview");
-    computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
-    let doc = computedView.styleDocument;
+  let panel = computedView.tooltip.panel;
+  let {valueSpan} = getComputedViewProperty(computedView, "font-family");
 
-    let panel = computedView.tooltip.panel;
-    let {valueSpan} = getComputedViewProperty("font-family");
-
-    yield assertTooltipShownOn(computedView.tooltip, valueSpan);
-
-    let description = panel.getElementsByTagName("description")[0];
-    is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
-  }).then(endTests);
-}
-
-function getRuleViewProperty(name) {
-  let prop = null;
-  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-computedlist"), property => {
-    let nameSpan = property.querySelector(".ruleview-propertyname");
-    let valueSpan = property.querySelector(".ruleview-propertyvalue");
+  yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
 
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
+  let description = panel.getElementsByTagName("description")[0];
+  is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
 }
-
-function getComputedViewProperty(name) {
-  let prop = null;
-  [].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
-    let nameSpan = property.querySelector(".property-name");
-    let valueSpan = property.querySelector(".property-value");
-
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
-}
--- a/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.js
+++ b/browser/devtools/styleinspector/test/browser_bug705707_is_content_stylesheet.js
@@ -1,139 +1,72 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Tests that the correct stylesheets origins are identified in HTML & XUL
-// stylesheets
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
+"use strict";
 
-const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
-                 "test/browser_bug705707_is_content_stylesheet.html";
-const TEST_URI2 = "http://example.com/browser/browser/devtools/styleinspector/" +
-                 "test/browser_bug705707_is_content_stylesheet.xul";
+// Check stylesheets on HMTL and XUL document
+
+const TEST_URI_HTML = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.html";
+const TEST_URI_XUL = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.xul";
 const XUL_URI = Cc["@mozilla.org/network/io-service;1"]
                 .getService(Ci.nsIIOService)
-                .newURI(TEST_URI2, null, null);
-const XUL_PRINCIPAL =  Components.classes["@mozilla.org/scriptsecuritymanager;1"]
-                                 .getService(Ci.nsIScriptSecurityManager)
-                                 .getNoAppCodebasePrincipal(XUL_URI);
+                .newURI(TEST_URI_XUL, null, null);
+const XUL_PRINCIPAL = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+                        .getService(Ci.nsIScriptSecurityManager)
+                        .getNoAppCodebasePrincipal(XUL_URI);
 
-let inspector, ruleView;
 let {CssLogic} = devtools.require("devtools/styleinspector/css-logic");
 
-function test()
-{
-  waitForExplicitFinish();
-  addTab(TEST_URI);
-  browser.addEventListener("load", htmlLoaded, true);
-}
+let test = asyncTest(function*() {
+  info("Checking stylesheets on HTML document");
+  yield addTab(TEST_URI_HTML);
+  let target = getNode("#target");
 
-function htmlLoaded()
-{
-  browser.removeEventListener("load", htmlLoaded, true);
-  doc = content.document;
-  testFromHTML()
-}
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield selectNode(target, inspector);
+
+  info("Checking stylesheets");
+  checkSheets(target);
 
-function testFromHTML()
-{
-  let target = doc.querySelector("#target");
+  info("Checking stylesheets on XUL document");
+  info("Allowing XUL content");
+  allowXUL();
+  yield addTab(TEST_URI_XUL);
+
+  let {toolbox, inspector, view} = yield openRuleView();
+  let target = getNode("#target");
+  yield selectNode(target, inspector);
 
-  executeSoon(function() {
-    checkSheets(target);
-    openRuleView((aInspector, aRuleView) => {
-      inspector = aInspector;
-      ruleView = aRuleView;
-      inspector.selection.setNode(target);
-      inspector.once("inspector-updated", testModifyRules);
-    });
-  });
+  checkSheets(target);
+  info("Disallowing XUL content");
+  disallowXUL();
+});
+
+function allowXUL() {
+  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
+    .addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
 }
 
-function reselectElement(target, cb)
-{
-  inspector.selection.setNode(target.parentNode);
-  inspector.once("inspector-updated", ()=> {
-    inspector.selection.setNode(target);
-    inspector.once("inspector-updated", cb);
-  });
-}
-
-function testModifyRules()
-{
-  // Set a property on all rules, then refresh and make sure they are still
-  // there (and there wasn't an error on the server side)
-  for (let rule of ruleView._elementStyle.rules) {
-    rule.editor.addProperty("font-weight", "bold", "");
-  }
-
-  executeSoon(() => {
-    reselectElement(doc.querySelector("#target"), () => {
-      for (let rule of ruleView._elementStyle.rules) {
-        let lastRule = rule.textProps[rule.textProps.length - 1];
-
-        is (lastRule.name, "font-weight", "Last rule name is font-weight");
-        is (lastRule.value, "bold", "Last rule value is bold");
-      }
-
-      gBrowser.removeCurrentTab();
-      openXUL();
-    });
-  });
+function disallowXUL() {
+  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
+    .addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
 }
 
-
-function openXUL()
-{
-  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
-    .addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
-  addTab(TEST_URI2);
-  browser.addEventListener("load", xulLoaded, true);
-}
-
-function xulLoaded()
-{
-  browser.removeEventListener("load", xulLoaded, true);
-  doc = content.document;
-  testFromXUL()
-}
-
-function testFromXUL()
-{
-  let target = doc.querySelector("#target");
-
-  executeSoon(function() {
-    checkSheets(target);
-    finishUp();
-  });
-}
-
-function checkSheets(aTarget)
-{
+function checkSheets(target) {
   let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
       .getService(Ci.inIDOMUtils);
-  let domRules = domUtils.getCSSStyleRules(aTarget);
+  let domRules = domUtils.getCSSStyleRules(target);
 
   for (let i = 0, n = domRules.Count(); i < n; i++) {
     let domRule = domRules.GetElementAt(i);
     let sheet = domRule.parentStyleSheet;
     let isContentSheet = CssLogic.isContentStylesheet(sheet);
 
     if (!sheet.href ||
         /browser_bug705707_is_content_stylesheet_/.test(sheet.href)) {
       ok(isContentSheet, sheet.href + " identified as content stylesheet");
     } else {
       ok(!isContentSheet, sheet.href + " identified as non-content stylesheet");
     }
   }
 }
-
-function finishUp()
-{
-  info("finishing up");
-  Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
-    .addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
-  doc = inspector = ruleView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_bug722196_property_view_media_queries.js
+++ b/browser/devtools/styleinspector/test/browser_bug722196_property_view_media_queries.js
@@ -1,88 +1,62 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 // Tests that we correctly display appropriate media query titles in the
 // property view.
 
-let doc;
-let computedView;
-
-const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
-  "test/browser_bug722196_identify_media_queries.html";
+const TEST_URI = TEST_URL_ROOT + "browser_bug722196_identify_media_queries.html";
 
 let {PropertyView} = devtools.require("devtools/styleinspector/computed-view");
 let {CssLogic} = devtools.require("devtools/styleinspector/css-logic");
 
-function test()
-{
-  waitForExplicitFinish();
-  addTab(TEST_URI);
-  browser.addEventListener("load", docLoaded, true);
-}
+let test = asyncTest(function*() {
+  yield addTab(TEST_URI);
+  let {toolbox, inspector, view} = yield openComputedView();
 
-function docLoaded()
-{
-  browser.removeEventListener("load", docLoaded, true);
-  doc = content.document;
-
-  openComputedView(selectNode);
-}
+  info("Selecting the test element");
+  yield selectNode("div", inspector);
 
-function selectNode(aInspector, aComputedView)
-{
-  computedView = aComputedView;
-
-  var div = doc.querySelector("div");
-  ok(div, "captain, we have the div");
+  info("Checking CSSLogic");
+  checkCssLogic();
 
-  aInspector.selection.setNode(div);
-  aInspector.once("inspector-updated", checkCssLogic);
-}
+  info("Checking property view");
+  yield checkPropertyView(view);
+});
 
-function checkCssLogic()
-{
+function checkCssLogic() {
   let cssLogic = new CssLogic();
-  cssLogic.highlight(doc.querySelector("div"));
+  cssLogic.highlight(getNode("div"));
   cssLogic.processMatchedSelectors();
 
   let _strings = Services.strings
     .createBundle("chrome://global/locale/devtools/styleinspector.properties");
 
   let inline = _strings.GetStringFromName("rule.sourceInline");
 
   let source1 = inline + ":8";
   let source2 = inline + ":15 @media screen and (min-width: 1px)";
   is(cssLogic._matchedRules[0][0].source, source1,
     "rule.source gives correct output for rule 1");
   is(cssLogic._matchedRules[1][0].source, source2,
     "rule.source gives correct output for rule 2");
-
-  checkPropertyView();
 }
 
-function checkPropertyView()
-{
-  let propertyView = new PropertyView(computedView, "width");
+function checkPropertyView(view) {
+  let propertyView = new PropertyView(view, "width");
   propertyView.buildMain();
   propertyView.buildSelectorContainer();
   propertyView.matchedExpanded = true;
+
   return propertyView.refreshMatchedSelectors().then(() => {
     let numMatchedSelectors = propertyView.matchedSelectors.length;
 
     is(numMatchedSelectors, 2,
         "Property view has the correct number of matched selectors for div");
 
     is(propertyView.hasMatchedSelectors, true,
         "hasMatchedSelectors returns true");
-
-    finishUp();
-  }).then(null, (err) => console.error(err));
+  });
 }
-
-function finishUp()
-{
-  doc = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_bug722196_rule_view_media_queries.js
+++ b/browser/devtools/styleinspector/test/browser_bug722196_rule_view_media_queries.js
@@ -1,61 +1,31 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 // Tests that we correctly display appropriate media query titles in the
 // rule view.
 
-let doc;
-let inspector;
-
-const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
-  "test/browser_bug722196_identify_media_queries.html";
-
-function test()
-{
-  waitForExplicitFinish();
-  addTab(TEST_URI);
-  browser.addEventListener("load", docLoaded, true);
-}
+const TEST_URI = TEST_URL_ROOT + "browser_bug722196_identify_media_queries.html";
 
-function docLoaded()
-{
-  browser.removeEventListener("load", docLoaded, true);
-  doc = content.document;
-  openRuleView(selectNode);
-}
-
-function selectNode(aInspector, aRuleView)
-{
-  inspector = aInspector;
+let test = asyncTest(function*() {
+  yield addTab(TEST_URI);
+  let {inspector, view} = yield openRuleView();
 
-  inspector.selection.setNode(doc.querySelector("div"));
-  inspector.once("inspector-updated", checkSheets);
-}
+  yield selectNode("div", inspector);
 
-function checkSheets()
-{
-  var div = doc.querySelector("div");
-  ok(div, "captain, we have the div");
-
-  let elementStyle = ruleView()._elementStyle;
+  let elementStyle = view._elementStyle;
 
   let _strings = Services.strings
     .createBundle("chrome://global/locale/devtools/styleinspector.properties");
 
   let inline = _strings.GetStringFromName("rule.sourceInline");
 
   is(elementStyle.rules.length, 3, "Should have 3 rules.");
   is(elementStyle.rules[0].title, inline, "check rule 0 title");
   is(elementStyle.rules[1].title, inline +
     ":15 @media screen and (min-width: 1px)", "check rule 1 title");
   is(elementStyle.rules[2].title, inline + ":8", "check rule 2 title");
-  finishUp();
-}
+});
 
-function finishUp()
-{
-  doc = inspector = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_bug722691_rule_view_increment.js
+++ b/browser/devtools/styleinspector/test/browser_bug722691_rule_view_increment.js
@@ -1,192 +1,176 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
 // Test that increasing/decreasing values in rule view using
 // arrow keys works correctly.
 
-let doc;
-let view;
-let inspector;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,sample document for bug 722691");
+  createDocument();
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  yield selectNode("#test", inspector);
 
-function setUpTests()
-{
-  doc.body.innerHTML = '<div id="test" style="' +
+  yield testMarginIncrements(view);
+  yield testVariousUnitIncrements(view);
+  yield testHexIncrements(view);
+  yield testRgbIncrements(view);
+  yield testShorthandIncrements(view);
+  yield testOddCases(view);
+});
+
+function createDocument() {
+  content.document.body.innerHTML = '<div id="test" style="' +
                            'margin-top:0px;' +
                            'padding-top: 0px;' +
                            'color:#000000;' +
                            'background-color: #000000;" >'+
                        '</div>';
+}
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    view = aRuleView;
-    inspector.selection.setNode(doc.getElementById("test"));
-    inspector.once("inspector-updated", () => {
-      runTests();
-    })
+function* testMarginIncrements(view) {
+  info("Testing keyboard increments on the margin property");
+
+  let idRuleEditor = view.element.children[0]._ruleEditor;
+  let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
+
+  yield runIncrementTest(marginPropEditor, view, {
+    1: {alt: true, start: "0px", end: "0.1px", selectAll: true},
+    2: {start: "0px", end: "1px", selectAll: true},
+    3: {shift: true, start: "0px", end: "10px", selectAll: true},
+    4: {down: true, alt: true, start: "0.1px", end: "0px", selectAll: true},
+    5: {down: true, start: "0px", end: "-1px", selectAll: true},
+    6: {down: true, shift: true, start: "0px", end: "-10px", selectAll: true},
+    7: {pageUp: true, shift: true, start: "0px", end: "100px", selectAll: true},
+    8: {pageDown: true, shift: true, start: "0px", end: "-100px", selectAll: true}
   });
 }
 
-function runTests()
-{
+function* testVariousUnitIncrements(view) {
+  info("Testing keyboard increments on values with various units");
+
   let idRuleEditor = view.element.children[0]._ruleEditor;
-  let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
   let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
+
+  yield runIncrementTest(paddingPropEditor, view, {
+    1: {start: "0px", end: "1px", selectAll: true},
+    2: {start: "0pt", end: "1pt", selectAll: true},
+    3: {start: "0pc", end: "1pc", selectAll: true},
+    4: {start: "0em", end: "1em", selectAll: true},
+    5: {start: "0%",  end: "1%",  selectAll: true},
+    6: {start: "0in", end: "1in", selectAll: true},
+    7: {start: "0cm", end: "1cm", selectAll: true},
+    8: {start: "0mm", end: "1mm", selectAll: true},
+    9: {start: "0ex", end: "1ex", selectAll: true}
+  });
+};
+
+function* testHexIncrements(view) {
+  info("Testing keyboard increments with hex colors");
+
+  let idRuleEditor = view.element.children[0]._ruleEditor;
   let hexColorPropEditor = idRuleEditor.rule.textProps[2].editor;
+
+  yield runIncrementTest(hexColorPropEditor, view, {
+    1: {start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
+    2: {shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true},
+    3: {start: "#CCCCCC", end: "#CDCCCC", selection: [1,3]},
+    4: {shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1,3]},
+    5: {start: "#FFFFFF", end: "#FFFFFF", selectAll: true},
+    6: {down: true, shift: true, start: "#000000", end: "#000000", selectAll: true}
+  });
+};
+
+function* testRgbIncrements(view) {
+  info("Testing keyboard increments with rgb colors");
+
+  let idRuleEditor = view.element.children[0]._ruleEditor;
   let rgbColorPropEditor = idRuleEditor.rule.textProps[3].editor;
 
-  (function() {
-    info("INCREMENTS");
-    newTest( marginPropEditor, {
-      1: { alt: true, start: "0px", end: "0.1px", selectAll: true },
-      2: { start: "0px", end: "1px", selectAll: true },
-      3: { shift: true, start: "0px", end: "10px", selectAll: true },
-      4: { down: true, alt: true, start: "0.1px", end: "0px", selectAll: true },
-      5: { down: true, start: "0px", end: "-1px", selectAll: true },
-      6: { down: true, shift: true, start: "0px", end: "-10px", selectAll: true },
-      7: { pageUp: true, shift: true, start: "0px", end: "100px", selectAll: true },
-      8: { pageDown: true, shift: true, start: "0px", end: "-100px", selectAll: true,
-           nextTest: test2 }
-    });
-    EventUtils.synthesizeMouse(marginPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  })();
+  yield runIncrementTest(rgbColorPropEditor, view, {
+    1: {start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6,7]},
+    2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6,7]},
+    3: {start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6,9]},
+    4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6,9]},
+    5: {down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6,7]},
+    6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6,7]}
+  });
+};
+
+function* testShorthandIncrements(view) {
+  info("Testing keyboard increments within shorthand values");
 
-  function test2() {
-    info("UNITS");
-    newTest( paddingPropEditor, {
-      1: { start: "0px", end: "1px", selectAll: true },
-      2: { start: "0pt", end: "1pt", selectAll: true },
-      3: { start: "0pc", end: "1pc", selectAll: true },
-      4: { start: "0em", end: "1em", selectAll: true },
-      5: { start: "0%",  end: "1%",  selectAll: true },
-      6: { start: "0in", end: "1in", selectAll: true },
-      7: { start: "0cm", end: "1cm", selectAll: true },
-      8: { start: "0mm", end: "1mm", selectAll: true },
-      9: { start: "0ex", end: "1ex", selectAll: true,
-           nextTest: test3 }
-    });
-    EventUtils.synthesizeMouse(paddingPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  };
+  let idRuleEditor = view.element.children[0]._ruleEditor;
+  let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
 
-  function test3() {
-    info("HEX COLORS");
-    newTest( hexColorPropEditor, {
-      1: { start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
-      2: { shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true },
-      3: { start: "#CCCCCC", end: "#CDCCCC", selection: [1,3] },
-      4: { shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1,3] },
-      5: { start: "#FFFFFF", end: "#FFFFFF", selectAll: true },
-      6: { down: true, shift: true, start: "#000000", end: "#000000", selectAll: true,
-           nextTest: test4 }
-    });
-    EventUtils.synthesizeMouse(hexColorPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  };
+  yield runIncrementTest(paddingPropEditor, view, {
+    1: {start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4,7]},
+    2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4,7]},
+    3: {start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true},
+    4: {shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true},
+    5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8,11]},
+    6: {down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true}
+  });
+};
+
+function* testOddCases(view) {
+  info("Testing some more odd cases");
 
-  function test4() {
-    info("RGB COLORS");
-    newTest( rgbColorPropEditor, {
-      1: { start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6,7] },
-      2: { shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6,7] },
-      3: { start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6,9] },
-      4: { shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6,9] },
-      5: { down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6,7] },
-      6: { down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6,7],
-           nextTest: test5 }
-    });
-    EventUtils.synthesizeMouse(rgbColorPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  };
+  let idRuleEditor = view.element.children[0]._ruleEditor;
+  let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
 
-  function test5() {
-    info("SHORTHAND");
-    newTest( paddingPropEditor, {
-      1: { start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4,7] },
-      2: { shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4,7] },
-      3: { start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true },
-      4: { shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true },
-      5: { down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8,11] },
-      6: { down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true,
-           nextTest: test6 }
-    });
-    EventUtils.synthesizeMouse(paddingPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  };
+  yield runIncrementTest(marginPropEditor, view, {
+    1: {start: "98.7%", end: "99.7%", selection: [3,3]},
+    2: {alt: true, start: "98.7%", end: "98.8%", selection: [3,3]},
+    3: {start: "0", end: "1"},
+    4: {down: true, start: "0", end: "-1"},
+    5: {start: "'a=-1'", end: "'a=0'", selection: [4,4]},
+    6: {start: "0 -1px", end: "0 0px", selection: [2,2]},
+    7: {start: "url(-1)", end: "url(-1)", selection: [4,4]},
+    8: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,11]},
+    9: {start: "url('test1.png')", end: "url('test2.png')", selection: [9,9]},
+    10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9,9]},
+    11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9,11]},
+    12: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,12]},
+    13: {down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10,11]},
+    14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10,14]}
+  });
+};
 
-  function test6() {
-    info("ODD CASES");
-    newTest( marginPropEditor, {
-      1: { start: "98.7%", end: "99.7%", selection: [3,3] },
-      2: { alt: true, start: "98.7%", end: "98.8%", selection: [3,3] },
-      3: { start: "0", end: "1" },
-      4: { down: true, start: "0", end: "-1" },
-      5: { start: "'a=-1'", end: "'a=0'", selection: [4,4] },
-      6: { start: "0 -1px", end: "0 0px", selection: [2,2] },
-      7: { start: "url(-1)", end: "url(-1)", selection: [4,4] },
-      8: { start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,11] },
-      9: { start: "url('test1.png')", end: "url('test2.png')", selection: [9,9] },
-      10: { shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9,9] },
-      11: { down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9,11] },
-      12: { start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,12] },
-      13: { down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10,11] },
-      14: { alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10,14],
-           endTest: true }
-    });
-    EventUtils.synthesizeMouse(marginPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
-  };
+function* runIncrementTest(propertyEditor, view, tests) {
+  let editor = yield focusEditableField(propertyEditor.valueSpan);
+
+  for(let test in tests) {
+    yield testIncrement(editor, tests[test], view);
+  }
+
+  // Once properties have been set, wait for the inspector to update
+  yield view.inspector.once("inspector-updated");
 }
 
-function newTest( propEditor, tests )
-{
-  waitForEditorFocus(propEditor.element, function onElementFocus(aEditor) {
-    for( test in tests) {
-      testIncrement( aEditor, tests[test] );
-    }
-  }, false);
-}
+function* testIncrement(editor, options, view) {
+  editor.input.value = options.start;
+  let input = editor.input;
 
-function testIncrement( aEditor, aOptions )
-{
-  aEditor.input.value = aOptions.start;
-  let input = aEditor.input;
-  if ( aOptions.selectAll ) {
+  if (options.selectAll) {
     input.select();
-  } else if ( aOptions.selection ) {
-    input.setSelectionRange(aOptions.selection[0], aOptions.selection[1]);
+  } else if (options.selection) {
+    input.setSelectionRange(options.selection[0], options.selection[1]);
   }
-  is(input.value, aOptions.start, "Value initialized at " + aOptions.start);
-  input.addEventListener("keyup", function onIncrementUp() {
-    input.removeEventListener("keyup", onIncrementUp, false);
-    input = aEditor.input;
-    is(input.value, aOptions.end, "Value changed to " + aOptions.end);
-    if( aOptions.nextTest) {
-      aOptions.nextTest();
-    }
-    else if( aOptions.endTest ) {
-      finishTest();
-    }
-  }, false);
+
+  is(input.value, options.start, "Value initialized at " + options.start);
+
+  let onKeyUp = once(input, "keyup");
+
   let key;
-  key = ( aOptions.down ) ? "VK_DOWN" : "VK_UP";
-  key = ( aOptions.pageDown ) ? "VK_PAGE_DOWN" : ( aOptions.pageUp ) ? "VK_PAGE_UP" : key;
-  EventUtils.synthesizeKey(key,
-                          {altKey: aOptions.alt, shiftKey: aOptions.shift},
-                          view.doc.defaultView);
+  key = options.down ? "VK_DOWN" : "VK_UP";
+  key = options.pageDown ? "VK_PAGE_DOWN" : options.pageUp ? "VK_PAGE_UP" : key;
+  EventUtils.synthesizeKey(key, {altKey: options.alt, shiftKey: options.shift}, view.doc.defaultView);
+
+  yield onKeyUp;
+  input = editor.input;
+  is(input.value, options.end, "Value changed to " + options.end);
 }
-
-function finishTest()
-{
-  doc = view = inspector = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, onload, true);
-    doc = content.document;
-    waitForFocus(setUpTests, content);
-  }, true);
-  content.location = "data:text/html,sample document for bug 722691";
-}
--- a/browser/devtools/styleinspector/test/browser_bug726427_csstransform_tooltip.js
+++ b/browser/devtools/styleinspector/test/browser_bug726427_csstransform_tooltip.js
@@ -1,16 +1,15 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let contentDoc;
-let inspector;
-let ruleView;
-let computedView;
+"use strict";
+
+// Test that the css transform preview tooltip is shown on transform properties
 
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  #testElement {',
   '    width: 500px;',
   '    height: 300px;',
   '    background: red;',
   '    transform: skew(16deg);',
@@ -24,165 +23,65 @@ const PAGE_CONTENT = [
   '    transform-origin: bottom right;',
   '  }',
   '  [attr] {',
   '  }',
   '</style>',
   '<div id="testElement" class="test-element" attr="value">transformed element</div>'
 ].join("\n");
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view css transform tooltip test");
+  content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view css transform tooltip test";
-}
-
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  info("Selecting the test node");
+  yield selectNode("#testElement", inspector);
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    startTests();
-  });
-}
+  info("Checking that transforms tooltips are shown in various rule-view properties");
+  for (let selector of [".test-element", "div", "#testElement"]) {
+    yield testTransformTooltipOnSelector(view, selector);
+  }
 
-function startTests() {
-  inspector.selection.setNode(contentDoc.querySelector("#testElement"));
-  inspector.once("inspector-updated", testTransformTooltipOnIDSelector);
-}
-
-function endTests() {
-  contentDoc = inspector = ruleView = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  info("Checking that the transform tooltip doesn't appear for invalid transforms");
+  yield testTransformTooltipNotShownOnInvalidTransform(view);
 
-function testTransformTooltipOnIDSelector() {
-  Task.spawn(function*() {
-    info("Testing that a transform tooltip appears on the #ID rule");
-
-    let panel = ruleView.previewTooltip.panel;
-    ok(panel, "The XUL panel exists for the rule-view preview tooltips");
-
-    let {valueSpan} = getRuleViewProperty("#testElement", "transform");
-    yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
+  info("Checking transforms in the computed-view");
+  let {view} = yield openComputedView();
+  yield testTransformTooltipOnComputedView(view);
+});
 
-    // The transform preview is canvas, so there's not much we can test, so for
-    // now, let's just be happy with the fact that the tooltips is shown!
-    ok(true, "Tooltip shown on the transform property of the #ID rule");
-  }).then(testTransformTooltipOnClassSelector);
-}
-
-function testTransformTooltipOnClassSelector() {
-  Task.spawn(function*() {
-    info("Testing that a transform tooltip appears on the .class rule");
+function* testTransformTooltipOnSelector(view, selector) {
+  info("Testing that a transform tooltip appears on transform in " + selector);
 
-    let {valueSpan} = getRuleViewProperty(".test-element", "transform");
-    yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
-
-    // The transform preview is canvas, so there's not much we can test, so for
-    // now, let's just be happy with the fact that the tooltips is shown!
-    ok(true, "Tooltip shown on the transform property of the .class rule");
-  }).then(testTransformTooltipOnTagSelector);
-}
+  let {valueSpan} = getRuleViewProperty(view, selector, "transform");
+  ok(valueSpan, "The transform property was found");
+  yield assertHoverTooltipOn(view.previewTooltip, valueSpan);
 
-function testTransformTooltipOnTagSelector() {
-  Task.spawn(function*() {
-    info("Testing that a transform tooltip appears on the tag rule");
-
-    let {valueSpan} = getRuleViewProperty("div", "transform");
-    yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
-
-    // The transform preview is canvas, so there's not much we can test, so for
-    // now, let's just be happy with the fact that the tooltips is shown!
-    ok(true, "Tooltip shown on the transform property of the tag rule");
-  }).then(testTransformTooltipNotShownOnInvalidTransform);
+  // The transform preview is canvas, so there's not much we can test, so for
+  // now, let's just be happy with the fact that the tooltips is shown!
+  ok(true, "Tooltip shown on the transform property in " + selector);
 }
 
-function testTransformTooltipNotShownOnInvalidTransform() {
-  Task.spawn(function*() {
-    info("Testing that a transform tooltip does not appear for invalid values");
-
-    let ruleEditor;
-    for (let rule of ruleView._elementStyle.rules) {
-      if (rule.matchedSelectors[0] === "[attr]") {
-        ruleEditor = rule.editor;
-      }
+function* testTransformTooltipNotShownOnInvalidTransform(view) {
+  let ruleEditor;
+  for (let rule of view._elementStyle.rules) {
+    if (rule.matchedSelectors[0] === "[attr]") {
+      ruleEditor = rule.editor;
     }
-    ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
-
-    let {valueSpan} = getRuleViewProperty("[attr]", "transform");
-    let isValid = yield isHoverTooltipTarget(ruleView.previewTooltip, valueSpan);
-    ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
-  }).then(testTransformTooltipOnComputedView);
-}
+  }
+  ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
 
-function testTransformTooltipOnComputedView() {
-  Task.spawn(function*() {
-    info("Testing that a transform tooltip appears in the computed view too");
-
-    inspector.sidebar.select("computedview");
-    computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
-    let doc = computedView.styleDocument;
-
-    let panel = computedView.tooltip.panel;
-    let {valueSpan} = getComputedViewProperty("transform");
-
-    yield assertTooltipShownOn(computedView.tooltip, valueSpan);
-
-    // The transform preview is canvas, so there's not much we can test, so for
-    // now, let's just be happy with the fact that the tooltips is shown!
-    ok(true, "Tooltip shown on the computed transform property");
-  }).then(endTests);
+  let {valueSpan} = getRuleViewProperty(view, "[attr]", "transform");
+  let isValid = yield isHoverTooltipTarget(view.previewTooltip, valueSpan);
+  ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
 }
 
-function getRule(selectorText) {
-  let rule;
-
-  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-rule"), aRule => {
-    let selector = aRule.querySelector(".ruleview-selector-matched");
-    if (selector && selector.textContent === selectorText) {
-      rule = aRule;
-    }
-  });
-
-  return rule;
-}
-
-function getRuleViewProperty(selectorText, propertyName) {
-  let prop;
+function* testTransformTooltipOnComputedView(view) {
+  info("Testing that a transform tooltip appears in the computed view too");
 
-  let rule = getRule(selectorText);
-  if (rule) {
-    // Look for the propertyName in that rule element
-    [].forEach.call(rule.querySelectorAll(".ruleview-property"), property => {
-      let nameSpan = property.querySelector(".ruleview-propertyname");
-      let valueSpan = property.querySelector(".ruleview-propertyvalue");
-
-      if (nameSpan.textContent === propertyName) {
-        prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-      }
-    });
-  }
+  let {valueSpan} = getComputedViewProperty(view, "transform");
+  yield assertHoverTooltipOn(view.tooltip, valueSpan);
 
-  return prop;
+  // The transform preview is canvas, so there's not much we can test, so for
+  // now, let's just be happy with the fact that the tooltips is shown!
+  ok(true, "Tooltip shown on the computed transform property");
 }
-
-function getComputedViewProperty(name) {
-  let prop;
-  [].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
-    let nameSpan = property.querySelector(".property-name");
-    let valueSpan = property.querySelector(".property-value");
-
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
-}
--- a/browser/devtools/styleinspector/test/browser_bug765105_background_image_tooltip.js
+++ b/browser/devtools/styleinspector/test/browser_bug765105_background_image_tooltip.js
@@ -1,16 +1,16 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let contentDoc;
-let inspector;
-let ruleView;
-let computedView;
+"use strict";
+
+// Test that background-image URLs have image preview tooltips in the rule-view
+// and computed-view
 
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    padding: 1em;',
   '    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAADI5JREFUeNrsWwuQFNUVPf1m5z87szv7HWSWj8CigBFMEFZKiQsB1PgJwUAZg1HBpIQsKmokEhNjWUnFVPnDWBT+KolJYbRMoqUVq0yCClpqiX8sCchPWFwVlt2db7+X93pez7zu6Vn2NxsVWh8987p7pu+9555z7+tZjTGGY3kjOMa34w447oBjfKsY7i/UNM3Y8eFSAkD50Plgw03K5P9gvGv7U5ieeR3PszeREiPNX3/0DL4hjslzhm8THh+OITfXk3dhiv4GDtGPVzCaeJmPLYzuu5qJuWfuw2QTlcN1X9pwQU7LhdZ/ZAseD45cOh9hHvDkc/yAF/DNhdb5Mrr3PvBMaAYW8fMSIi2G497IMEK/YutGtAYr6+ej+nxu/NN8Ks3N7AR6HgcLz0Eg1Ljg1UcxZzi5qewIkMYLRweTr2Kzp+nmyXAd5pS3XQDd+N/4h4zgu9FI7brlXf90nMEnuwQxlvv+hosE3TuexmWeysmT4W+WxkMaLzf9Y8ATgjcUn7T9H1gqrpFq8eV1gMn6t16NhngjfoX6q4DUP032Rd4LJgpSLwJ1yzFqBG69eRkah0MVyo0Acfe+yy9AG4nMiYCkeM53KKFXncBLAXqEm+wCqZwaueq7WCmuLTcKSJmj737ol2hurA9eq9VdyiO8yWa3NNyog+SB5CZodSsQq/dfu34tJpYbBaTMzvVddDZu16q5smXf4G8zEvqm4cyaAmJPuTJk3oJWdS4WzcVtfMZbThSQckb/pYfRGgo3zNOqZnEHbJPGK4abaDCQIIsT8V/qTaBqHkLh6LzXH8XZQhbLhYKyyCC/WeHYcNdmvOgfe8skzbWL270/T3wf7tSx/lGCbTu8xlzzmCSWLc5iwmgikcCHi3Mga0Ry913vBFvQwg90l6M4ImWKfsWOp7DSWxmfpPlCFuPFfsNfKrCnPYpQKIRgqBK7D0SxYaNHwkEiJMtl0ReDp3Lc5D3PGoTo/sKngCl7a5chFqvBatKwjBd7WwqIlzB/78NcoUcp5VSgGxm+7b8eqQRGnHMO634epO4S1EZww09/iFg5UmGoESDuznP1xVhTUX1WWHPzjpd25wyH0hRxI3LGM75nxmuNEEUVpAN0XgxmPoKralakbQnWlIMQyVBD/w+3orkq4lvualjKyWwzt4MaxqspQHVhPOWG64bxYuhZXSFGWhipbSDVragOu5Y9eAsmDDUKyBA703vemVhHoueD6e9wAzJK1WfmN0Umk5GGM4kEMZcuIECqgjm0nldAqmbjwtm4VxZH5AvlADP6mx9Eqy9Q0+KqW8Ch+47FaMMYmnNGfY1iPMshoC6qFxme4wQ+0p+ARE6H3+9veWEDWgUhDhUKyFARn4jM5BNxT0XsMg7bfymGK1ov3wtjDfhL4w0HVGUVBEjDaaE+QNdrcNWch1PG4W6xrjBUXECGivg++Cva3JUT4iQUz3V2RsSVaKLwOuDT89A3HdBQoxhNC+fnVm74ual2EG893P6G+PuP4SfiO4cCBWQooL9qCWKNXPbcI37Aa/lnlZxXRt4RFONGwSDCPAHqOuqjWct1QiEMw5mChM5X4K47FyNqcd3aK9AwFH0CGYLoe1ctxk2eWi57rg5JfGp9rzC6ggCdFlAgHBDw5Yxlcg6G8SyHCjMlsgmDD9zhSeHlF+JnAgWDTQUy2NxfdwOao1UVV3pi3+bE97YSbWpLAbn6zefHNQkp1PMpIBwwvslKgIYTKM2nEpNzrGcH3FXTEal0L38kJ4uDQgEZbO4vnI173LXf5NHZaiUxtaCxyZuo/rK6LpUg54yg3zTWRAArvDcRIPZ6BqzrQ1REpmL+DNw32OKIDCb3X1qPVn8wNNMT4w2bvs+q4bAZrqBh2skaL3yyhhIIZ4i6oHkUK0RckcB8GigEyRIH4A6Mgc8fatl0/+BkkQxC9gIT4ljna1rIZW9rEdNbjJcNjsnoYj7LHWCUwpITzEgzRQKZ3XAFHbTzA3hrz8TEUUZxFBhoKpABQt/97p+w0hMZG68I8R6FtlsJT3FELndZntjM+VMnylKYq8GJI3UZaRMpquGSGFVOEfv0YZBMNzz+uvjbfzS6xQERIhlI9FcvQWNdFVb7x1zCb+QNK8vb9NsiifmI5hBgVoOCBC1sb0ab5RomqENxLO3eA1/0NDRU47q2RQNbRCUDIb7lF2CNL3ZGxEV4n08TVvZWYG4pZyV0zUdS45tyCBByOHWiyvZmxFXDCyRo1ge5+Sy0TA+8lWMiP/6O0S32exGV9Jf4fr8azdUR3zL/CZz4MtvzdX5uOYs6NDOmpkuj5Huh+7qUQSYl0ThHzw0YQzcGo6bhzEqoYq5rN3yRiYiG3Vfe2Ybm/qKA9NNZ3nNm4F7/yDkg9AN+U1mHiBcXP8zuDN76jj8hg1QyiWQigalj02BJPhK8I0zxijAjhp5zhlpLUDvS+BCy2HMAvvB4XDgL9/SXC0g/ou/5+6/xLX8w0uJrOIkXfPvyhY0F6gr7M8H0KWFYikcqAXakB+xwD9CdREBLoau7Gz3cAdSIdLFxFtJTCqRChSjnutvhDcREtzjz2Tswtz+yeNRFUeXZXtWux7C1fuoVcbd3J//ipDX3uZZDLGrwweS+UBLL5TDliVBnF8P7H+XI8aRRGsIBJg/Zlslt1+W+D1JWoSyi+kD9jfhs78t7mhZhSl+fLfY1Bdyv3I8V/qpY3B1McgN7ZFT5/vNO0I5DPLLdPBIJA8qc4h2I0QplYfDpJwHT+aj0246r5S8rToG8OjCle8wk4OLvvYGa+Ovr84uo2qBSwJS9G5egoZFLTfiEqWDtbwGfHgKOdPHcS+ai7XDzMPW/FJRLGGcxnBbK4YJC2K+h+T6Bdu5CqHqCWERd3bawb7JI+iJ735+LNaHaprBLLHBm08U3XxShEsdt+f3eTh3v7aC95Dct4RCWL5OZWh/oXBZThxAIxyOXLzBk8aiEWJID8rK3CpPOmeHaGpvCS+7EHv5FujVHUSJPLXvIFeHcNc+9xrB2gws9KZdxuLFax/WLM5gzzSm/lTXF/OdAcapyvjxPqxqHjr2v4ckX2bS2dRBrc5lSdpKjEJ9/9tdwX2WMd53ZQ2IVo3RES+UwVSpCPvYepNx4gmTGDUKIMQ4eduPnD7mx9xOn/KZKOlFbStjONxHTtR+BYAPmnoZ1Zp8wkBRwP/EL3u0F/C2hGl7vpz7vW37T3vP7if8wroKuoh8ribknX9BK5rcF+mo1qKaKyRPJTgTDjbzY8szcuLb3bpH00u35T47j7prRpwDJTxzyG0dHgxPp5bPG8VdkpfPbUg3SgoOo2mwVukb98D5EqpswZTTulCggTk4gpYhv0++wIhCJxr0+Hq1sondis0SE2oxQe3qWXwWyO4DSQg9gJ8Iiw1VFcGqXxet0N9xE4ygIxv/9W6wo9WyROEX/R+eiobYSq2vHTOR631Eiv2lRfh9dvxkumkXh92Qsx8XrAJ+7YGbWuhxOi/U+31NQmzyqNYG8N/3wfo6CRtRHcN01FzkvojohwLu0VVvDa56IS/xcj2b7nN+O+m0jqpE1wMPXZxAN9iCVThtDvH7gmiRGRpU8Lspv1Uhq4wIVdQoyuGSLNYPKUCS8+CzNURbzMmjK3i8u0U793lmuV0ef9nWQ5MGC/DiUqEUSaCtXna9RJEspZS1lrXINK/pcq+SpT50t98QKMq1FRmDfx3vxty102k0PM4ssEnvuz5+G26Ij4yDpz6z9fV8bkyIkqBFkhej0Ib+ZQ34XJK9AfozaiimqIoX3Jp3tiISrcfYpuN2+iFph/02P36PNC9fVcCnp6H9jYouKyfaWufz5Tp9tVxcUniw7IohZv4dZz81/ns67z3AYPrc2n0+Ix2q8k0PWjgBy88XaibnfK9A+5LdDY2Ivhy36fbT8Zv3Lb1U1qLqUxorXEEXIs0mjjrtxoTZWtdvigNs2sgPiujTv6DIZLld6b/V5742JZV3fUsUVFy5gdsNtKWFzUCEVbNepD1MkSMVbsb6SZm7jI3/zODtQKgUMsOw8wDZ63t5xcV1TnaEAxoc6wrqY+Fj+N4DsqOnhOIdicrQSm1MPYCPlIqHn5bbHg8/bj2D3QfZnCX3mpAICDZV8jH5kpbZqTD0W+DxaA74CWzLN2nd14OlL72J38Lf7+TjC7dadZFDoZJQPrtaIKL/G0L6ktptPZVJ8fMqHYPZOKYPMyQGadIJfDvdXwAFiZOTvDBPydf5vk4rWA+RfdhBlaF/yDDBRoMu9pfnSjv/p7DG+HXfAcQcc49v/BBgAcFAO4DmB2GQAAAAASUVORK5CYII=);',
   '    background-repeat: repeat-y;',
   '    background-position: right top;',
@@ -20,155 +20,102 @@ const PAGE_CONTENT = [
   '    color: #333;',
   '    background: url(chrome://global/skin/icons/warning-64.png) no-repeat left center;',
   '    padding-left: 70px;',
   '  }',
   '</style>',
   '<div class="test-element">test element</div>'
 ].join("\n");
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view tooltip test");
+  content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  info("Testing the background-image property on the body rule");
+  yield testBodyRuleView(view);
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
+  info("Selecting the test div node");
+  yield selectNode(".test-element", inspector);
+  info("Testing the the background property on the .test-element rule");
+  yield testDivRuleView(view);
 
-  content.location = "data:text/html,rule view tooltip test";
-}
+  info("Testing that image preview tooltips show even when there are fields being edited");
+  yield testTooltipAppearsEvenInEditMode(view);
 
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  info("Switching over to the computed-view");
+  let {view} = yield openComputedView();
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    startTests();
-  });
-}
+  info("Testing that the background-image computed style has a tooltip too");
+  yield testComputedView(view);
+});
+
+function* testBodyRuleView(view) {
+  info("Testing tooltips in the rule view");
+  let panel = view.previewTooltip.panel;
 
-function startTests() {
-  inspector.selection.setNode(contentDoc.body);
-  inspector.once("inspector-updated", testBodyRuleView);
-}
+  // Check that the rule view has a tooltip and that a XUL panel has been created
+  ok(view.previewTooltip, "Tooltip instance exists");
+  ok(panel, "XUL panel exists");
 
-function endTests() {
-  contentDoc = inspector = ruleView = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  // Get the background-image property inside the rule view
+  let {valueSpan} = getRuleViewProperty(view, "body", "background-image");
+  let uriSpan = valueSpan.querySelector(".theme-link");
+
+  yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
+
+  let images = panel.getElementsByTagName("image");
+  is(images.length, 1, "Tooltip contains an image");
+  ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
+    "The image URL seems fine");
 }
 
-function testBodyRuleView() {
-  Task.spawn(function*() {
-    info("Testing tooltips in the rule view");
-    let panel = ruleView.previewTooltip.panel;
-
-    // Check that the rule view has a tooltip and that a XUL panel has been created
-    ok(ruleView.previewTooltip, "Tooltip instance exists");
-    ok(panel, "XUL panel exists");
+function* testDivRuleView(view) {
+  let panel = view.previewTooltip.panel;
 
-    // Get the background-image property inside the rule view
-    let {valueSpan} = getRuleViewProperty("background-image");
-    let uriSpan = valueSpan.querySelector(".theme-link");
-
-    yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
+  // Get the background property inside the rule view
+  let {valueSpan} = getRuleViewProperty(view, ".test-element", "background");
+  let uriSpan = valueSpan.querySelector(".theme-link");
 
-    let images = panel.getElementsByTagName("image");
-    is(images.length, 1, "Tooltip contains an image");
-    ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
-      "The image URL seems fine");
+  yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
 
-    let onUpdated = inspector.once("inspector-updated");
-    inspector.selection.setNode(contentDoc.querySelector(".test-element"));
-    yield onUpdated;
-  }).then(testDivRuleView);
+  let images = panel.getElementsByTagName("image");
+  is(images.length, 1, "Tooltip contains an image");
+  ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
 }
 
-function testDivRuleView() {
-  Task.spawn(function*() {
-    let panel = ruleView.previewTooltip.panel;
-
-    // Get the background property inside the rule view
-    let {valueSpan} = getRuleViewProperty("background");
-    let uriSpan = valueSpan.querySelector(".theme-link");
+function* testTooltipAppearsEvenInEditMode(view) {
+  let panel = view.previewTooltip.panel;
 
-    yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
-
-    let images = panel.getElementsByTagName("image");
-    is(images.length, 1, "Tooltip contains an image");
-    ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
-  }).then(testTooltipAppearsEvenInEditMode);
-}
+  info("Switching to edit mode in the rule view");
+  let editor = yield turnToEditMode(view);
 
-function testTooltipAppearsEvenInEditMode() {
-  Task.spawn(function*() {
-    let panel = ruleView.previewTooltip.panel;
-
-    info("Switching to edit mode in the rule view");
-    let editor = yield turnToEditMode(ruleView);
+  info("Now trying to show the preview tooltip");
+  let {valueSpan} = getRuleViewProperty(view, ".test-element", "background");
+  let uriSpan = valueSpan.querySelector(".theme-link");
+  yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
 
-    info("Now trying to show the preview tooltip");
-    let {valueSpan} = getRuleViewProperty("background");
-    let uriSpan = valueSpan.querySelector(".theme-link");
-    yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
-
-    is(ruleView.doc.activeElement, editor.input,
-      "Tooltip was shown in edit mode, and inplace-editor still focused");
-  }).then(testComputedView);
+  is(view.doc.activeElement, editor.input,
+    "Tooltip was shown in edit mode, and inplace-editor still focused");
 }
 
 function turnToEditMode(ruleView) {
-  let def = promise.defer();
   let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
-  waitForEditorFocus(brace.parentNode, def.resolve);
-  brace.click();
-  return def.promise;
+  return focusEditableField(brace);
 }
 
-function testComputedView() {
-  Task.spawn(function*() {
-    info("Testing tooltips in the computed view");
-
-    inspector.sidebar.select("computedview");
-    computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
-    let doc = computedView.styleDocument;
+function* testComputedView(view) {
+  let tooltip = view.tooltip;
+  ok(tooltip, "The computed-view has a tooltip defined");
 
-    let panel = computedView.tooltip.panel;
-    let {valueSpan} = getComputedViewProperty("background-image");
-    let uriSpan = valueSpan.querySelector(".theme-link");
-
-    yield assertTooltipShownOn(computedView.tooltip, uriSpan);
-
-    let images = panel.getElementsByTagName("image");
-    is(images.length, 1, "Tooltip contains an image");
-
-    ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
-  }).then(endTests);
-}
+  let panel = tooltip.panel;
+  ok(panel, "The computed-view tooltip has a XUL panel");
 
-function getRuleViewProperty(name) {
-  let prop = null;
-  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
-    let nameSpan = property.querySelector(".ruleview-propertyname");
-    let valueSpan = property.querySelector(".ruleview-propertyvalue");
+  let {valueSpan} = getComputedViewProperty(view, "background-image");
+  let uriSpan = valueSpan.querySelector(".theme-link");
 
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
-}
+  yield assertHoverTooltipOn(view.tooltip, uriSpan);
 
-function getComputedViewProperty(name) {
-  let prop = null;
-  [].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
-    let nameSpan = property.querySelector(".property-name");
-    let valueSpan = property.querySelector(".property-value");
+  let images = panel.getElementsByTagName("image");
+  is(images.length, 1, "Tooltip contains an image");
 
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
+  ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
 }
--- a/browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_existing_property.js
+++ b/browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_existing_property.js
@@ -1,21 +1,19 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Test that CSS property names are autocompleted and cycled correctly.
+"use strict";
+
+// Test that CSS property names are autocompleted and cycled correctly when
+// editing an existing property in the rule view
 
 const MAX_ENTRIES = 10;
 
-let doc;
-let inspector;
-let ruleViewWindow;
-let editor;
-let state;
 // format :
 //  [
 //    what key to press,
 //    expected input box value after keypress,
 //    selectedIndex of the popup,
 //    total items in the popup
 //  ]
 let testData = [
@@ -49,109 +47,60 @@ let testData = [
   ["f", "fill", 0, MAX_ENTRIES],
   ["i", "fill", 0, 4],
   ["VK_LEFT", "fill", -1, 0],
   ["VK_LEFT", "fill", -1, 0],
   ["i", "fiill", -1, 0],
   ["VK_ESCAPE", null, -1, 0],
 ];
 
-function openRuleView()
-{
-  var target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
+let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename" +
+               ": browser_bug893965_css_property_completion_existing_property.js</h1>";
+
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-    // Highlight a node.
-    let node = content.document.getElementsByTagName("h1")[0];
-    inspector.selection.setNode(node);
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
 
-    inspector.once("inspector-updated", testCompletion);
-  });
-}
+  info("Focusing the css property editable field");
+  let propertyName = view.doc.querySelectorAll(".ruleview-propertyname")[0];
+  let editor = yield focusEditableField(propertyName);
 
-function testCompletion()
-{
-  ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
-  let brace = ruleViewWindow.document.querySelector(".ruleview-propertyname");
+  info("Starting to test for css property completion");
+  for (let i = 0; i < testData.length; i ++) {
+    yield testCompletion(testData[i], editor, view);
+  }
+});
 
-  waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-    editor = aEditor;
-    checkStateAndMoveOn(0);
-  });
+function* testCompletion([key, completion, index, total], editor, view) {
+  info("Pressing key " + key);
+  info("Expecting " + completion + ", " + index + ", " + total);
+
+  let onSuggest;
 
-  brace.click();
-}
-
-function checkStateAndMoveOn(index) {
-  if (index == testData.length) {
-    finishUp();
-    return;
+  if (/(left|right|back_space|escape)/ig.test(key)) {
+    info("Adding event listener for left|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");
   }
 
-  let [key] = testData[index];
-  state = index;
+  info("Synthesizing key " + key);
+  EventUtils.synthesizeKey(key, {}, view.doc.defaultView);
 
-  info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
-       "] for state " + state);
-  if (/(left|right|back_space|escape)/ig.test(key)) {
-    info("added event listener for right|back_space|escape keys");
-    editor.input.addEventListener("keypress", function onKeypress() {
-      if (editor.input) {
-        editor.input.removeEventListener("keypress", onKeypress);
-      }
-      info("inside event listener");
-      checkState();
-    });
-  }
-  else {
-    editor.once("after-suggest", checkState);
-  }
-  EventUtils.synthesizeKey(key, {}, ruleViewWindow);
-}
+  yield onSuggest;
+  yield wait(1); // Equivalent of executeSoon
 
-function checkState() {
-  executeSoon(() => {
-    info("After keypress for state " + state);
-    let [key, completion, index, total] = testData[state];
-    if (completion != null) {
-      is(editor.input.value, completion,
-         "Correct value is autocompleted for state " + state);
-    }
-    if (total == 0) {
-      ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
-         state);
-    }
-    else {
-      ok(editor.popup._panel.state == "open" ||
-         editor.popup._panel.state == "showing",
-         "Popup is open for state " + state);
-      is(editor.popup.getItems().length, total,
-         "Number of suggestions match for state " + state);
-      is(editor.popup.selectedIndex, index,
-         "Correct item is selected for state " + state);
-    }
-    checkStateAndMoveOn(state + 1);
-  });
+  info("Checking the state");
+  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");
+    is(editor.popup.getItems().length, total, "Number of suggestions match");
+    is(editor.popup.selectedIndex, index, "Correct item is selected");
+  }
 }
-
-function finishUp()
-{
-  doc = inspector = editor = ruleViewWindow = state = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    doc.title = "Rule View Test";
-    waitForFocus(openRuleView, content);
-  }, true);
-
-  content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename" +
-                     ": browser_bug893965_css_property_completion_existing_property.js</h1>";
-}
--- a/browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_new_property.js
+++ b/browser/devtools/styleinspector/test/browser_bug893965_css_property_completion_new_property.js
@@ -1,21 +1,19 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Test that CSS property names are autocompleted and cycled correctly.
+"use strict";
+
+// Test that CSS property names are autocompleted and cycled correctly when
+// creating a new property in the ruleview
 
 const MAX_ENTRIES = 10;
 
-let doc;
-let inspector;
-let ruleViewWindow;
-let editor;
-let state;
 // format :
 //  [
 //    what key to press,
 //    expected input box value after keypress,
 //    selectedIndex of the popup,
 //    total items in the popup
 //  ]
 let testData = [
@@ -34,103 +32,60 @@ let testData = [
   ["VK_BACK_SPACE", "di", -1, 0],
   ["VK_BACK_SPACE", "d", -1, 0],
   ["VK_BACK_SPACE", "", -1, 0],
   ["f", "fill", 0, MAX_ENTRIES],
   ["i", "fill", 0, 4],
   ["VK_ESCAPE", null, -1, 0],
 ];
 
-function openRuleView() {
-  var target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
+let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename:" +
+               "browser_bug893965_css_property_completion_new_property.js</h1>";
+
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-    // Highlight a node.
-    let node = content.document.getElementsByTagName("h1")[0];
-    inspector.selection.setNode(node);
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
 
-    inspector.once("inspector-updated", testCompletion);
-  });
-}
+  info("Focusing the css property editable field");
+  let brace = view.doc.querySelector(".ruleview-ruleclose");
+  let editor = yield focusEditableField(brace);
 
-function testCompletion() {
-  ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
-  let brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
+  info("Starting to test for css property completion");
+  for (let i = 0; i < testData.length; i ++) {
+    yield testCompletion(testData[i], editor, view);
+  }
+});
 
-  waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-    editor = aEditor;
-    checkStateAndMoveOn(0);
-  });
+function* testCompletion([key, completion, index, total], editor, view) {
+  info("Pressing key " + key);
+  info("Expecting " + completion + ", " + index + ", " + total);
+
+  let onSuggest;
 
-  brace.click();
-}
-
-function checkStateAndMoveOn(index) {
-  if (index == testData.length) {
-    finishUp();
-    return;
+  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");
   }
 
-  let [key] = testData[index];
-  state = index;
+  info("Synthesizing key " + key);
+  EventUtils.synthesizeKey(key, {}, view.doc.defaultView);
 
-  info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
-       "] for state " + state);
-  if (/(return|back_space|escape)/ig.test(key)) {
-    info("added event listener for return|back_space|escape keys");
-    editor.input.addEventListener("keypress", function onKeypress() {
-      if (editor.input) {
-        editor.input.removeEventListener("keypress", onKeypress);
-      }
-      info("inside event listener");
-      checkState();
-    });
-  }
-  else {
-    editor.once("after-suggest", checkState);
-  }
-  EventUtils.synthesizeKey(key, {}, ruleViewWindow);
-}
+  yield onSuggest;
+  yield wait(1); // Equivalent of executeSoon
 
-function checkState(event) {
-  executeSoon(() => {
-    info("After keypress for state " + state);
-    let [key, completion, index, total] = testData[state];
-    if (completion != null) {
-      is(editor.input.value, completion,
-         "Correct value is autocompleted for state " + state);
-    }
-    if (total == 0) {
-      ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
-         state);
-    }
-    else {
-      ok(editor.popup.isOpen, "Popup is open for state " + state);
-      is(editor.popup.getItems().length, total,
-         "Number of suggestions match for state " + state);
-      is(editor.popup.selectedIndex, index,
-         "Correct item is selected for state " + state);
-    }
-    checkStateAndMoveOn(state + 1);
-  });
+  info("Checking the state");
+  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");
+    is(editor.popup.getItems().length, total, "Number of suggestions match");
+    is(editor.popup.selectedIndex, index, "Correct item is selected");
+  }
 }
-
-function finishUp() {
-  doc = inspector = editor = ruleViewWindow = state = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test() {
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    doc.title = "Rule View Test";
-    waitForFocus(openRuleView, content);
-  }, true);
-
-  content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename:" +
-                     "browser_bug893965_css_property_completion_new_property.js</h1>";
-}
--- a/browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_existing_property_value_pair.js
+++ b/browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_existing_property_value_pair.js
@@ -1,22 +1,17 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Test that CSS property names are autocompleted and cycled correctly.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const MAX_ENTRIES = 10;
+"use strict";
 
-let doc;
-let inspector;
-let ruleViewWindow;
-let editor;
-let state;
-let brace;
+// Test that CSS property names and values are autocompleted and cycled correctly
+// when editing existing properties in the rule view
+
 // format :
 //  [
 //    what key to press,
 //    modifers,
 //    expected input box value after keypress,
 //    selectedIndex of the popup,
 //    total items in the popup
 //  ]
@@ -36,115 +31,71 @@ let testData = [
   ["d", {}, "direction", 0, 3],
   ["i", {}, "direction", 0, 2],
   ["s", {}, "display", -1, 0],
   ["VK_TAB", {}, "blue", -1, 0],
   ["n", {}, "none", -1, 0],
   ["VK_RETURN", {}, null, -1, 0]
 ];
 
-function openRuleView()
-{
-  var target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
+let TEST_URL = "data:text/html,<h1 style='color: red'>Filename: " +
+               "browser_bug894376_css_value_completion_existing_property_value_pair.js</h1>";
+
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-    // Highlight a node.
-    let node = content.document.getElementsByTagName("h1")[0];
-    inspector.selection.setNode(node);
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
 
-    inspector.once("inspector-updated", testCompletion);
-  });
-}
+  info("Focusing the css property editable value");
+  let value = view.doc.querySelectorAll(".ruleview-propertyvalue")[0];
+  let editor = yield focusEditableField(value);
 
-function testCompletion()
-{
-  ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
-  brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
+  info("Starting to test for css property completion");
+  for (let i = 0; i < testData.length; i ++) {
+    // Re-define the editor at each iteration, because the focus may have moved
+    // from property to value and back
+    editor = inplaceEditor(view.doc.activeElement);
+    yield testCompletion(testData[i], editor, view);
+  }
+});
+
+function* testCompletion([key, modifiers, completion, index, total], editor, view) {
+  info("Pressing key " + key);
+  info("Expecting " + completion + ", " + index + ", " + total);
 
-  waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-    editor = aEditor;
-    checkStateAndMoveOn(0);
-  });
+  let onKeyPress;
 
-  ruleViewWindow.document.querySelector(".ruleview-propertyvalue").click();
-}
-
-function checkStateAndMoveOn(index) {
-  if (index == testData.length) {
-    finishUp();
-    return;
+  if (/tab/ig.test(key)) {
+    info("Waiting for the new property or value editor to get focused");
+    let brace = view.doc.querySelector(".ruleview-ruleclose");
+    onKeyPress = once(brace.parentNode, "focus", true);
+  } else if (/(right|return|back_space)/ig.test(key)) {
+    info("Adding event listener for right|return|back_space keys");
+    onKeyPress = once(editor.input, "keypress");
+  } else {
+    info("Waiting for after-suggest event on the editor");
+    onKeyPress = editor.once("after-suggest");
   }
 
-  let [key, modifiers] = testData[index];
-  state = index;
+  info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
+  EventUtils.synthesizeKey(key, modifiers, view.doc.defaultView);
 
-  info("pressing key " + key + " to get result: [" + testData[index].slice(2) +
-       "] for state " + state);
-  if (/tab/ig.test(key)) {
-    info("waiting for the editor to get focused");
-    waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-      info("editor focused : " + aEditor.input);
-      editor = aEditor;
-      checkState();
-    });
-  }
-  else if (/(right|return|back_space)/ig.test(key)) {
-    info("added event listener for right|return|back_space keys");
-    editor.input.addEventListener("keypress", function onKeypress() {
-      if (editor.input) {
-        editor.input.removeEventListener("keypress", onKeypress);
-      }
-      info("inside event listener");
-      checkState();
-    });
-  }
-  else {
-    editor.once("after-suggest", checkState);
-  }
-  EventUtils.synthesizeKey(key, modifiers, ruleViewWindow);
-}
+  yield onKeyPress;
+  yield wait(1); // Equivalent of executeSoon
+
+  // The key might have been a TAB or shift-TAB, in which case the editor will
+  // be a new one
+  editor = inplaceEditor(view.doc.activeElement);
 
-function checkState(event) {
-  executeSoon(() => {
-    info("After keypress for state " + state);
-    let [key, modifier, completion, index, total] = testData[state];
-    if (completion != null) {
-      is(editor.input.value, completion,
-         "Correct value is autocompleted for state " + state);
-    }
-    if (total == 0) {
-      ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
-         state);
-    }
-    else {
-      ok(editor.popup.isOpen, "Popup is open for state " + state);
-      is(editor.popup.getItems().length, total,
-         "Number of suggestions match for state " + state);
-      is(editor.popup.selectedIndex, index,
-         "Correct item is selected for state " + state);
-    }
-    checkStateAndMoveOn(state + 1);
-  });
+  info("Checking the state");
+  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");
+    is(editor.popup.getItems().length, total, "Number of suggestions match");
+    is(editor.popup.selectedIndex, index, "Correct item is selected");
+  }
 }
-
-function finishUp()
-{
-  brace = doc = inspector = editor = ruleViewWindow = state = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    doc.title = "Rule View Test";
-    waitForFocus(openRuleView, content);
-  }, true);
-
-  content.location = "data:text/html,<h1 style='color: red'>Filename: " +
-                     "browser_bug894376_css_value_completion_existing_property_value_pair.js</h1>";
-}
--- a/browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_new_property_value_pair.js
+++ b/browser/devtools/styleinspector/test/browser_bug894376_css_value_completion_new_property_value_pair.js
@@ -1,22 +1,17 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-// Test that CSS property names are autocompleted and cycled correctly.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const MAX_ENTRIES = 10;
+"use strict";
 
-let doc;
-let inspector;
-let ruleViewWindow;
-let editor;
-let state;
-let brace;
+// Test that CSS property names and values are autocompleted and cycled correctly
+// when editing new properties in the rule view
+
 // format :
 //  [
 //    what key to press,
 //    modifers,
 //    expected input box value after keypress,
 //    selectedIndex of the popup,
 //    total items in the popup
 //  ]
@@ -37,112 +32,72 @@ let testData = [
   ["VK_DOWN", {}, "rgba", 2, 5],
   ["VK_DOWN", {}, "rosybrown", 3, 5],
   ["VK_DOWN", {}, "royalblue", 4, 5],
   ["VK_RIGHT", {}, "royalblue", -1, 0],
   [" ", {}, "royalblue !important", 0, 10],
   ["!", {}, "royalblue !important", 0, 0],
   ["VK_ESCAPE", {}, null, -1, 0]
 ];
-function openRuleView() {
-  var target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
+
+let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename:"+
+               " browser_bug894376_css_value_completion_new_property_value_pair.js</h1>";
 
-    // Highlight a node.
-    let node = content.document.getElementsByTagName("h1")[0];
-    inspector.selection.setNode(node);
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-    inspector.once("inspector-updated", testCompletion);
-  });
-}
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
+
+  info("Focusing a new css property editable property");
+  let brace = view.doc.querySelectorAll(".ruleview-ruleclose")[0];
+  let editor = yield focusEditableField(brace);
 
-function testCompletion() {
-  ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
-  brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
+  info("Starting to test for css property completion");
+  for (let i = 0; i < testData.length; i ++) {
+    // Re-define the editor at each iteration, because the focus may have moved
+    // from property to value and back
+    editor = inplaceEditor(view.doc.activeElement);
+    yield testCompletion(testData[i], editor, view);
+  }
+});
+
+function* testCompletion([key, modifiers, completion, index, total], editor, view) {
+  info("Pressing key " + key);
+  info("Expecting " + completion + ", " + index + ", " + total);
 
-  waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-    editor = aEditor;
-    checkStateAndMoveOn(0);
-  });
+  let onKeyPress;
 
-  brace.click();
-}
-
-function checkStateAndMoveOn(index) {
-  if (index == testData.length) {
-    finishUp();
-    return;
+  if (/tab/ig.test(key)) {
+    info("Waiting for the new property or value editor to get focused");
+    let brace = view.doc.querySelector(".ruleview-ruleclose");
+    onKeyPress = once(brace.parentNode, "focus", true);
+  } else if (/(right|back_space|escape|return)/ig.test(key) ||
+             (modifiers.accelKey || modifiers.ctrlKey)) {
+    info("Adding event listener for right|escape|back_space|return keys");
+    onKeyPress = once(editor.input, "keypress");
+  } else {
+    info("Waiting for after-suggest event on the editor");
+    onKeyPress = editor.once("after-suggest");
   }
 
-  let [key, modifiers] = testData[index];
-  state = index;
+  info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
+  EventUtils.synthesizeKey(key, modifiers, view.doc.defaultView);
 
-  info("pressing key " + key + " to get result: [" + testData[index].slice(2) +
-       "] for state " + state);
-  if (/tab/ig.test(key)) {
-    info("waiting for the editor to get focused");
-    waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-      info("editor focused : " + aEditor.input);
-      editor = aEditor;
-      checkState();
-    });
-  }
-  else if (/(right|back_space|escape|return)/ig.test(key) ||
-           (modifiers.accelKey || modifiers.ctrlKey)) {
-    info("added event listener for right|escape|back_space|return keys");
-    editor.input.addEventListener("keypress", function onKeypress() {
-      if (editor.input) {
-        editor.input.removeEventListener("keypress", onKeypress);
-      }
-      info("inside event listener");
-      checkState();
-    });
-  }
-  else {
-    editor.once("after-suggest", checkState);
-  }
-  EventUtils.synthesizeKey(key, modifiers, ruleViewWindow);
-}
+  yield onKeyPress;
+  yield wait(1); // Equivalent of executeSoon
 
-function checkState(event) {
-  executeSoon(() => {
-    info("After keypress for state " + state);
-    let [key, modifier, completion, index, total] = testData[state];
-    if (completion != null) {
-      is(editor.input.value, completion,
-         "Correct value is autocompleted for state " + state);
-    }
-    if (total == 0) {
-      ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
-         state);
-    }
-    else {
-      ok(editor.popup.isOpen, "Popup is open for state " + state);
-      is(editor.popup.getItems().length, total,
-         "Number of suggestions match for state " + state);
-      is(editor.popup.selectedIndex, index,
-         "Correct item is selected for state " + state);
-    }
-    checkStateAndMoveOn(state + 1);
-  });
+  info("Checking the state");
+  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.doc.activeElement);
+    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");
+    is(editor.popup.getItems().length, total, "Number of suggestions match");
+    is(editor.popup.selectedIndex, index, "Correct item is selected");
+  }
 }
-
-function finishUp() {
-  brace = doc = inspector = editor = ruleViewWindow = state = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test() {
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    doc.title = "Rule View Test";
-    waitForFocus(openRuleView, content);
-  }, true);
-
-  content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename:"+
-                     " browser_bug894376_css_value_completion_new_property_value_pair.js</h1>";
-}
--- a/browser/devtools/styleinspector/test/browser_bug913014_matched_expand.js
+++ b/browser/devtools/styleinspector/test/browser_bug913014_matched_expand.js
@@ -1,125 +1,108 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
-let inspector;
-let view;
-let viewDoc;
+"use strict";
 
-const DOCUMENT_URL = "data:text/html," + encodeURIComponent([
+// Test that the computed view properties can be expanded and collapsed with
+// either the twisty or by dbl-clicking on the container
+
+const TEST_URL = "data:text/html," + encodeURIComponent([
   '<html>' +
   '<head>' +
   '  <title>Computed view toggling test</title>',
   '  <style type="text/css"> ',
   '    html { color: #000000; font-size: 15pt; } ',
   '    h1 { color: red; } ',
   '  </style>',
   '</head>',
   '<body>',
   '  <h1>Some header text</h1>',
   '</body>',
   '</html>'
 ].join("\n"));
 
-function test()
-{
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(function () { openComputedView(startTests); }, content);
-  }, true);
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
 
-  content.location = DOCUMENT_URL;
-}
+  yield testExpandOnTwistyClick(view, inspector);
+  yield testCollapseOnTwistyClick(view, inspector);
+  yield testExpandOnDblClick(view, inspector);
+  yield testCollapseOnDblClick(view, inspector);
+});
 
-function startTests(aInspector, aview)
-{
-  inspector = aInspector;
-  view = aview;
-  viewDoc = view.styleDocument;
+function* testExpandOnTwistyClick({styleDocument, styleWindow}, inspector) {
+  info("Testing that a property expands on twisty click");
+
+  info("Getting twisty element");
+  let twisty = styleDocument.querySelector(".expandable");
+  ok(twisty, "Twisty found");
 
-  testExpandOnTwistyClick();
-}
+  let onExpand = inspector.once("computed-view-property-expanded");
+  info("Clicking on the twisty element");
+  twisty.click();
 
-function endTests()
-{
-  doc = inspector = view = viewDoc = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  yield onExpand;
+
+  // Expanded means the matchedselectors div is not empty
+  let div = styleDocument.querySelector(".property-content .matchedselectors");
+  ok(div.childNodes.length > 0, "Matched selectors are expanded on twisty click");
 }
 
-function testExpandOnTwistyClick()
-{
-  let h1 = doc.querySelector("h1");
-  ok(h1, "H1 exists");
-
-  inspector.selection.setNode(h1);
-  inspector.once("inspector-updated", () => {
-    // Get the first twisty
-    let twisty = viewDoc.querySelector(".expandable");
-    ok(twisty, "Twisty found");
+function* testCollapseOnTwistyClick({styleDocument, styleWindow}, inspector) {
+  info("Testing that a property collapses on twisty click");
 
-    // Click and check whether it's been expanded
-    inspector.once("computed-view-property-expanded", () => {
-      // Expanded means the matchedselectors div is not empty
-      let div = viewDoc.querySelector(".property-content .matchedselectors");
-      ok(div.childNodes.length > 0, "Matched selectors are expanded on twisty click");
-
-      testCollapseOnTwistyClick();
-    });
-    twisty.click();
-  });
-}
-
-function testCollapseOnTwistyClick() {
-  // Get the same first twisty again
-  let twisty = viewDoc.querySelector(".expandable");
+  info("Getting twisty element");
+  let twisty = styleDocument.querySelector(".expandable");
   ok(twisty, "Twisty found");
 
-  // Click and check whether matched selectors are collapsed now
-  inspector.once("computed-view-property-collapsed", () => {
-    // Collapsed means the matchedselectors div is empty
-    let div = viewDoc.querySelector(".property-content .matchedselectors");
-    ok(div.childNodes.length === 0, "Matched selectors are collapsed on twisty click");
+  let onCollapse = inspector.once("computed-view-property-collapsed");
+  info("Clicking on the twisty element");
+  twisty.click();
 
-    testExpandOnDblClick();
-  });
-  twisty.click();
+  yield onCollapse;
+
+  // Collapsed means the matchedselectors div is empty
+  let div = styleDocument.querySelector(".property-content .matchedselectors");
+  ok(div.childNodes.length === 0, "Matched selectors are collapsed on twisty click");
 }
 
-function testExpandOnDblClick()
-{
-  // Get the computed rule container, not the twisty this time
-  let container = viewDoc.querySelector(".property-view");
+function* testExpandOnDblClick({styleDocument, styleWindow}, inspector) {
+  info("Testing that a property expands on container dbl-click");
+
+  info("Getting computed property container");
+  let container = styleDocument.querySelector(".property-view");
+  ok(container, "Container found");
 
-  // Dblclick on it and check if it expands the matched selectors
-  inspector.once("computed-view-property-expanded", () => {
-    // Expanded means the matchedselectors div is not empty
-    let div = viewDoc.querySelector(".property-content .matchedselectors");
-    ok(div.childNodes.length > 0, "Matched selectors are expanded on dblclick");
+  let onExpand = inspector.once("computed-view-property-expanded");
+  info("Dbl-clicking on the container");
+  EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, styleWindow);
 
-    testCollapseOnDblClick();
-  });
-  EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, view.styleWindow);
+  yield onExpand;
+
+  // Expanded means the matchedselectors div is not empty
+  let div = styleDocument.querySelector(".property-content .matchedselectors");
+  ok(div.childNodes.length > 0, "Matched selectors are expanded on dblclick");
 }
 
-function testCollapseOnDblClick()
-{
-  // Get the computed rule container, not the twisty this time
-  let container = viewDoc.querySelector(".property-view");
+function* testCollapseOnDblClick({styleDocument, styleWindow}, inspector) {
+  info("Testing that a property collapses on container dbl-click");
+
+  info("Getting computed property container");
+  let container = styleDocument.querySelector(".property-view");
+  ok(container, "Container found");
 
-  // Dblclick on it and check if it expands the matched selectors
-  inspector.once("computed-view-property-collapsed", () => {
-    // Collapsed means the matchedselectors div is empty
-    let div = viewDoc.querySelector(".property-content .matchedselectors");
-    ok(div.childNodes.length === 0, "Matched selectors are collapsed on dblclick");
+  let onCollapse = inspector.once("computed-view-property-collapsed");
+  info("Dbl-clicking on the container");
+  EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, styleWindow);
 
-    endTests();
-  });
-  EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, view.styleWindow);
+  yield onCollapse;
+
+  // Collapsed means the matchedselectors div is empty
+  let div = styleDocument.querySelector(".property-content .matchedselectors");
+  ok(div.childNodes.length === 0, "Matched selectors are collapsed on dblclick");
 }
--- a/browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js
+++ b/browser/devtools/styleinspector/test/browser_bug940500_rule_view_pick_gradient_color.js
@@ -1,135 +1,76 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 // Test that changing a color in a gradient css declaration using the tooltip
 // color picker works
 
-let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
-
-let contentDoc;
-let contentWin;
-let inspector;
-let ruleView;
-
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    background-image: linear-gradient(to left, #f06 25%, #333 95%, #000 100%);',
   '  }',
   '</style>',
   'Updating a gradient declaration with the color picker tooltip'
 ].join("\n");
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    contentWin = contentDoc.defaultView;
-    waitForFocus(createDocument, content);
-  }, true);
+  info("Creating the test document");
+  content.document.body.innerHTML = PAGE_CONTENT;
 
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  info("Opening the rule-view")
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    startTests();
-  });
-}
-
-function startTests() {
-  inspector.selection.setNode(contentDoc.body);
-  inspector.once("inspector-updated", testColorParsing);
-}
+  info("Testing that the colors in gradient properties are parsed correctly");
+  testColorParsing(view);
 
-function endTests() {
-  executeSoon(function() {
-    gDevTools.once("toolbox-destroyed", () => {
-      contentDoc = contentWin = inspector = ruleView = null;
-      gBrowser.removeCurrentTab();
-      finish();
-    });
-    inspector._toolbox.destroy();
-  });
-}
+  info("Testing that changing one of the colors of a gradient property works");
+  yield testPickingNewColor(view);
+});
 
-function testColorParsing() {
-  let ruleEl = getRuleViewProperty("background-image");
+function testColorParsing(view) {
+  let ruleEl = getRuleViewProperty(view, "body", "background-image");
   ok(ruleEl, "The background-image gradient declaration was found");
 
   let swatchEls = ruleEl.valueSpan.querySelectorAll(".ruleview-colorswatch");
   ok(swatchEls, "The color swatch elements were found");
   is(swatchEls.length, 3, "There are 3 color swatches");
 
   let colorEls = ruleEl.valueSpan.querySelectorAll(".ruleview-color");
   ok(colorEls, "The color elements were found");
   is(colorEls.length, 3, "There are 3 color values");
 
   let colors = ["#F06", "#333", "#000"];
   for (let i = 0; i < colors.length; i ++) {
     is(colorEls[i].textContent, colors[i], "The right color value was found");
   }
-
-  testPickingNewColor();
 }
 
-function testPickingNewColor() {
+function* testPickingNewColor(view) {
   // Grab the first color swatch and color in the gradient
-  let ruleEl = getRuleViewProperty("background-image");
+  let ruleEl = getRuleViewProperty(view, "body", "background-image");
   let swatchEl = ruleEl.valueSpan.querySelector(".ruleview-colorswatch");
   let colorEl = ruleEl.valueSpan.querySelector(".ruleview-color");
 
-  // Get the color picker tooltip
-  let cPicker = ruleView.colorPicker;
-
-  cPicker.tooltip.once("shown", () => {
-    simulateColorChange(cPicker, [1, 1, 1, 1]);
+  info("Getting the color picker tooltip and clicking on the swatch to show it");
+  let cPicker = view.colorPicker;
+  let onShown = cPicker.tooltip.once("shown");
+  swatchEl.click();
+  yield onShown;
 
-    executeSoon(() => {
-      is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
-        "The color swatch's background was updated");
-      is(colorEl.textContent, "rgba(1, 1, 1, 1)",
-        "The color text was updated");
-      is(content.getComputedStyle(content.document.body).backgroundImage,
-        "linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
-        "The gradient has been updated correctly");
-
-      cPicker.hide();
-      endTests();
-    });
-  });
-  swatchEl.click();
-}
+  yield simulateColorPickerChange(cPicker, [1, 1, 1, 1]);
 
-function simulateColorChange(colorPicker, newRgba) {
-  // Note that this test isn't concerned with simulating events to test how the
-  // spectrum color picker reacts, see browser_spectrum.js for this.
-  // This test only cares about the color swatch <-> color picker <-> rule view
-  // interactions. That's why there's no event simulations here
-  colorPicker.spectrum.then(spectrum => {
-    spectrum.rgb = newRgba;
-    spectrum.updateUI();
-    spectrum.onChange();
-  });
-}
+  is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
+    "The color swatch's background was updated");
+  is(colorEl.textContent, "rgba(1, 1, 1, 1)",
+    "The color text was updated");
+  is(content.getComputedStyle(content.document.body).backgroundImage,
+    "linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
+    "The gradient has been updated correctly");
 
-function getRuleViewProperty(name) {
-  let prop = null;
-  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
-    let nameSpan = property.querySelector(".ruleview-propertyname");
-    let valueSpan = property.querySelector(".ruleview-propertyvalue");
-
-    if (nameSpan.textContent === name) {
-      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
-    }
-  });
-  return prop;
+  cPicker.hide();
 }
--- a/browser/devtools/styleinspector/test/browser_bug942297_user_property_reset.js
+++ b/browser/devtools/styleinspector/test/browser_bug942297_user_property_reset.js
@@ -1,128 +1,90 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 // Test that user set style properties can be changed from the markup-view and
 // don't survive page reload
 
-let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
-let promise = devtools.require("sdk/core/promise");
-let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
-
 let TEST_PAGE = [
   "data:text/html,",
   "<p id='id1' style='width:200px;'>element 1</p>",
   "<p id='id2' style='width:100px;'>element 2</p>"
 ].join("");
 
-let doc;
-let inspector;
-let ruleView;
-let markupView;
-
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab(TEST_PAGE);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
-    doc = content.document;
-    waitForFocus(() => {
-      openRuleView((aInspector, aView) => {
-        inspector = aInspector;
-        ruleView = aView;
-        markupView = inspector.markup;
-
-        Task.spawn(function() {
-          yield selectElement("id1");
-          yield modifyRuleViewWidth("300px");
-          assertRuleAndMarkupViewWidth("id1", "300px");
-          yield selectElement("id2");
-          assertRuleAndMarkupViewWidth("id2", "100px");
-          yield modifyRuleViewWidth("50px");
-          assertRuleAndMarkupViewWidth("id2", "50px");
+  yield selectNode("#id1", inspector);
+  yield modifyRuleViewWidth("300px", view, inspector);
+  assertRuleAndMarkupViewWidth("id1", "300px", view, inspector);
 
-          yield reloadPage();
-          yield selectElement("id1");
-          assertRuleAndMarkupViewWidth("id1", "200px");
-          yield selectElement("id2");
-          assertRuleAndMarkupViewWidth("id2", "100px");
+  yield selectNode("#id2", inspector);
+  assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
+  yield modifyRuleViewWidth("50px", view, inspector);
+  assertRuleAndMarkupViewWidth("id2", "50px", view, inspector);
 
-          finishTest();
-        }).then(null, Cu.reportError);
-      });
-    }, content);
-  }, true);
-
-  content.location = TEST_PAGE;
-}
+  yield reloadPage(inspector);
 
-function finishTest() {
-  doc = inspector = ruleView = markupView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  yield selectNode("#id1", inspector);
+  assertRuleAndMarkupViewWidth("id1", "200px", view, inspector);
+  yield selectNode("#id2", inspector);
+  assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
+});
 
-function selectElement(id) {
-  let deferred = promise.defer();
-  inspector.selection.setNode(doc.getElementById(id));
-  inspector.once("inspector-updated", deferred.resolve);
-  return deferred.promise;
-}
-
-function getStyleRule() {
+function getStyleRule(ruleView) {
   return ruleView.doc.querySelector(".ruleview-rule");
 }
 
-function modifyRuleViewWidth(value) {
-  let deferred = promise.defer();
+function* modifyRuleViewWidth(value, ruleView, inspector) {
+  info("Getting the property value element");
+  let valueSpan = getStyleRule(ruleView).querySelector(".ruleview-propertyvalue");
+
+  info("Focusing the property value to set it to edit mode");
+  let editor = yield focusEditableField(valueSpan.parentNode);
+
+  ok(editor.input, "The inplace-editor field is ready");
+  info("Setting the new value");
+  editor.input.value = value;
 
-  let valueSpan = getStyleRule().querySelector(".ruleview-propertyvalue");
-  waitForEditorFocus(valueSpan.parentNode, () => {
-    let editor = inplaceEditor(valueSpan);
-    editor.input.value = value;
-    waitForEditorBlur(editor, () => {
-      // Changing the style will refresh the markup view, let's wait for that
-      inspector.once("markupmutation", () => {
-        waitForEditorBlur({input: ruleView.doc.activeElement}, deferred.resolve);
-        EventUtils.sendKey("escape");
-      });
-    });
-    EventUtils.sendKey("return");
-  });
-  valueSpan.click();
+  info("Pressing return and waiting for the field to blur and for the markup-view to show the mutation");
+  let onBlur = once(editor.input, "blur", true);
+  let onMutation = inspector.once("markupmutation");
+  EventUtils.sendKey("return");
+  yield onBlur;
+  yield onMutation;
 
-  return deferred.promise;
+  info("Escaping out of the new property field that has been created after the value was edited");
+  let onNewFieldBlur = once(ruleView.doc.activeElement, "blur", true);
+  EventUtils.sendKey("escape");
+  yield onNewFieldBlur;
 }
 
-function getContainerStyleAttrValue(id) {
-  let front = markupView.walker.frontForRawNode(doc.getElementById(id));
-  let container = markupView.getContainer(front);
+function getContainerStyleAttrValue(id, {markup}) {
+  let front = markup.walker.frontForRawNode(content.document.getElementById(id));
+  let container = markup.getContainer(front);
 
   let attrIndex = 0;
   for (let attrName of container.elt.querySelectorAll(".attr-name")) {
     if (attrName.textContent === "style") {
       return container.elt.querySelectorAll(".attr-value")[attrIndex];
     }
     attrIndex ++;
   }
 }
 
-function assertRuleAndMarkupViewWidth(id, value) {
-  let valueSpan = getStyleRule().querySelector(".ruleview-propertyvalue");
+function assertRuleAndMarkupViewWidth(id, value, ruleView, inspector) {
+  let valueSpan = getStyleRule(ruleView).querySelector(".ruleview-propertyvalue");
   is(valueSpan.textContent, value, "Rule-view style width is " + value + " as expected");
 
-  let attr = getContainerStyleAttrValue(id);
+  let attr = getContainerStyleAttrValue(id, inspector);
   is(attr.textContent.replace(/\s/g, ""), "width:" + value + ";", "Markup-view style attribute width is " + value);
 }
 
-function reloadPage() {
-  let deferred = promise.defer();
-  inspector.once("new-root", () => {
-    doc = content.document;
-    markupView = inspector.markup;
-    markupView._waitForChildren().then(deferred.resolve);
-  });
+function reloadPage(inspector) {
+  let onNewRoot = inspector.once("new-root");
   content.location.reload();
-  return deferred.promise;
+  return onNewRoot.then(inspector.markup._waitForChildren);
 }
--- a/browser/devtools/styleinspector/test/browser_bug946331_close_tooltip_on_new_selection.js
+++ b/browser/devtools/styleinspector/test/browser_bug946331_close_tooltip_on_new_selection.js
@@ -1,81 +1,49 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let contentDoc;
-let inspector;
-let ruleView;
-let computedView;
+"use strict";
 
-const PAGE_CONTENT = '<div class="one">el 1</div><div class="two">el 2</div>';
+// Test that if a tooltip is visible when a new selection is made, it closes
 
-function test() {
-  waitForExplicitFinish();
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,<div class='one'>el 1</div><div class='two'>el 2</div>");
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    contentDoc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield selectNode(".one", inspector);
+
+  info("Testing rule view tooltip closes on new selection");
+  yield testRuleView(view, inspector);
 
-  content.location = "data:text/html,rule/computed views tooltip hiding test";
-}
-
-function createDocument() {
-  contentDoc.body.innerHTML = PAGE_CONTENT;
+  info("Testing computed view tooltip closes on new selection");
+  let {view} = yield openComputedView();
+  yield testComputedView(view, inspector);
+});
 
-  openView("ruleview", (aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    openView("computedview", (_, aComputedView) => {
-      computedView = aComputedView;
-      startTests();
-    });
-  });
-}
+function* testRuleView(ruleView, inspector) {
+  info("Showing the tooltip");
+  let tooltip = ruleView.previewTooltip;
+  let onShown = tooltip.once("shown");
+  tooltip.show();
+  yield onShown;
 
-function startTests() {
-  inspector.selection.setNode(contentDoc.querySelector(".one"));
-  inspector.once("inspector-updated", testRuleView);
+  info("Selecting a new node");
+  let onHidden = tooltip.once("hidden");
+  yield selectNode(".two", inspector);
+
+  ok(true, "Rule view tooltip closed after a new node got selected");
 }
 
-function endTests() {
-  contentDoc = inspector = ruleView = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function testRuleView() {
-  info("Testing rule view tooltip closes on new selection");
-
-  // Show the rule view tooltip
-  let tooltip = ruleView.previewTooltip;
+function* testComputedView(computedView, inspector) {
+  info("Showing the tooltip");
+  let tooltip = computedView.tooltip;
+  let onShown = tooltip.once("shown");
   tooltip.show();
-  tooltip.once("shown", () => {
-    // Select a new node and assert that the tooltip closes
-    tooltip.once("hidden", () => {
-      ok(true, "Rule view tooltip closed after a new node got selected");
-      inspector.once("inspector-updated", testComputedView);
-    });
-    inspector.selection.setNode(contentDoc.querySelector(".two"));
-  });
-}
-
-function testComputedView() {
-  info("Testing computed view tooltip closes on new selection");
+  yield onShown;
 
-  inspector.sidebar.select("computedview");
+  info("Selecting a new node");
+  let onHidden = tooltip.once("hidden");
+  yield selectNode(".one", inspector);
 
-  // Show the computed view tooltip
-  let tooltip = computedView.tooltip;
-  tooltip.show();
-  tooltip.once("shown", () => {
-    // Select a new node and assert that the tooltip closes
-    tooltip.once("hidden", () => {
-      ok(true, "Computed view tooltip closed after a new node got selected");
-      inspector.once("inspector-updated", endTests);
-    });
-    inspector.selection.setNode(contentDoc.querySelector(".one"));
-  });
+  ok(true, "Computed view tooltip closed after a new node got selected");
 }
--- a/browser/devtools/styleinspector/test/browser_bug970532_mathml_element.js
+++ b/browser/devtools/styleinspector/test/browser_bug970532_mathml_element.js
@@ -1,17 +1,16 @@
-/* Any copyright", " is dedicated to the Public Domain.
-http://creativecommons.org/publicdomain/zero/1.0/ */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the rule-view displays correctly on MathML elements
 
-waitForExplicitFinish();
-
 const TEST_URL = [
   "data:text/html,",
   "<div>",
   "  <math xmlns=\"http://www.w3.org/1998/Math/MathML\">",
   "    <mfrac>",
   "      <msubsup>",
   "        <mi>a</mi>",
   "        <mi>i</mi>",
@@ -21,50 +20,35 @@ const TEST_URL = [
   "        <mi>x</mi>",
   "        <mn>0</mn>",
   "      </msub>",
   "    </mfrac>",
   "  </math>",
   "</div>"
 ].join("");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
-    waitForFocus(runTests, content);
-  }, true);
-  content.location = TEST_URL;
-}
+let test = asyncTest(function*() {
+  yield addTab(TEST_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-function runTests() {
-  openRuleView((inspector, ruleView) => {
-    Task.spawn(function() {
-      info("Select the DIV node and verify the rule-view shows rules");
-      yield selectNode("div", inspector);
-      ok(ruleView.element.querySelectorAll(".ruleview-rule").length,
-        "The rule-view shows rules for the div element");
+  info("Select the DIV node and verify the rule-view shows rules");
+  yield selectNode("div", inspector);
+  ok(view.element.querySelectorAll(".ruleview-rule").length,
+    "The rule-view shows rules for the div element");
+
+  info("Select various MathML nodes and verify the rule-view is empty");
+  yield selectNode("math", inspector);
+  ok(!view.element.querySelectorAll(".ruleview-rule").length,
+    "The rule-view is empty for the math element");
 
-      info("Select various MathML nodes and verify the rule-view is empty");
-      yield selectNode("math", inspector);
-      ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
-        "The rule-view is empty for the math element");
-
-      yield selectNode("msubsup", inspector);
-      ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
-        "The rule-view is empty for the msubsup element");
-
-      yield selectNode("mn", inspector);
-      ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
-        "The rule-view is empty for the mn element");
+  yield selectNode("msubsup", inspector);
+  ok(!view.element.querySelectorAll(".ruleview-rule").length,
+    "The rule-view is empty for the msubsup element");
 
-      info("Select again the DIV node and verify the rule-view shows rules");
-      yield selectNode("div", inspector);
-      ok(ruleView.element.querySelectorAll(".ruleview-rule").length,
-        "The rule-view shows rules for the div element");
-    }).then(null, ok.bind(null, false)).then(finishUp);
-  });
-}
+  yield selectNode("mn", inspector);
+  ok(!view.element.querySelectorAll(".ruleview-rule").length,
+    "The rule-view is empty for the mn element");
 
-function finishUp() {
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  info("Select again the DIV node and verify the rule-view shows rules");
+  yield selectNode("div", inspector);
+  ok(view.element.querySelectorAll(".ruleview-rule").length,
+    "The rule-view shows rules for the div element");
+});
--- a/browser/devtools/styleinspector/test/browser_bug_592743_specificity.js
+++ b/browser/devtools/styleinspector/test/browser_bug_592743_specificity.js
@@ -1,99 +1,69 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 // Tests that CSS specificity is properly calculated.
 
 const DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
                    .getService(Ci.inIDOMUtils);
+const TEST_DATA = [
+  {text: "*", expected: 0},
+  {text: "LI", expected: 1},
+  {text: "UL LI", expected: 2},
+  {text: "UL OL + LI", expected: 3},
+  {text: "H1 + [REL=\"up\"]", expected: 257},
+  {text: "UL OL LI.red", expected: 259},
+  {text: "LI.red.level", expected: 513},
+  {text: ".red .level", expected: 512},
+  {text: "#x34y", expected: 65536},
+  {text: "#s12:not(FOO)", expected: 65537},
+  {text: "body#home div#warning p.message", expected: 131331},
+  {text: "* body#home div#warning p.message", expected: 131331},
+  {text: "#footer :not(nav) li", expected: 65538},
+  {text: "bar:nth-child(n)", expected: 257},
+  {text: "li::-moz-list-number", expected: 1},
+  {text: "a:hover", expected: 257}
+];
 
-function createDocument()
-{
-  let doc = content.document;
-  doc.body.innerHTML = getStylesheetText();
-  doc.title = "Computed view specificity test";
-  runTests(doc);
-}
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,Computed view specificity test");
+  createDocument();
 
-function runTests(doc) {
+  info("Creating a CssLogic instance");
   let cssLogic = new CssLogic();
-  cssLogic.highlight(doc.body);
-
-  let tests = getTests();
+  cssLogic.highlight(content.document.body);
   let cssSheet = cssLogic.sheets[0];
   let cssRule = cssSheet.domSheet.cssRules[0];
   let selectors = CssLogic.getSelectors(cssRule);
 
+  info("Iterating over the test selectors")
   for (let i = 0; i < selectors.length; i++) {
     let selectorText = selectors[i];
+    info("Testing selector " + selectorText);
+
     let selector = new CssSelector(cssRule, selectorText, i);
     let expected = getExpectedSpecificity(selectorText);
     let specificity = DOMUtils.getSpecificity(selector.cssRule,
                                               selector.selectorIndex)
     is(specificity, expected,
-      'selector "' + selectorText + '" has a specificity of ' + expected);
+      'Selector "' + selectorText + '" has a specificity of ' + expected);
   }
-  finishUp();
+});
+
+function createDocument() {
+  let doc = content.document;
+  doc.body.innerHTML = getStylesheetText();
+  doc.title = "Computed view specificity test";
+}
+
+function getStylesheetText() {
+  info("Creating the test stylesheet");
+  let text = TEST_DATA.map(i=>i.text).join(",");
+  return '<style type="text/css">' + text + " {color:red;}</style>";
 }
 
 function getExpectedSpecificity(selectorText) {
-  let tests = getTests();
-
-  for (let test of tests) {
-    if (test.text == selectorText) {
-      return test.expected;
-    }
-  }
-}
-
-function getTests() {
-  return [
-    {text: "*", expected: 0},
-    {text: "LI", expected: 1},
-    {text: "UL LI", expected: 2},
-    {text: "UL OL + LI", expected: 3},
-    {text: "H1 + [REL=\"up\"]", expected: 257},
-    {text: "UL OL LI.red", expected: 259},
-    {text: "LI.red.level", expected: 513},
-    {text: ".red .level", expected: 512},
-    {text: "#x34y", expected: 65536},
-    {text: "#s12:not(FOO)", expected: 65537},
-    {text: "body#home div#warning p.message", expected: 131331},
-    {text: "* body#home div#warning p.message", expected: 131331},
-    {text: "#footer :not(nav) li", expected: 65538},
-    {text: "bar:nth-child(n)", expected: 257},
-    {text: "li::-moz-list-number", expected: 1},
-    {text: "a:hover", expected: 257},
-  ];
+  return TEST_DATA.filter(i=>i.text === selectorText)[0].expected;
 }
-
-function getStylesheetText() {
-  let tests = getTests();
-  let text = "";
-
-  tests.forEach(function(test) {
-    if (text.length > 0) {
-      text += ",";
-    }
-    text += test.text;
-  });
-  return '<style type="text/css">' + text + " {color:red;}</style>";
-}
-
-function finishUp()
-{
-  CssLogic = CssSelector = tempScope = null;
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,Computed view specificity test";
-}
--- a/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js
+++ b/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js
@@ -1,77 +1,44 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests for selector text errors.
+"use strict";
 
-let doc;
-let computedView;
+// Tests for matched selector texts in the computed view
 
-function createDocument()
-{
-  doc.body.innerHTML = "<div style='color:blue;'></div>";
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,<div style='color:blue;'></div>");
 
-  doc.title = "Style Inspector Selector Text Test";
+  info("Opening the computed view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  openComputedView(startTests);
-}
-
+  info("Selecting the test node");
+  yield selectNode("div", inspector);
 
-function startTests(aInspector, aComputedView)
-{
-  computedView = aComputedView;
+  info("Checking the color property view");
+  let propertyView = getPropertyView(view, "color");
+  ok(propertyView, "found PropertyView for color");
+  is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true");
 
-  let div = doc.querySelector("div");
-  ok(div, "captain, we have the test div");
+  info("Expanding the matched selectors");
+  propertyView.matchedExpanded = true;
+  yield propertyView.refreshMatchedSelectors();
 
-  aInspector.selection.setNode(div);
-  aInspector.once("inspector-updated", SI_checkText);
-}
+  let span = propertyView.matchedSelectorsContainer.querySelector("span.rule-text");
+  ok(span, "Found the first table row");
 
-function SI_checkText()
-{
+  let selector = propertyView.matchedSelectorViews[0];
+  ok(selector, "Found the first matched selector view");
+});
+
+function getPropertyView(computedView, name) {
   let propertyView = null;
-  computedView.propertyViews.some(function(aView) {
-    if (aView.name == "color") {
-      propertyView = aView;
+  computedView.propertyViews.some(function(view) {
+    if (view.name == name) {
+      propertyView = view;
       return true;
     }
     return false;
   });
-
-  ok(propertyView, "found PropertyView for color");
-
-  is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true");
-
-  propertyView.matchedExpanded = true;
-  propertyView.refreshMatchedSelectors().then(() => {
-
-    let span = propertyView.matchedSelectorsContainer.querySelector("span.rule-text");
-    ok(span, "found the first table row");
-
-    let selector = propertyView.matchedSelectorViews[0];
-    ok(selector, "found the first matched selector view");
-
-    finishUp();
-  });
+  return propertyView;
 }
-
-function finishUp()
-{
-  doc = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,selector text test, bug 692400";
-}
--- a/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js
@@ -1,15 +1,15 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
-let inspector;
-let computedView;
+"use strict";
+
+// Test the links from the computed view to the style editor
 
 const STYLESHEET_URL = "data:text/css,"+encodeURIComponent(
   [".highlight {",
    "color: blue",
    "}"].join("\n"));
 
 const DOCUMENT_URL = "data:text/html,"+encodeURIComponent(
   ['<html>' +
@@ -35,133 +35,80 @@ const DOCUMENT_URL = "data:text/html,"+e
    'yet, write some test-cases for another bit of code. ',
    '<span style="font-style: italic">some text</span></p>',
    '<p id="closing">more text</p>',
    '<p>even more text</p>',
    '</div>',
    '</body>',
    '</html>'].join("\n"));
 
-
+let test = asyncTest(function*() {
+  yield addTab(DOCUMENT_URL);
 
-function selectNode(aInspector, aComputedView)
-{
-  inspector = aInspector;
-  computedView = aComputedView;
+  info("Opening the computed-view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  let span = doc.querySelector("span");
-  ok(span, "captain, we have the span");
+  info("Selecting the test node");
+  yield selectNode("span", inspector);
 
-  inspector.selection.setNode(span);
-  inspector.once("inspector-updated", testInlineStyle);
-}
+  yield testInlineStyle(view, inspector);
+  yield testInlineStyleSheet(view, toolbox);
+  yield testExternalStyleSheet(view, toolbox);
+});
 
-function testInlineStyle()
-{
-  expandProperty(0, function propertyExpanded() {
-    Services.ww.registerNotification(function onWindow(aSubject, aTopic) {
-      if (aTopic != "domwindowopened") {
-        return;
-      }
-      info("window opened");
-      let win = aSubject.QueryInterface(Ci.nsIDOMWindow);
-      win.addEventListener("load", function windowLoad() {
-        win.removeEventListener("load", windowLoad);
-        info("window load completed");
-        let windowType = win.document.documentElement.getAttribute("windowtype");
-        is(windowType, "navigator:view-source", "view source window is open");
-        info("closing window");
-        win.close();
-        Services.ww.unregisterNotification(onWindow);
-        executeSoon(() => {
-          testInlineStyleSheet();
-        });
-      });
-    });
-    let link = getLinkByIndex(0);
-    link.click();
-  });
-}
+function* testInlineStyle(view, inspector) {
+  info("Testing inline style");
+
+  yield expandComputedViewPropertyByIndex(view, inspector, 0);
 
-function testInlineStyleSheet()
-{
-  info("clicking an inline stylesheet");
-
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  let toolbox = gDevTools.getToolbox(target);
-  toolbox.once("styleeditor-selected", () => {
-    let panel = toolbox.getCurrentPanel();
+  let onWindow = waitForWindow();
+  info("Clicking on the first rule-link in the computed-view");
+  let link = getComputedViewLinkByIndex(view, 0);
+  link.click();
 
-    panel.UI.once("editor-selected", (event, editor) => {
-      validateStyleEditorSheet(editor, 0);
-      executeSoon(() => {
-        testExternalStyleSheet(toolbox);
-      });
-    });
-  });
+  let win = yield onWindow;
 
-  let link = getLinkByIndex(2);
-  link.click();
+  let windowType = win.document.documentElement.getAttribute("windowtype");
+  is(windowType, "navigator:view-source", "View source window is open");
+  info("Closing window");
+  win.close();
 }
 
-function testExternalStyleSheet(toolbox) {
-  info ("clicking an external stylesheet");
+function* testInlineStyleSheet(view, toolbox) {
+  info("Testing inline stylesheet");
 
-  let panel = toolbox.getCurrentPanel();
-  panel.UI.once("editor-selected", (event, editor) => {
-    is(toolbox.currentToolId, "styleeditor", "style editor selected");
-    validateStyleEditorSheet(editor, 1);
-    finishUp();
-  });
+  info("Listening for toolbox switch to the styleeditor");
+  let onSwitch = waitForStyleEditor(toolbox);
 
-  toolbox.selectTool("inspector").then(function () {
-    info("inspector selected");
-    let link = getLinkByIndex(1);
-    link.click();
-  });
-}
+  info("Clicking an inline stylesheet");
+  let link = getComputedViewLinkByIndex(view, 2);
+  link.click();
+  let editor = yield onSwitch;
 
-function validateStyleEditorSheet(aEditor, aExpectedSheetIndex)
-{
-  info("validating style editor stylesheet");
-  let sheet = doc.styleSheets[aExpectedSheetIndex];
-  is(aEditor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
+  ok(true, "Switched to the style-editor panel in the toolbox");
+
+  validateStyleEditorSheet(editor, 0);
 }
 
-function expandProperty(aIndex, aCallback)
-{
-  info("expanding property " + aIndex);
-  let contentDoc = computedView.styleDocument;
-  let expando = contentDoc.querySelectorAll(".expandable")[aIndex];
+function* testExternalStyleSheet(view, toolbox) {
+  info("Testing external stylesheet");
 
-  expando.click();
+  info("Waiting for the stylesheet editor to be selected");
+  let panel = toolbox.getCurrentPanel();
+  let onSelected = panel.UI.once("editor-selected");
 
-  inspector.once("computed-view-property-expanded", aCallback);
-}
+  info("Switching back to the inspector panel in the toolbox");
+  yield toolbox.selectTool("inspector");
 
-function getLinkByIndex(aIndex)
-{
-  let contentDoc = computedView.styleDocument;
-  let links = contentDoc.querySelectorAll(".rule-link .link");
-  return links[aIndex];
+  info("Clicking on an external stylesheet link");
+  let link =  getComputedViewLinkByIndex(view, 1);
+  link.click();
+  let editor = yield onSelected;
+
+  is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
+  validateStyleEditorSheet(editor, 1);
 }
 
-function finishUp()
-{
-  doc = inspector = computedView = null;
-  gBrowser.removeCurrentTab();
-  finish();
+function validateStyleEditorSheet(editor, expectedSheetIndex) {
+  info("Validating style editor stylesheet");
+  let sheet = content.document.styleSheets[expectedSheetIndex];
+  is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
 }
-
-function test()
-{
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(function () { openComputedView(selectNode); }, content);
-  }, true);
-
-  content.location = DOCUMENT_URL;
-}
--- a/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js
@@ -1,94 +1,62 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests that the style inspector works properly
-
-let doc, computedView, inspector;
+"use strict";
 
-function test()
-{
-  waitForExplicitFinish();
+// Tests the computed-view keyboard navigation
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,computed view keyboard nav test");
 
-  content.location = "data:text/html,computed view context menu test";
-}
-
-function createDocument()
-{
-  doc.body.innerHTML = '<style type="text/css"> ' +
+  content.document.body.innerHTML = '<style type="text/css"> ' +
     'span { font-variant: small-caps; color: #000000; } ' +
     '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
     'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
     '<h1>Some header text</h1>\n' +
     '<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
     '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
     'solely to provide some things to <span style="color: yellow">' +
     'highlight</span> and <span style="font-weight: bold">count</span> ' +
     'style list-items in the box at right. If you are reading this, ' +
     'you should go do something else instead. Maybe read a book. Or better ' +
     'yet, write some test-cases for another bit of code. ' +
     '<span style="font-style: italic">some text</span></p>\n' +
     '<p id="closing">more text</p>\n' +
     '<p>even more text</p>' +
     '</div>';
-  doc.title = "Computed view keyboard navigation test";
+  content.document.title = "Computed view keyboard navigation test";
 
-  openComputedView(startTests);
-}
+  info("Opening the computed-view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-function startTests(aInspector, aComputedView)
-{
-  computedView = aComputedView;
-  inspector = aInspector;
-  testTabThrougStyles();
-}
+  info("Selecting the test node");
+  yield selectNode("span", inspector);
 
-function endTests()
-{
-  computedView = inspector = doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function testTabThrougStyles()
-{
-  let span = doc.querySelector("span");
+  info("Selecting the first computed style in the list");
+  let firstStyle = view.styleDocument.querySelector(".property-view");
+  ok(firstStyle, "First computed style found in panel");
+  firstStyle.focus();
 
-  inspector.once("computed-view-refreshed", () => {
-    // Selecting the first computed style in the list
-    let firstStyle = computedView.styleDocument.querySelector(".property-view");
-    ok(firstStyle, "First computed style found in panel");
-    firstStyle.focus();
+  info("Tab to select the 2nd style and press return");
+  let onExpanded = inspector.once("computed-view-property-expanded");
+  EventUtils.synthesizeKey("VK_TAB", {});
+  EventUtils.synthesizeKey("VK_RETURN", {});
+  yield onExpanded;
 
-    // Tab to select the 2nd style, press return
-    EventUtils.synthesizeKey("VK_TAB", {});
-    EventUtils.synthesizeKey("VK_RETURN", {});
-    inspector.once("computed-view-property-expanded", () => {
-      // Verify the 2nd style has been expanded
-      let secondStyleSelectors = computedView.styleDocument.querySelectorAll(
-        ".property-content .matchedselectors")[1];
-      ok(secondStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
+  info("Verify the 2nd style has been expanded");
+  let secondStyleSelectors = view.styleDocument.querySelectorAll(
+    ".property-content .matchedselectors")[1];
+  ok(secondStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
 
-      // Tab back up and test the same thing, with space
-      EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
-      EventUtils.synthesizeKey("VK_SPACE", {});
-      inspector.once("computed-view-property-expanded", () => {
-        // Verify the 1st style has been expanded too
-        let firstStyleSelectors = computedView.styleDocument.querySelectorAll(
-          ".property-content .matchedselectors")[0];
-        ok(firstStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
+  info("Tab back up and test the same thing, with space");
+  let onExpanded = inspector.once("computed-view-property-expanded");
+  EventUtils.synthesizeKey("VK_TAB", {shiftKey: true});
+  EventUtils.synthesizeKey("VK_SPACE", {});
+  yield onExpanded;
 
-        endTests();
-      });
-    });
-  });
-
-  inspector.selection.setNode(span);
-}
+  info("Verify the 1st style has been expanded too");
+  let firstStyleSelectors = view.styleDocument.querySelectorAll(
+    ".property-content .matchedselectors")[0];
+  ok(firstStyleSelectors.childNodes.length > 0, "Matched selectors expanded");
+});
--- a/browser/devtools/styleinspector/test/browser_computedview_copy.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_copy.js
@@ -1,161 +1,118 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-// Tests that the style inspector works properly
+"use strict";
 
-let doc;
-let win;
-let computedView;
+// Tests that properties can be selected and copied from the computed view
 
 XPCOMUtils.defineLazyGetter(this, "osString", function() {
   return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
 });
 
-function createDocument()
-{
-  doc.body.innerHTML = '<style type="text/css"> ' +
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,computed view copy test");
+
+  info("Creating the test document");
+  content.document.body.innerHTML = '<style type="text/css"> ' +
     'span { font-variant: small-caps; color: #000000; } ' +
     '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
     'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
     '<h1>Some header text</h1>\n' +
     '<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
     '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
     'solely to provide some things to <span style="color: yellow">' +
     'highlight</span> and <span style="font-weight: bold">count</span> ' +
     'style list-items in the box at right. If you are reading this, ' +
     'you should go do something else instead. Maybe read a book. Or better ' +
     'yet, write some test-cases for another bit of code. ' +
     '<span style="font-style: italic">some text</span></p>\n' +
     '<p id="closing">more text</p>\n' +
     '<p>even more text</p>' +
     '</div>';
-  doc.title = "Computed view context menu test";
-
-  openComputedView(selectNode);
-}
+  content.document.title = "Computed view context menu test";
 
-function selectNode(aInspector, aComputedView)
-{
-  computedView = aComputedView;
-  win = aInspector.sidebar.getWindowForTab("computedview");
+  info("Opening the computed view");
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  let span = doc.querySelector("span");
-  ok(span, "captain, we have the span");
+  info("Selecting the test node");
+  yield selectNode("span", inspector);
 
-  aInspector.selection.setNode(span);
-  aInspector.once("inspector-updated", runStyleInspectorTests);
-}
-
+  yield checkCopySelection(view);
+  yield checkSelectAll(view);
+});
 
-function runStyleInspectorTests()
-{
-  let contentDocument = computedView.styleDocument;
-  let prop = contentDocument.querySelector(".property-view");
-  ok(prop, "captain, we have the property-view node");
+function checkCopySelection(view) {
+  info("Testing selection copy");
 
-  checkCopySelection();
-}
-
-function checkCopySelection()
-{
-  let contentDocument = computedView.styleDocument;
+  let contentDocument = view.styleDocument;
   let props = contentDocument.querySelectorAll(".property-view");
   ok(props, "captain, we have the property-view nodes");
 
-  let range = document.createRange();
+  let range = contentDocument.createRange();
   range.setStart(props[1], 0);
   range.setEnd(props[3], 3);
-  win.getSelection().addRange(range);
+  contentDocument.defaultView.getSelection().addRange(range);
 
-  info("Checking that cssHtmlTree.siBoundCopy() " +
-       " returns the correct clipboard value");
+  info("Checking that cssHtmlTree.siBoundCopy() returns the correct clipboard value");
 
   let expectedPattern = "font-family: helvetica,sans-serif;[\\r\\n]+" +
                         "font-size: 16px;[\\r\\n]+" +
                         "font-variant: small-caps;[\\r\\n]*";
 
-  SimpleTest.waitForClipboard(function CS_boundCopyCheck() {
-    return checkClipboardData(expectedPattern);
-  },
-  function() {
+  return waitForClipboard(() => {
     fireCopyEvent(props[0]);
-  },
-  checkSelectAll,
-  function() {
-    failedClipboard(expectedPattern, checkSelectAll);
+  }, () => {
+    return checkClipboardData(expectedPattern);
+  }).then(() => {}, () => {
+    failedClipboard(expectedPattern);
   });
 }
 
-function checkSelectAll()
-{
-  let contentDoc = computedView.styleDocument;
+function checkSelectAll(view) {
+  info("Testing select-all copy");
+
+  let contentDoc = view.styleDocument;
   let prop = contentDoc.querySelector(".property-view");
 
   info("Checking that _SelectAll() then copy returns the correct clipboard value");
-  computedView._onSelectAll();
+  view._onSelectAll();
   let expectedPattern = "color: #FF0;[\\r\\n]+" +
                         "font-family: helvetica,sans-serif;[\\r\\n]+" +
                         "font-size: 16px;[\\r\\n]+" +
                         "font-variant: small-caps;[\\r\\n]*";
 
-  SimpleTest.waitForClipboard(function() {
-    return checkClipboardData(expectedPattern);
-  },
-  function() {
+  return waitForClipboard(() => {
     fireCopyEvent(prop);
-  },
-  finishUp,
-  function() {
-    failedClipboard(expectedPattern, finishUp);
+  }, () => {
+    return checkClipboardData(expectedPattern);
+  }).then(() => {}, () => {
+    failedClipboard(expectedPattern);
   });
 }
 
-function checkClipboardData(aExpectedPattern)
-{
+function checkClipboardData(expectedPattern) {
   let actual = SpecialPowers.getClipboardData("text/unicode");
-  let expectedRegExp = new RegExp(aExpectedPattern, "g");
+  let expectedRegExp = new RegExp(expectedPattern, "g");
   return expectedRegExp.test(actual);
 }
 
-function failedClipboard(aExpectedPattern, aCallback)
-{
+function failedClipboard(expectedPattern) {
   // Format expected text for comparison
   let terminator = osString == "WINNT" ? "\r\n" : "\n";
-  aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
-  aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "(");
-  aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")");
+  expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
+  expectedPattern = expectedPattern.replace(/\\\(/g, "(");
+  expectedPattern = expectedPattern.replace(/\\\)/g, ")");
 
   let actual = SpecialPowers.getClipboardData("text/unicode");
 
   // Trim the right hand side of our strings. This is because expectedPattern
   // accounts for windows sometimes adding a newline to our copied data.
-  aExpectedPattern = aExpectedPattern.trimRight();
+  expectedPattern = expectedPattern.trimRight();
   actual = actual.trimRight();
 
   dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " +
     "results (escaped for accurate comparison):\n");
   info("Actual: " + escape(actual));
-  info("Expected: " + escape(aExpectedPattern));
-  aCallback();
-}
-
-function finishUp()
-{
-  computedView = doc = win = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  info("Expected: " + escape(expectedPattern));
 }
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,computed view context menu test";
-}
--- a/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js
+++ b/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js
@@ -1,137 +1,68 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let win;
-let doc;
-let inspector;
-let computedView;
-let toolbox;
+"use strict";
 
-const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps.html";
+// Test that the computed view shows the original source link when source maps
+// are enabled
+
+const TESTCASE_URI = TEST_URL_ROOT_SSL + "sourcemaps.html";
 const PREF = "devtools.styleeditor.source-maps-enabled";
-
 const SCSS_LOC = "sourcemaps.scss:4";
 const CSS_LOC = "sourcemaps.css:1";
 
-function test()
-{
-  waitForExplicitFinish();
-
+let test = asyncTest(function*() {
+  info("Turning the pref " + PREF + " on");
   Services.prefs.setBoolPref(PREF, true);
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(function () { openComputedView(highlightNode); }, content);
-  }, true);
+  yield addTab(TESTCASE_URI);
+  let {toolbox, inspector, view} = yield openComputedView();
 
-  content.location = TESTCASE_URI;
-}
-
-function highlightNode(aInspector, aComputedView)
-{
-  inspector = aInspector;
-  computedView = aComputedView;
+  info("Select the test node");
+  yield selectNode("div", inspector);
 
-  // Highlight a node.
-  let div = content.document.getElementsByTagName("div")[0];
-  ok(div, "div to select exists")
-
-  inspector.selection.setNode(div);
-  inspector.once("inspector-updated", () => {
-    is(inspector.selection.node, div, "selection matches the div element");
+  info("Expanding the first property");
+  yield expandComputedViewPropertyByIndex(view, inspector, 0);
 
-    expandProperty(0, testComputedViewLink);
-  });
-}
+  info("Verifying the link text");
+  yield verifyLinkText(view, SCSS_LOC);
 
-function testComputedViewLink() {
-  verifyLinkText(SCSS_LOC, testTogglePref);
-}
-
-function testTogglePref() {
+  info("Toggling the pref");
   Services.prefs.setBoolPref(PREF, false);
 
-  verifyLinkText(CSS_LOC, () => {
-    Services.prefs.setBoolPref(PREF, true);
+  info("Verifying that the link text has changed after the pref change");
+  yield verifyLinkText(view, CSS_LOC);
 
-    testClickingLink();
-  })
-}
+  info("Toggling the pref again");
+  Services.prefs.setBoolPref(PREF, true);
 
-function testClickingLink() {
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  let toolbox = gDevTools.getToolbox(target);
+  info("Testing that clicking on the link works");
+  yield testClickingLink(toolbox, view);
 
-  toolbox.once("styleeditor-ready", function(id, aToolbox) {
-    let panel = toolbox.getCurrentPanel();
-    panel.UI.on("editor-selected", (event, editor) => {
-      // The style editor selects the first sheet at first load before
-      // selecting the desired sheet.
-      if (editor.styleSheet.href.endsWith("scss")) {
-        info("original source editor selected");
-        editor.getSourceEditor().then(editorSelected);
-      }
-    });
-  });
+  info("Turning the pref " + PREF + " off");
+  Services.prefs.clearUserPref(PREF);
+});
 
-  let link = getLinkByIndex(0);
+function* testClickingLink(toolbox, view) {
+  let onEditor = waitForStyleEditor(toolbox, "sourcemaps.scss");
 
-  info("clicking rule view link");
+  info("Clicking the computedview stylesheet link");
+  let link = getComputedViewLinkByIndex(view, 0);
   link.scrollIntoView();
   link.click();
-}
 
-function editorSelected(editor) {
-  let href = editor.styleSheet.href;
-  ok(href.endsWith("sourcemaps.scss"), "selected stylesheet is correct one");
+  let editor = yield onEditor;
 
   let {line, col} = editor.sourceEditor.getCursor();
   is(line, 3, "cursor is at correct line number in original source");
-
-  finishUp();
-}
-
-/* Helpers */
-function expandProperty(aIndex, aCallback)
-{
-  info("expanding property " + aIndex);
-  let contentDoc = computedView.styleDocument;
-  let expando = contentDoc.querySelectorAll(".expandable")[aIndex];
-
-  expando.click();
-
-  inspector.once("computed-view-property-expanded", aCallback);
 }
 
-function getLinkByIndex(aIndex)
-{
-  let contentDoc = computedView.styleDocument;
-  let links = contentDoc.querySelectorAll(".rule-link .link");
-  return links[aIndex];
-}
-
-function verifyLinkText(text, callback) {
-  let link = getLinkByIndex(0);
+function verifyLinkText(view, text) {
+  let link = getComputedViewLinkByIndex(view, 0);
 
-  waitForSuccess({
-    name: "link text changed to display correct location: " + text,
-    validatorFn: function()
-    {
-      return link.textContent == text;
-    },
-    successFn: callback,
-    failureFn: callback,
-  });
+  return waitForSuccess(
+    () => link.textContent == text,
+    "link text changed to display correct location: " + text
+  );
 }
-
-function finishUp()
-{
-  gBrowser.removeCurrentTab();
-  doc = inspector = computedView = toolbox = win = null;
-  Services.prefs.clearUserPref(PREF);
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_csslogic_inherited.js
+++ b/browser/devtools/styleinspector/test/browser_csslogic_inherited.js
@@ -1,44 +1,23 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
 // Test that inherited properties are treated correctly.
 
-let doc;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,selector text test, bug 692400");
 
-function createDocument()
-{
-  doc.body.innerHTML = '<div style="margin-left:10px; font-size: 5px"><div id="innerdiv">Inner div</div></div>';
-  doc.title = "Style Inspector Inheritance Test";
+  content.document.body.innerHTML = '<div style="margin-left:10px; font-size: 5px"><div id="innerdiv">Inner div</div></div>';
+  content.document.title = "Style Inspector Inheritance Test";
 
   let cssLogic = new CssLogic();
-  cssLogic.highlight(doc.getElementById("innerdiv"));
+  cssLogic.highlight(content.document.getElementById("innerdiv"));
 
   let marginProp = cssLogic.getPropertyInfo("margin-left");
   is(marginProp.matchedRuleCount, 0, "margin-left should not be included in matched selectors.");
 
   let fontSizeProp = cssLogic.getPropertyInfo("font-size");
   is(fontSizeProp.matchedRuleCount, 1, "font-size should be included in matched selectors.");
-
-  finishUp();
-}
-
-function finishUp()
-{
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,selector text test, bug 692400";
-}
+});
--- a/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js
@@ -1,29 +1,23 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let win;
-let doc;
-let contentWindow;
-let inspector;
-let toolbox;
+"use strict";
 
-let tempScope = {};
-Cu.import("resource://gre/modules/Services.jsm", tempScope);
-let Services = tempScope.Services;
+// Test the links from the rule-view to the styleeditor
 
 const STYLESHEET_URL = "data:text/css,"+encodeURIComponent(
   ["#first {",
    "color: blue",
    "}"].join("\n"));
 
 const EXTERNAL_STYLESHEET_FILE_NAME = "browser_ruleview_734259_style_editor_link.css"
-const EXTERNAL_STYLESHEET_URL = TEST_BASE_HTTP + EXTERNAL_STYLESHEET_FILE_NAME;
+const EXTERNAL_STYLESHEET_URL = TEST_URL_ROOT + EXTERNAL_STYLESHEET_FILE_NAME;
 
 const DOCUMENT_URL = "data:text/html,"+encodeURIComponent(
   ['<html>' +
    '<head>' +
    '<title>Rule view style editor link test</title>',
    '<style type="text/css"> ',
    'html { color: #000000; } ',
    'div { font-variant: small-caps; color: #000000; } ',
@@ -45,145 +39,92 @@ const DOCUMENT_URL = "data:text/html,"+e
    'yet, write some test-cases for another bit of code. ',
    '<span style="font-style: italic">some text</span></p>',
    '<p id="closing">more text</p>',
    '<p>even more text</p>',
    '</div>',
    '</body>',
    '</html>'].join("\n"));
 
-function openToolbox() {
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
+let test = asyncTest(function*() {
+  yield addTab(DOCUMENT_URL);
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  gDevTools.showToolbox(target, "inspector").then(function(aToolbox) {
-    toolbox = aToolbox;
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
-    highlightNode();
-  });
-}
+  info("Select the test node");
+  yield selectNode("div", inspector);
+
+  yield testInlineStyle(view, inspector);
+  yield testInlineStyleSheet(view, toolbox);
+  yield testExternalStyleSheet(view, toolbox);
+});
 
-function highlightNode()
-{
-  // Highlight a node.
-  let div = content.document.getElementsByTagName("div")[0];
+function* testInlineStyle(view, inspector) {
+  info("Testing inline style");
 
-  inspector.selection.setNode(div);
-  inspector.once("inspector-updated", () => {
-    is(inspector.selection.node, div, "selection matches the div element");
-    testInlineStyle();
-  });
+  let onWindow = waitForWindow();
+  info("Clicking on the first link in the rule-view");
+  let link = getRuleViewLinkByIndex(view, 0);
+  link.scrollIntoView();
+  link.click();
+
+  let win = yield onWindow;
+
+  let windowType = win.document.documentElement.getAttribute("windowtype");
+  is(windowType, "navigator:view-source", "View source window is open");
+  info("Closing window");
+  win.close();
 }
 
-function testInlineStyle()
-{
-  info("clicking an inline style");
-
-  Services.ww.registerNotification(function onWindow(aSubject, aTopic) {
-    if (aTopic != "domwindowopened") {
-      return;
-    }
+function* testInlineStyleSheet(view, toolbox) {
+  info("Testing inline stylesheet");
 
-    win = aSubject.QueryInterface(Ci.nsIDOMWindow);
-    win.addEventListener("load", function windowLoad() {
-      win.removeEventListener("load", windowLoad);
-      let windowType = win.document.documentElement.getAttribute("windowtype");
-      is(windowType, "navigator:view-source", "view source window is open");
-      win.close();
-      Services.ww.unregisterNotification(onWindow);
-      executeSoon(() => {
-        testInlineStyleSheet();
-      });
-    });
-  });
+  info("Listening for toolbox switch to the styleeditor");
+  let onSwitch = waitForStyleEditor(toolbox);
 
-  let link = getLinkByIndex(0);
+  info("Clicking an inline stylesheet");
+  let link = getRuleViewLinkByIndex(view, 4);
   link.scrollIntoView();
   link.click();
+  let editor = yield onSwitch;
+
+  ok(true, "Switched to the style-editor panel in the toolbox");
+
+  validateStyleEditorSheet(editor, 0);
 }
 
-function testInlineStyleSheet()
-{
-  info("clicking an inline stylesheet");
+function* testExternalStyleSheet(view, toolbox) {
+  info("Testing external stylesheet");
 
-  toolbox.once("styleeditor-ready", function(id, aToolbox) {
-    let panel = toolbox.getCurrentPanel();
+  info("Waiting for the stylesheet editor to be selected");
+  let panel = toolbox.getCurrentPanel();
+  let onSelected = panel.UI.once("editor-selected");
 
-    panel.UI.once("editor-selected", (event, editor) => {
-      validateStyleEditorSheet(editor, 0);
-      executeSoon(() => {
-        testExternalStyleSheet(toolbox);
-      });
-    });
-  });
+  info("Switching back to the inspector panel in the toolbox");
+  yield toolbox.selectTool("inspector");
 
-  let link = getLinkByIndex(4);
+  info("Clicking on an external stylesheet link");
+  testRuleViewLinkLabel(view);
+  let link =  getRuleViewLinkByIndex(view, 1);
   link.scrollIntoView();
   link.click();
+  let editor = yield onSelected;
+
+  is(toolbox.currentToolId, "styleeditor", "The style editor is selected again");
+  validateStyleEditorSheet(editor, 1);
 }
 
-function testExternalStyleSheet(toolbox) {
-  info ("clicking an external stylesheet");
-
-  let panel = toolbox.getCurrentPanel();
-  panel.UI.once("editor-selected", (event, editor) => {
-    is(toolbox.currentToolId, "styleeditor", "style editor tool selected");
-    validateStyleEditorSheet(editor, 1);
-    finishUp();
-  });
-
-  toolbox.selectTool("inspector").then(function () {
-    testRuleViewLinkLabel();
-    let link = getLinkByIndex(1);
-    link.scrollIntoView();
-    link.click();
-  });
+function validateStyleEditorSheet(editor, expectedSheetIndex) {
+  info("validating style editor stylesheet");
+  let sheet = content.document.styleSheets[expectedSheetIndex];
+  is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
 }
 
-function testRuleViewLinkLabel()
-{
-  let link = getLinkByIndex(2);
+function testRuleViewLinkLabel(view) {
+  let link = getRuleViewLinkByIndex(view, 2);
   let labelElem = link.querySelector(".source-link-label");
   let value = labelElem.getAttribute("value");
   let tooltipText = labelElem.getAttribute("tooltiptext");
 
   is(value, EXTERNAL_STYLESHEET_FILE_NAME + ":1",
     "rule view stylesheet display value matches filename and line number");
   is(tooltipText, EXTERNAL_STYLESHEET_URL,
     "rule view stylesheet tooltip text matches the full URI path");
 }
-
-function validateStyleEditorSheet(aEditor, aExpectedSheetIndex)
-{
-  info("validating style editor stylesheet");
-  let sheet = doc.styleSheets[aExpectedSheetIndex];
-  is(aEditor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet");
-}
-
-function getLinkByIndex(aIndex)
-{
-  let contentDoc = ruleView().doc;
-  contentWindow = contentDoc.defaultView;
-  let links = contentDoc.querySelectorAll(".ruleview-rule-source");
-  return links[aIndex];
-}
-
-function finishUp()
-{
-  gBrowser.removeCurrentTab();
-  contentWindow = doc = inspector = toolbox = win = null;
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(openToolbox, content);
-  }, true);
-
-  content.location = DOCUMENT_URL;
-}
new file mode 100644
--- /dev/null
+++ b/browser/devtools/styleinspector/test/browser_ruleview_add_property_01.js
@@ -0,0 +1,48 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests that adding properties to rules work and reselecting the element still
+// show them
+
+const TEST_URI = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.html";
+
+let test = asyncTest(function*() {
+  yield addTab(TEST_URI);
+
+  let target = getNode("#target");
+
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield selectNode(target, inspector);
+
+  info("Setting a font-weight property on all rules");
+  setPropertyOnAllRules(view);
+
+  info("Reselecting the element");
+  yield reselectElement(target, inspector);
+
+  checkPropertyOnAllRules(view);
+});
+
+function reselectElement(node, inspector) {
+  return selectNode(node.parentNode, inspector).then(() => {
+    return selectNode(node, inspector);
+  });
+}
+
+function setPropertyOnAllRules(view) {
+  for (let rule of view._elementStyle.rules) {
+    rule.editor.addProperty("font-weight", "bold", "");
+  }
+}
+
+function checkPropertyOnAllRules(view) {
+  for (let rule of view._elementStyle.rules) {
+    let lastRule = rule.textProps[rule.textProps.length - 1];
+
+    is(lastRule.name, "font-weight", "Last rule name is font-weight");
+    is(lastRule.value, "bold", "Last rule value is bold");
+  }
+}
--- a/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js
@@ -1,103 +1,84 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
 // Test original value is correctly displayed when ESCaping out of the
 // inplace editor in the style inspector.
 
-let doc;
-let ruleWindow;
-let ruleView;
-let inspector;
-let originalValue = "#00F";
+const originalValue = "#00F";
 
 // Test data format
 // {
 //  value: what char sequence to type,
 //  commitKey: what key to type to "commit" the change,
 //  modifiers: commitKey modifiers,
 //  expected: what value is expected as a result
 // }
-let testData = [
+const testData = [
   {value: "red", commitKey: "VK_ESCAPE", modifiers: {}, expected: originalValue},
   {value: "red", commitKey: "VK_RETURN", modifiers: {}, expected: "#F00"},
   {value: "invalid", commitKey: "VK_RETURN", modifiers: {}, expected: "invalid"},
   {value: "blue", commitKey: "VK_TAB", modifiers: {shiftKey: true}, expected: "blue"}
 ];
 
-function startTests()
-{
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,test escaping property change reverts back to original value");
+
+  info("Creating the test document");
+  createDocument();
+
+  info("Opening the rule view");
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  info("Selecting the test node");
+  yield selectNode("#testid", inspector);
+
+  info("Iterating over the test data");
+  for (let data of testData) {
+    yield runTestData(view, data);
+  }
+});
+
+function createDocument() {
   let style = '' +
     '#testid {' +
     '  color: ' + originalValue + ';' +
     '}';
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid">Styled Node</div>';
-  let testElement = doc.getElementById("testid");
+  let node = content.document.createElement('style');
+  node.setAttribute("type", "text/css");
+  node.textContent = style;
+  content.document.getElementsByTagName("head")[0].appendChild(node);
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    ruleWindow = aRuleView.doc.defaultView;
-    inspector.selection.setNode(testElement);
-    inspector.once("inspector-updated", () => runTestData(0));
-  });
+  content.document.body.innerHTML = '<div id="testid">Styled Node</div>';
 }
 
-function runTestData(index)
-{
-  if (index === testData.length) {
-    finishTest();
-    return;
+function* runTestData(view, {value, commitKey, modifiers, expected}) {
+  let idRuleEditor = view.element.children[1]._ruleEditor;
+  let propEditor = idRuleEditor.rule.textProps[0].editor;
+
+  info("Focusing the inplace editor field");
+  let editor = yield focusEditableField(propEditor.valueSpan);
+  is(inplaceEditor(propEditor.valueSpan), editor, "Focused editor should be the value span.");
+
+  info("Entering test data " + value)
+  for (let ch of value) {
+    EventUtils.sendChar(ch, view.doc.defaultView);
   }
 
-  let idRuleEditor = ruleView.element.children[1]._ruleEditor;
-  let propEditor = idRuleEditor.rule.textProps[0].editor;
-  waitForEditorFocus(propEditor.element, function(aEditor) {
-    is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value span.");
+  info("Waiting for focus on the field");
+  let onBlur = once(editor.input, "blur");
 
-    for (let ch of testData[index].value) {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
+  info("Entering the commit key " + commitKey + " " + modifiers);
+  EventUtils.synthesizeKey(commitKey, modifiers);
+  yield onBlur;
 
-    // Need to wait for the change to be finished before the next test starts
-    // if not cancelling the change (the previous modification can change which
-    // color format is shown).
-    if (testData[index].commitKey === "VK_ESCAPE") {
-      EventUtils.synthesizeKey(testData[index].commitKey, testData[index].modifiers);
-      is(propEditor.valueSpan.textContent, testData[index].expected, "Value is same as expected: " + testData[index].expected);
-      runTestData(index + 1);
-    } else {
-      ruleView.element.addEventListener("CssRuleViewChanged", function nextTest() {
-        ruleView.element.removeEventListener("CssRuleViewChanged", nextTest);
-        is(propEditor.valueSpan.textContent, testData[index].expected, "Value is same as expected: " + testData[index].expected);
-        runTestData(index + 1);
-      });
-      EventUtils.synthesizeKey(testData[index].commitKey, testData[index].modifiers);
-    }
-  });
-
-  EventUtils.synthesizeMouse(propEditor.valueSpan, 1, 1, {}, ruleWindow);
+  if (commitKey === "VK_ESCAPE") {
+    is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected);
+  } else {
+    yield once(view.element, "CssRuleViewChanged");
+    is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected);
+  }
 }
-
-function finishTest()
-{
-  inspector = ruleWindow = ruleView = null;
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function escapePropertyChange_load(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, escapePropertyChange_load, true);
-    doc = content.document;
-    waitForFocus(startTests, content);
-  }, true);
-
-  content.location = "data:text/html,test escaping property change reverts back to original value";
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js
@@ -12,63 +12,49 @@ const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    background: url("chrome://global/skin/icons/warning-64.png"), linear-gradient(white, #F06 400px);',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
+  content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-function createDocument() {
-  content.document.body.innerHTML = PAGE_CONTENT;
+  let value = getRuleViewProperty(view, "body", "background").valueSpan;
+  let swatch = value.querySelector(".ruleview-colorswatch");
+  let url = value.querySelector(".theme-link");
+  yield testImageTooltipAfterColorChange(swatch, url, view);
+});
 
-  openRuleView((inspector, ruleView) => {
-    inspector.once("inspector-updated", () => {
-      let value = getRuleViewProperty("background", ruleView).valueSpan;
-      let swatch = value.querySelector(".ruleview-colorswatch");
-      let url = value.querySelector(".theme-link");
-      testImageTooltipAfterColorChange(swatch, url, ruleView);
-    });
-  });
-}
+function* testImageTooltipAfterColorChange(swatch, url, ruleView) {
+  info("First, verify that the image preview tooltip works");
+  let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
+  ok(anchor, "The image preview tooltip is shown on the url span");
+  is(anchor, url, "The anchor returned by the showOnHover callback is correct");
 
-function testImageTooltipAfterColorChange(swatch, url, ruleView) {
-  Task.spawn(function*() {
-    info("First, verify that the image preview tooltip works");
-    let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
-    ok(anchor, "The image preview tooltip is shown on the url span");
-    is(anchor, url, "The anchor returned by the showOnHover callback is correct");
+  info("Open the color picker tooltip and change the color");
+  let picker = ruleView.colorPicker;
+  let onShown = picker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+  yield simulateColorPickerChange(picker, [0, 0, 0, 1], {
+    element: content.document.body,
+    name: "backgroundImage",
+    value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'
+  });
 
-    info("Open the color picker tooltip and change the color");
-    let picker = ruleView.colorPicker;
-    let onShown = picker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
-    yield simulateColorChange(picker, [0, 0, 0, 1], {
-      element: content.document.body,
-      name: "backgroundImage",
-      value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)'
-    });
+  let spectrum = yield picker.spectrum;
+  let onHidden = picker.tooltip.once("hidden");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
+  yield onHidden;
 
-    let spectrum = yield picker.spectrum;
-    let onHidden = picker.tooltip.once("hidden");
-    EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
-    yield onHidden;
-
-    info("Verify again that the image preview tooltip works");
-    // After a color change, the property is re-populated, we need to get the new
-    // dom node
-    url = getRuleViewProperty("background", ruleView).valueSpan.querySelector(".theme-link");
-    let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
-    ok(anchor, "The image preview tooltip is shown on the url span");
-    is(anchor, url, "The anchor returned by the showOnHover callback is correct");
-  }).then(finish);
+  info("Verify again that the image preview tooltip works");
+  // After a color change, the property is re-populated, we need to get the new
+  // dom node
+  url = getRuleViewProperty(ruleView, "body", "background").valueSpan.querySelector(".theme-link");
+  let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
+  ok(anchor, "The image preview tooltip is shown on the url span");
+  is(anchor, url, "The anchor returned by the showOnHover callback is correct");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js
@@ -14,63 +14,48 @@ const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    background: red url("chrome://global/skin/icons/warning-64.png") no-repeat center center;',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
   content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield testColorChangeIsntRevertedWhenOtherTooltipIsShown(view);
+});
 
-  openRuleView((inspector, ruleView) => {
-    inspector.once("inspector-updated", () => {
-      testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView);
-    });
-  });
-}
+function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
+  let swatch = getRuleViewProperty(ruleView, "body", "background").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-function testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
-  Task.spawn(function*() {
-    let swatch = getRuleViewProperty("background", ruleView).valueSpan
-      .querySelector(".ruleview-colorswatch");
+  info("Open the color picker tooltip and change the color");
+  let picker = ruleView.colorPicker;
+  let onShown = picker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    info("Open the color picker tooltip and change the color");
-    let picker = ruleView.colorPicker;
-    let onShown = picker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  yield simulateColorPickerChange(picker, [0, 0, 0, 1], {
+    element: content.document.body,
+    name: "backgroundColor",
+    value: "rgb(0, 0, 0)"
+  });
+  let spectrum = yield picker.spectrum;
+  let onHidden = picker.tooltip.once("hidden");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
+  yield onHidden;
 
-    yield simulateColorChange(picker, [0, 0, 0, 1], {
-      element: content.document.body,
-      name: "backgroundColor",
-      value: "rgb(0, 0, 0)"
-    });
-    let spectrum = yield picker.spectrum;
-    let onHidden = picker.tooltip.once("hidden");
-    EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
-    yield onHidden;
+  info("Open the image preview tooltip");
+  let value = getRuleViewProperty(ruleView, "body", "background").valueSpan;
+  let url = value.querySelector(".theme-link");
+  let onShown = ruleView.previewTooltip.once("shown");
+  let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
+  ruleView.previewTooltip.show(anchor);
+  yield onShown;
 
-    info("Open the image preview tooltip");
-    let value = getRuleViewProperty("background", ruleView).valueSpan;
-    let url = value.querySelector(".theme-link");
-    let onShown = ruleView.previewTooltip.once("shown");
-    let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url);
-    ruleView.previewTooltip.show(anchor);
-    yield onShown;
-
-    info("Image tooltip is shown, verify that the swatch is still correct");
-    let swatch = value.querySelector(".ruleview-colorswatch");
-    is(swatch.style.backgroundColor, "rgb(0, 0, 0)", "The swatch's color is correct");
-    is(swatch.nextSibling.textContent, "#000", "The color name is correct");
-  }).then(finish);
+  info("Image tooltip is shown, verify that the swatch is still correct");
+  let swatch = value.querySelector(".ruleview-colorswatch");
+  is(swatch.style.backgroundColor, "rgb(0, 0, 0)", "The swatch's color is correct");
+  is(swatch.nextSibling.textContent, "#000", "The color name is correct");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js
@@ -1,77 +1,54 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that color pickers appear when clicking on color swatches
 
-let ruleView, swatches;
-
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    color: red;',
   '    background-color: #ededed;',
   '    background-image: url(chrome://global/skin/icons/warning-64.png);',
   '    border: 2em solid rgba(120, 120, 120, .5);',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
   content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  openRuleView((inspector, view) => {
-    ruleView = view;
-    inspector.once("inspector-updated", () => {
-      let cSwatch = getRuleViewProperty("color", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      let bSwatch = getRuleViewProperty("border", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      swatches = [cSwatch, bgSwatch, bSwatch];
+  let cSwatch = getRuleViewProperty(view, "body", "color").valueSpan
+    .querySelector(".ruleview-colorswatch");
+  let bgSwatch = getRuleViewProperty(view, "body", "background-color").valueSpan
+    .querySelector(".ruleview-colorswatch");
+  let bSwatch = getRuleViewProperty(view, "body", "border").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-      testColorPickerAppearsOnColorSwatchClick();
-    });
-  });
-}
+  for (let swatch of [cSwatch, bgSwatch, bSwatch]) {
+    info("Testing that the colorpicker appears colorswatch click");
+    yield testColorPickerAppearsOnColorSwatchClick(view, swatch);
+  }
+});
 
-function testColorPickerAppearsOnColorSwatchClick() {
-  let cPicker = ruleView.colorPicker;
+function* testColorPickerAppearsOnColorSwatchClick(view, swatch) {
+  let cPicker = view.colorPicker;
+  ok(cPicker, "The rule-view has the expected colorPicker property");
+
   let cPickerPanel = cPicker.tooltip.panel;
   ok(cPickerPanel, "The XUL panel for the color picker exists");
 
-  function clickOnSwatch(index, cb) {
-    if (index === swatches.length) {
-      return cb();
-    }
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    let swatch = swatches[index];
-    cPicker.tooltip.once("shown", () => {
-      ok(true, "The color picker was shown on click of the color swatch");
-      ok(!inplaceEditor(swatch.parentNode),
-        "The inplace editor wasn't shown as a result of the color swatch click");
-      cPicker.hide();
-      clickOnSwatch(index + 1, cb);
-    });
-    swatch.click();
-  }
-
-  clickOnSwatch(0, () => {
-    ruleView = swatches = null;
-    finish();
-  });
+  ok(true, "The color picker was shown on click of the color swatch");
+  ok(!inplaceEditor(swatch.parentNode),
+    "The inplace editor wasn't shown as a result of the color swatch click");
+  cPicker.hide();
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-commit-on-ENTER.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-commit-on-ENTER.js
@@ -10,64 +10,50 @@ const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    border: 2em solid rgba(120, 120, 120, .5);',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
   content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  openRuleView((inspector, ruleView) => {
-    inspector.once("inspector-updated", () => {
-      let swatch = getRuleViewProperty("border", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      testPressingEnterCommitsChanges(swatch, ruleView);
-    });
-  });
-}
+  let swatch = getRuleViewProperty(view, "body" , "border").valueSpan
+    .querySelector(".ruleview-colorswatch");
+  yield testPressingEnterCommitsChanges(swatch, view);
+});
 
-function testPressingEnterCommitsChanges(swatch, ruleView) {
-  Task.spawn(function*() {
-    let cPicker = ruleView.colorPicker;
+function* testPressingEnterCommitsChanges(swatch, ruleView) {
+  let cPicker = ruleView.colorPicker;
+
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    let onShown = cPicker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  yield simulateColorPickerChange(cPicker, [0, 255, 0, .5], {
+    element: content.document.body,
+    name: "borderLeftColor",
+    value: "rgba(0, 255, 0, 0.5)"
+  });
 
-    yield simulateColorChange(cPicker, [0, 255, 0, .5], {
-      element: content.document.body,
-      name: "borderLeftColor",
-      value: "rgba(0, 255, 0, 0.5)"
-    });
+  is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
+    "The color swatch's background was updated");
+  is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
+    "2em solid rgba(0, 255, 0, 0.5)",
+    "The text of the border css property was updated");;
 
-    is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
-      "The color swatch's background was updated");
-    is(getRuleViewProperty("border", ruleView).valueSpan.textContent,
-      "2em solid rgba(0, 255, 0, 0.5)",
-      "The text of the border css property was updated");;
+  let spectrum = yield cPicker.spectrum;
+  let onHidden = cPicker.tooltip.once("hidden");
+  EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
+  yield onHidden;
 
-    let spectrum = yield cPicker.spectrum;
-    let onHidden = cPicker.tooltip.once("hidden");
-    EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
-    yield onHidden;
-
-    is(content.getComputedStyle(content.document.body).borderLeftColor,
-      "rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
-    is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
-      "The color swatch's background was kept after RETURN");
-    is(getRuleViewProperty("border", ruleView).valueSpan.textContent,
-      "2em solid rgba(0, 255, 0, 0.5)",
-      "The text of the border css property was kept after RETURN");
-  }).then(finish);
+  is(content.getComputedStyle(content.document.body).borderLeftColor,
+    "rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
+  is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
+    "The color swatch's background was kept after RETURN");
+  is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
+    "2em solid rgba(0, 255, 0, 0.5)",
+    "The text of the border css property was kept after RETURN");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-hides-on-tooltip.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-hides-on-tooltip.js
@@ -2,95 +2,67 @@
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that the color picker tooltip hides when an image or transform
 // tooltip appears
 
-let ruleView, swatches;
-
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    color: red;',
   '    background-color: #ededed;',
   '    background-image: url(chrome://global/skin/icons/warning-64.png);',
   '    border: 2em solid rgba(120, 120, 120, .5);',
   '    transform: skew(-16deg);',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
+  content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
+  let swatch = getRuleViewProperty(view, "body", "color").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-function createDocument() {
-  content.document.body.innerHTML = PAGE_CONTENT;
+  yield testColorPickerHidesWhenImageTooltipAppears(view, swatch);
+  yield testColorPickerHidesWhenTransformTooltipAppears(view, swatch);
+});
 
-  openRuleView((inspector, view) => {
-    ruleView = view;
-    inspector.once("inspector-updated", () => {
-      let cSwatch = getRuleViewProperty("color", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      let bSwatch = getRuleViewProperty("border", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      swatches = [cSwatch, bgSwatch, bSwatch];
+function* testColorPickerHidesWhenImageTooltipAppears(view, swatch) {
+  let bgImageSpan = getRuleViewProperty(view, "body", "background-image").valueSpan;
+  let uriSpan = bgImageSpan.querySelector(".theme-link");
+  let tooltip = view.colorPicker.tooltip;
 
-      testColorPickerHidesWhenImageTooltipAppears();
-    });
-  });
+  info("Showing the color picker tooltip by clicking on the color swatch");
+  let onShown = tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  info("Now showing the image preview tooltip to hide the color picker");
+  let onHidden = tooltip.once("hidden");
+  yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
+  yield onHidden;
+
+  ok(true, "The color picker closed when the image preview tooltip appeared");
 }
 
-function testColorPickerHidesWhenImageTooltipAppears() {
-  Task.spawn(function*() {
-    let swatch = swatches[0];
-    let bgImageSpan = getRuleViewProperty("background-image", ruleView).valueSpan;
-    let uriSpan = bgImageSpan.querySelector(".theme-link");
-    let tooltip = ruleView.colorPicker.tooltip;
-
-    info("Showing the color picker tooltip by clicking on the color swatch");
-    let onShown = tooltip.once("shown");
-    swatch.click();
-    yield onShown;
-
-    info("Now showing the image preview tooltip to hide the color picker");
-    let onHidden = tooltip.once("hidden");
-    yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
-    yield onHidden;
-
-    ok(true, "The color picker closed when the image preview tooltip appeared");
-  }).then(testColorPickerHidesWhenTransformTooltipAppears);
-}
+function* testColorPickerHidesWhenTransformTooltipAppears(view, swatch) {
+  let transformSpan = getRuleViewProperty(view, "body", "transform").valueSpan;
+  let tooltip = view.colorPicker.tooltip;
 
-function testColorPickerHidesWhenTransformTooltipAppears() {
-  Task.spawn(function*() {
-    let swatch = swatches[0];
-    let transformSpan = getRuleViewProperty("transform", ruleView).valueSpan;
-    let tooltip = ruleView.colorPicker.tooltip;
-
-    info("Showing the color picker tooltip by clicking on the color swatch");
-    let onShown = tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  info("Showing the color picker tooltip by clicking on the color swatch");
+  let onShown = tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    info("Now showing the transform preview tooltip to hide the color picker");
-    let onHidden = tooltip.once("hidden");
-    yield assertTooltipShownOn(ruleView.previewTooltip, transformSpan);
-    yield onHidden;
+  info("Now showing the transform preview tooltip to hide the color picker");
+  let onHidden = tooltip.once("hidden");
+  yield assertHoverTooltipOn(view.previewTooltip, transformSpan);
+  yield onHidden;
 
-    ok(true, "The color picker closed when the transform preview tooltip appeared");
-  }).then(() => {
-    swatches = ruleView = null;
-    finish();
-  });
+  ok(true, "The color picker closed when the transform preview tooltip appeared");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-multiple-changes.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-multiple-changes.js
@@ -19,128 +19,108 @@ const PAGE_CONTENT = [
   '  }',
   '  p {',
   '    color: blue;',
   '  }',
   '</style>',
   '<p>Testing the color picker tooltip!</p>'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
   content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  openRuleView((inspector, ruleView) => {
-    inspector.once("inspector-updated", () => {
-      testSimpleMultipleColorChanges(inspector, ruleView);
-    });
-  });
-}
+  yield testSimpleMultipleColorChanges(inspector, view);
+  yield testComplexMultipleColorChanges(inspector, view);
+  yield testOverriddenMultipleColorChanges(inspector, view);
+});
 
-function testSimpleMultipleColorChanges(inspector, ruleView) {
-  Task.spawn(function*() {
-    yield selectNode("p", inspector);
+function* testSimpleMultipleColorChanges(inspector, ruleView) {
+  yield selectNode("p", inspector);
+
+  info("Getting the <p> tag's color property");
+  let swatch = getRuleViewProperty(ruleView, "p", "color").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-    info("Getting the <p> tag's color property");
-    let swatch = getRuleViewSelectorProperty("p", "color", ruleView).valueSpan
-      .querySelector(".ruleview-colorswatch");
-
-    info("Opening the color picker");
-    let picker = ruleView.colorPicker;
-    let onShown = picker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  info("Opening the color picker");
+  let picker = ruleView.colorPicker;
+  let onShown = picker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    info("Changing the color several times");
-    let colors = [
-      {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
-      {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
-      {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
-    ];
-    for (let {rgba, computed} of colors) {
-      yield simulateColorChange(picker, rgba, {
-        element: content.document.querySelector("p"),
-        name: "color",
-        value: computed
-      });
-    }
-  }).then(() => {
-    testComplexMultipleColorChanges(inspector, ruleView);
-  });
+  info("Changing the color several times");
+  let colors = [
+    {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
+    {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
+    {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
+  ];
+  for (let {rgba, computed} of colors) {
+    yield simulateColorPickerChange(picker, rgba, {
+      element: content.document.querySelector("p"),
+      name: "color",
+      value: computed
+    });
+  }
 }
 
-function testComplexMultipleColorChanges(inspector, ruleView) {
-  Task.spawn(function*() {
-    yield selectNode("body", inspector);
+function* testComplexMultipleColorChanges(inspector, ruleView) {
+  yield selectNode("body", inspector);
 
-    info("Getting the <body> tag's color property");
-    let swatch = getRuleViewSelectorProperty("body", "background", ruleView).valueSpan
-      .querySelector(".ruleview-colorswatch");
+  info("Getting the <body> tag's color property");
+  let swatch = getRuleViewProperty(ruleView, "body", "background").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-    info("Opening the color picker");
-    let picker = ruleView.colorPicker;
-    let onShown = picker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  info("Opening the color picker");
+  let picker = ruleView.colorPicker;
+  let onShown = picker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    info("Changing the color several times");
-    let colors = [
-      {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
-      {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
-      {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
-    ];
-    for (let {rgba, computed} of colors) {
-      yield simulateColorChange(picker, rgba, {
-        element: content.document.body,
-        name: "backgroundColor",
-        value: computed
-      });
-    }
+  info("Changing the color several times");
+  let colors = [
+    {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
+    {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
+    {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
+  ];
+  for (let {rgba, computed} of colors) {
+    yield simulateColorPickerChange(picker, rgba, {
+      element: content.document.body,
+      name: "backgroundColor",
+      value: computed
+    });
+  }
 
-    info("Closing the color picker");
-    let onHidden = picker.tooltip.once("hidden");
-    picker.tooltip.hide();
-    yield onHidden;
-  }).then(() => {
-    testOverriddenMultipleColorChanges(inspector, ruleView);
-  });
+  info("Closing the color picker");
+  let onHidden = picker.tooltip.once("hidden");
+  picker.tooltip.hide();
+  yield onHidden;
 }
 
-function testOverriddenMultipleColorChanges(inspector, ruleView) {
-  Task.spawn(function*() {
-    yield selectNode("p", inspector);
+function* testOverriddenMultipleColorChanges(inspector, ruleView) {
+  yield selectNode("p", inspector);
 
-    info("Getting the <body> tag's color property");
-    let swatch = getRuleViewSelectorProperty("body", "color", ruleView).valueSpan
-      .querySelector(".ruleview-colorswatch");
+  info("Getting the <body> tag's color property");
+  let swatch = getRuleViewProperty(ruleView, "body", "color").valueSpan
+    .querySelector(".ruleview-colorswatch");
 
-    info("Opening the color picker");
-    let picker = ruleView.colorPicker;
-    let onShown = picker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  info("Opening the color picker");
+  let picker = ruleView.colorPicker;
+  let onShown = picker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    info("Changing the color several times");
-    let colors = [
-      {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
-      {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
-      {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
-    ];
-    for (let {rgba, computed} of colors) {
-      yield simulateColorChange(picker, rgba, {
-        element: content.document.body,
-        name: "color",
-        value: computed
-      });
-      is(content.getComputedStyle(content.document.querySelector("p")).color,
-        "rgb(200, 200, 200)", "The color of the P tag is still correct");
-    }
-  }).then(finish);
+  info("Changing the color several times");
+  let colors = [
+    {rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
+    {rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
+    {rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
+  ];
+  for (let {rgba, computed} of colors) {
+    yield simulateColorPickerChange(picker, rgba, {
+      element: content.document.body,
+      name: "color",
+      value: computed
+    });
+    is(content.getComputedStyle(content.document.querySelector("p")).color,
+      "rgb(200, 200, 200)", "The color of the P tag is still correct");
+  }
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
@@ -10,64 +10,47 @@ const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    background-color: #ededed;',
   '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
   content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  openRuleView((inspector, ruleView) => {
-    inspector.once("inspector-updated", () => {
-      let swatch = getRuleViewProperty("background-color", ruleView).valueSpan
-        .querySelector(".ruleview-colorswatch");
-      testPressingEscapeRevertsChanges(swatch, ruleView);
-    });
-  });
-}
+  let swatch = getRuleViewProperty(view, "body", "background-color").valueSpan
+    .querySelector(".ruleview-colorswatch");
+  yield testPressingEscapeRevertsChanges(swatch, view);
+});
 
-function testPressingEscapeRevertsChanges(swatch, ruleView) {
-  Task.spawn(function*() {
-    let cPicker = ruleView.colorPicker;
+function* testPressingEscapeRevertsChanges(swatch, ruleView) {
+  let cPicker = ruleView.colorPicker;
+
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
 
-    let onShown = cPicker.tooltip.once("shown");
-    swatch.click();
-    yield onShown;
+  yield simulateColorPickerChange(cPicker, [0, 0, 0, 1], {
+    element: content.document.body,
+    name: "backgroundColor",
+    value: "rgb(0, 0, 0)"
+  });
 
-    yield simulateColorChange(cPicker, [0, 0, 0, 1], {
-      element: content.document.body,
-      name: "backgroundColor",
-      value: "rgb(0, 0, 0)"
-    });
-
-    is(swatch.style.backgroundColor, "rgb(0, 0, 0)",
-      "The color swatch's background was updated");
-    is(getRuleViewProperty("background-color", ruleView).valueSpan.textContent,
-      "rgba(0, 0, 0, 1)", "The text of the background-color css property was updated");
+  is(swatch.style.backgroundColor, "rgb(0, 0, 0)",
+    "The color swatch's background was updated");
+  is(getRuleViewProperty(ruleView, "body", "background-color").valueSpan.textContent,
+    "rgba(0, 0, 0, 1)", "The text of the background-color css property was updated");
 
-    let spectrum = yield cPicker.spectrum;
-
-    // ESC out of the color picker
-    let onHidden = cPicker.tooltip.once("hidden");
-    EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
-    yield onHidden;
+  let spectrum = yield cPicker.spectrum;
 
-    yield waitForSuccess({
-      validatorFn: () => {
-        return content.getComputedStyle(content.document.body).backgroundColor === "rgb(237, 237, 237)";
-      },
-      name: "The element's background-color was reverted"
-    });
-  }).then(finish);
+  // ESC out of the color picker
+  let onHidden = cPicker.tooltip.once("hidden");
+  EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
+  yield onHidden;
+
+  yield waitForSuccess(() => {
+    return content.getComputedStyle(content.document.body).backgroundColor === "rgb(237, 237, 237)";
+  }, "The element's background-color was reverted");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-swatch-displayed.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-swatch-displayed.js
@@ -1,57 +1,55 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test that color swatches are displayed next to colors in the rule-view
 
-let ruleView;
-
 const PAGE_CONTENT = [
   '<style type="text/css">',
   '  body {',
   '    color: red;',
   '    background-color: #ededed;',
   '    background-image: url(chrome://global/skin/icons/warning-64.png);',
   '    border: 2em solid rgba(120, 120, 120, .5);',
   '  }',
+  '  * {',
+  '    color: blue;',
+  '    box-shadow: inset 0 0 2px 20px red, inset 0 0 2px 40px blue;',
+  '  }',
   '</style>',
   'Testing the color picker tooltip!'
 ].join("\n");
 
-function test() {
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function load(evt) {
-    gBrowser.selectedBrowser.removeEventListener("load", load, true);
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,rule view color picker tooltip test";
-}
-
-function createDocument() {
-  content.document.body.innerHTML = PAGE_CONTENT;
+// Tests that properties in the rule-view contain color swatches
+// Each entry in the test array should contain:
+// {
+//   selector: the rule-view selector to look for the property in
+//   propertyName: the property to test
+//   nb: the number of color swatches this property should have
+// }
+const TESTS = [
+  {selector: "body", propertyName: "color", nb: 1},
+  {selector: "body", propertyName: "background-color", nb: 1},
+  {selector: "body", propertyName: "border", nb: 1},
+  {selector: "*", propertyName: "color", nb: 1},
+  {selector: "*", propertyName: "box-shadow", nb: 2},
+];
 
-  openRuleView((inspector, view) => {
-    ruleView = view;
-    inspector.once("inspector-updated", testColorSwatchesAreDisplayed);
-  });
-}
-
-function testColorSwatchesAreDisplayed() {
-  let cSwatch = getRuleViewProperty("color", ruleView).valueSpan
-    .querySelector(".ruleview-colorswatch");
-  ok(cSwatch, "Color swatch is displayed for the color property");
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,rule view color picker tooltip test");
+  content.document.body.innerHTML = PAGE_CONTENT;
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan
-    .querySelector(".ruleview-colorswatch");
-  ok(bgSwatch, "Color swatch is displayed for the bg-color property");
+  for (let {selector, propertyName, nb} of TESTS) {
+    info("Looking for color swatches in property " + propertyName +
+      " in selector " + selector);
 
-  let bSwatch = getRuleViewProperty("border", ruleView).valueSpan
-    .querySelector(".ruleview-colorswatch");
-  ok(bSwatch, "Color swatch is displayed for the border property");
+    let prop = getRuleViewProperty(view, selector, propertyName).valueSpan;
+    let swatches = prop.querySelectorAll(".ruleview-colorswatch");
 
-  ruleView = null;
-  finish();
-}
+    ok(swatches.length, "Swatches found in the property");
+    is(swatches.length, nb, "Correct number of swatches found in the property");
+  }
+});
--- a/browser/devtools/styleinspector/test/browser_ruleview_copy.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_copy.js
@@ -1,170 +1,129 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
-let inspector;
-let win;
+"use strict";
+
+// Tests that properties can be selected and copied from the rule view
 
 XPCOMUtils.defineLazyGetter(this, "osString", function() {
   return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
 });
 
-function createDocument()
-{
-  doc.body.innerHTML = '<style type="text/css"> ' +
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,<p>rule view context menu test</p>");
+
+  info("Creating the test document");
+  content.document.body.innerHTML = '<style type="text/css"> ' +
     'html { color: #000000; } ' +
     'span { font-variant: small-caps; color: #000000; } ' +
     '.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
     'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
     '<h1>Some header text</h1>\n' +
     '<p id="salutation" style="font-size: 12pt">hi.</p>\n' +
     '<p id="body" style="font-size: 12pt">I am a test-case. This text exists ' +
     'solely to provide some things to <span style="color: yellow">' +
     'highlight</span> and <span style="font-weight: bold">count</span> ' +
     'style list-items in the box at right. If you are reading this, ' +
     'you should go do something else instead. Maybe read a book. Or better ' +
     'yet, write some test-cases for another bit of code. ' +
     '<span style="font-style: italic">some text</span></p>\n' +
     '<p id="closing">more text</p>\n' +
     '<p>even more text</p>' +
     '</div>';
-  doc.title = "Rule view context menu test";
+  content.document.title = "Rule view context menu test";
 
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
-  gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
-    win = inspector.sidebar.getWindowForTab("ruleview");
-    highlightNode();
-  });
-}
+  info("Opening the computed view");
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  info("Selecting the test node");
+  yield selectNode("div", inspector);
 
-function highlightNode()
-{
-  // Highlight a node.
-  let div = content.document.getElementsByTagName("div")[0];
+  yield checkCopySelection(view);
+  yield checkSelectAll(view);
+});
 
-  inspector.once("inspector-updated", function() {
-    is(inspector.selection.node, div, "selection matches the div element");
-    executeSoon(checkCopySelection);
-  });
+function checkCopySelection(view) {
+  info("Testing selection copy");
 
-  inspector.selection.setNode(div);
-}
-
-function checkCopySelection()
-{
-  let contentDoc = win.document;
+  let contentDoc = view.doc;
   let prop = contentDoc.querySelector(".ruleview-property");
   let values = contentDoc.querySelectorAll(".ruleview-propertycontainer");
 
   let range = contentDoc.createRange();
   range.setStart(prop, 0);
   range.setEnd(values[4], 2);
-
-  let selection = win.getSelection();
-  selection.addRange(range);
+  let selection = view.doc.defaultView.getSelection().addRange(range);
 
   info("Checking that _Copy() returns the correct clipboard value");
+
   let expectedPattern = "    margin: 10em;[\\r\\n]+" +
                         "    font-size: 14pt;[\\r\\n]+" +
                         "    font-family: helvetica,sans-serif;[\\r\\n]+" +
                         "    color: #AAA;[\\r\\n]+" +
                         "}[\\r\\n]+" +
                         "html {[\\r\\n]+" +
                         "    color: #000;[\\r\\n]*";
 
-  SimpleTest.waitForClipboard(function() {
-    return checkClipboardData(expectedPattern);
-  },
-  function() {
+  return waitForClipboard(() => {
     fireCopyEvent(prop);
-  },
-  checkSelectAll,
-  function() {
-    failedClipboard(expectedPattern, checkSelectAll);
+  }, () => {
+    return checkClipboardData(expectedPattern);
+  }).then(() => {}, () => {
+    failedClipboard(expectedPattern);
   });
 }
 
-function checkSelectAll()
-{
-  let contentDoc = win.document;
-  let _ruleView = ruleView();
+function checkSelectAll(view) {
+  info("Testing select-all copy");
+
+  let contentDoc = view.doc;
   let prop = contentDoc.querySelector(".ruleview-property");
 
   info("Checking that _SelectAll() then copy returns the correct clipboard value");
-  _ruleView._onSelectAll();
+  view._onSelectAll();
   let expectedPattern = "[\\r\\n]+" +
                         "element {[\\r\\n]+" +
                         "    margin: 10em;[\\r\\n]+" +
                         "    font-size: 14pt;[\\r\\n]+" +
                         "    font-family: helvetica,sans-serif;[\\r\\n]+" +
                         "    color: #AAA;[\\r\\n]+" +
                         "}[\\r\\n]+" +
                         "html {[\\r\\n]+" +
                         "    color: #000;[\\r\\n]+" +
                         "}[\\r\\n]*";
 
-  SimpleTest.waitForClipboard(function() {
-    return checkClipboardData(expectedPattern);
-  },
-  function() {
+  return waitForClipboard(() => {
     fireCopyEvent(prop);
-  },
-  finishup,
-  function() {
-    failedClipboard(expectedPattern, finishup);
+  }, () => {
+    return checkClipboardData(expectedPattern);
+  }).then(() => {}, () => {
+    failedClipboard(expectedPattern);
   });
 }
 
-function checkClipboardData(aExpectedPattern)
-{
+function checkClipboardData(expectedPattern) {
   let actual = SpecialPowers.getClipboardData("text/unicode");
-  let expectedRegExp = new RegExp(aExpectedPattern, "g");
+  let expectedRegExp = new RegExp(expectedPattern, "g");
   return expectedRegExp.test(actual);
 }
 
-function failedClipboard(aExpectedPattern, aCallback)
-{
+function failedClipboard(expectedPattern) {
   // Format expected text for comparison
   let terminator = osString == "WINNT" ? "\r\n" : "\n";
-  aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
-  aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "(");
-  aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")");
+  expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator);
+  expectedPattern = expectedPattern.replace(/\\\(/g, "(");
+  expectedPattern = expectedPattern.replace(/\\\)/g, ")");
 
   let actual = SpecialPowers.getClipboardData("text/unicode");
 
   // Trim the right hand side of our strings. This is because expectedPattern
   // accounts for windows sometimes adding a newline to our copied data.
-  aExpectedPattern = aExpectedPattern.trimRight();
+  expectedPattern = expectedPattern.trimRight();
   actual = actual.trimRight();
 
   dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " +
     "results (escaped for accurate comparison):\n");
   info("Actual: " + escape(actual));
-  info("Expected: " + escape(aExpectedPattern));
-  aCallback();
-}
-
-function finishup()
-{
-  gBrowser.removeCurrentTab();
-  doc = inspector = win = null;
-  finish();
+  info("Expected: " + escape(expectedPattern));
 }
-
-function test()
-{
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(createDocument, content);
-  }, true);
-
-  content.location = "data:text/html,<p>rule view context menu test</p>";
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_editor.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_editor.js
@@ -1,119 +1,117 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc = content.document;
+"use strict";
 
-function expectDone(aValue, aCommit, aNext)
-{
-  return function(aDoneValue, aDoneCommit) {
-    dump("aDoneValue: " + aDoneValue + " commit: " + aDoneCommit + "\n");
+// Test the inplace-editor behavior.
+// This test doesn't open the devtools, it just exercises the inplace-editor
+// on test elements in the page
 
-    is(aDoneValue, aValue, "Should get expected value");
-    is(aDoneCommit, aDoneCommit, "Should get expected commit value");
-    aNext();
-  }
-}
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,inline editor tests");
+  yield testReturnCommit();
+  yield testBlurCommit();
+  yield testAdvanceCharCommit();
+});
+
+function testReturnCommit() {
+  info("Testing that pressing return commits the new value");
+  let def = promise.defer();
 
-function clearBody()
-{
-  doc.body.innerHTML = "";
-}
+  createInplaceEditorAndClick({
+    initial: "explicit initial",
+    start: function(editor) {
+      is(editor.input.value, "explicit initial", "Explicit initial value should be used.");
+      editor.input.value = "Test Value";
+      EventUtils.sendKey("return");
+    },
+    done: onDone("Test Value", true, def)
+  });
 
-function createSpan()
-{
-  let span = doc.createElement("span");
-  span.setAttribute("tabindex", "0");
-  span.textContent = "Edit Me!";
-  doc.body.appendChild(span);
-  return span;
+  return def.promise;
 }
 
-function testReturnCommit()
-{
-  clearBody();
-  let span = createSpan();
-  editableField({
-    element: span,
-    initial: "explicit initial",
-    start: function() {
-      is(inplaceEditor(span).input.value, "explicit initial", "Explicit initial value should be used.");
-      inplaceEditor(span).input.value = "Test Value";
-      EventUtils.sendKey("return");
+function testBlurCommit() {
+  info("Testing that bluring the field commits the new value");
+  let def = promise.defer();
+
+  createInplaceEditorAndClick({
+    start: function(editor) {
+      is(editor.input.value, "Edit Me!", "textContent of the span used.");
+      editor.input.value = "Test Value";
+      editor.input.blur();
     },
-    done: expectDone("Test Value", true, testBlurCommit)
+    done: onDone("Test Value", true, def)
   });
-  span.click();
+
+  return def.promise;
 }
 
-function testBlurCommit()
-{
-  clearBody();
-  let span = createSpan();
-  editableField({
-    element: span,
-    start: function() {
-      is(inplaceEditor(span).input.value, "Edit Me!", "textContent of the span used.");
-      inplaceEditor(span).input.value = "Test Value";
-      inplaceEditor(span).input.blur();
-    },
-    done: expectDone("Test Value", true, testAdvanceCharCommit)
-  });
-  span.click();
-}
+function testAdvanceCharCommit() {
+  info("Testing that configured advanceChars commit the new value");
+  let def = promise.defer();
 
-function testAdvanceCharCommit()
-{
-  clearBody();
-  let span = createSpan();
-  editableField({
-    element: span,
+  createInplaceEditorAndClick({
     advanceChars: ":",
-    start: function() {
-      let input = inplaceEditor(span).input;
+    start: function(editor) {
+      let input = editor.input;
       for each (let ch in "Test:") {
         EventUtils.sendChar(ch);
       }
     },
-    done: expectDone("Test", true, testEscapeCancel)
+    done: onDone("Test", true, def)
   });
-  span.click();
+
+  return def.promise;
 }
 
-function testEscapeCancel()
-{
-  clearBody();
-  let span = createSpan();
-  editableField({
-    element: span,
+function testEscapeCancel() {
+  info("Testing that escape cancels the new value");
+  let def = promise.defer();
+
+  createInplaceEditorAndClick({
     initial: "initial text",
-    start: function() {
-      inplaceEditor(span).input.value = "Test Value";
+    start: function(editor) {
+      editor.input.value = "Test Value";
       EventUtils.sendKey("escape");
     },
-    done: expectDone("initial text", false, finishTest)
+    done: onDone("initial text", false, def)
   });
+
+  return def.promise;
+}
+
+function onDone(value, isCommit, def) {
+  return function(actualValue, actualCommit) {
+    info("Inplace-editor's done callback executed, checking its state");
+    is(actualValue, value, "The value is correct");
+    is(actualCommit, isCommit, "The commit boolean is correct");
+    def.resolve();
+  }
+}
+
+function createInplaceEditorAndClick(options) {
+  clearBody();
+  let span = options.element = createSpan();
+
+  info("Creating an inplace-editor field");
+  editableField(options);
+
+  info("Clicking on the inplace-editor field to turn to edit mode");
   span.click();
 }
 
-
-function finishTest()
-{
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
+function clearBody() {
+  info("Clearing the page body");
+  content.document.body.innerHTML = "";
 }
 
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(testReturnCommit, content);
-  }, true);
-
-  content.location = "data:text/html,inline editor tests";
+function createSpan() {
+  info("Creating a new span element");
+  let span = content.document.createElement("span");
+  span.setAttribute("tabindex", "0");
+  span.textContent = "Edit Me!";
+  content.document.body.appendChild(span);
+  return span;
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js
@@ -1,220 +1,187 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
-let ruleWindow;
-let ruleView;
-let inspector;
-let TEST_URL = 'url("http://example.com/browser/browser/devtools/' +
-               'styleinspector/test/test-image.png")';
+"use strict";
+
+// Testing various inplace-editor behaviors in the rule-view
+// FIXME: To be split in several test files, and some of the inplace-editor
+// focus/blur/commit/revert stuff should be factored out in head.js
 
-function startTest()
-{
-  let style = '' +
-    '#testid {' +
-    '  background-color: blue;' +
-    '} ' +
-    '.testclass {' +
-    '  background-color: green;' +
-    '}';
+let TEST_URL = 'url("' + TEST_URL_ROOT + 'test-image.png")';
+let PAGE_CONTENT = [
+  '<style type="text/css">',
+  '  #testid {',
+  '    background-color: blue;',
+  '  }',
+  '  .testclass {',
+  '    background-color: green;',
+  '  }',
+  '</style>',
+  '<div id="testid" class="testclass">Styled Node</div>'
+].join("\n");
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
-  let testElement = doc.getElementById("testid");
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,test rule view user changes");
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    ruleWindow = aRuleView.doc.defaultView;
-    inspector.selection.setNode(testElement);
-    inspector.once("inspector-updated", testCancelNew);
-  });
-}
+  info("Creating the test document");
+  content.document.body.innerHTML = PAGE_CONTENT;
 
-function testCancelNew()
-{
-  // Start at the beginning: start to add a rule to the element's style
-  // declaration, but leave it empty.
-  let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    let input = aEditor.input;
-    waitForEditorBlur(aEditor, function () {
-      ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding request after a cancel.");
-      is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
-      ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
-      testCreateNew();
-    });
-    aEditor.input.blur();
-  });
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
-}
+  info("Opening the rule-view");
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  info("Selecting the test element");
+  yield selectNode("#testid", inspector);
+
+  yield testCancelNew(view);
+  yield testCreateNew(view);
+  yield testCreateNewEscape(view);
+  yield testEditProperty(view, "border-color", "red");
+  yield testEditProperty(view, "background-image", TEST_URL);
+});
+
+function* testCancelNew(view) {
+  info("Test adding a new rule to the element's style declaration and leaving it empty.");
 
-function testCreateNew()
-{
-  // Create a new property.
-  let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    let input = aEditor.input;
-    input.value = "background-color";
+  let elementRuleEditor = view.element.children[0]._ruleEditor;
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused");
 
-    waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
-      promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => {
-        is(elementRuleEditor.rule.textProps.length,  1, "Should have created a new text property.");
-        is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
-        let textProp = elementRuleEditor.rule.textProps[0];
-        is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
-        aEditor.input.value = "#XYZ";
-        waitForEditorBlur(aEditor, function() {
-          promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => {
-            is(textProp.value, "#XYZ", "Text prop should have been changed.");
-            is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry");
-            testCreateNewEscape();
-          }));
-        });
-        aEditor.input.blur();
-      }));
-    });
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
-  });
+  info("Bluring the editor input");
+  let onBlur = once(editor.input, "blur");
+  editor.input.blur();
+  yield onBlur;
 
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
+  info("Checking the state of canceling a new property name editor");
+  ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding request after a cancel.");
+  is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
+  ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
 }
 
-function testCreateNewEscape()
-{
-  // Create a new property.
-  let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    let input = aEditor.input;
-    input.value = "color";
+function* testCreateNew(view) {
+  info("Test creating a new property");
+
+  let elementRuleEditor = view.element.children[0]._ruleEditor;
 
-    waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
-      promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => {
-        is(elementRuleEditor.rule.textProps.length,  2, "Should have created a new text property.");
-        is(elementRuleEditor.propertyList.children.length, 2, "Should have created a property editor.");
-        let textProp = elementRuleEditor.rule.textProps[1];
-        is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
-        aEditor.input.value = "red";
-        EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow);
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused");
+  let input = editor.input;
+
+  info("Entering background-color in the property name editor");
+  input.value = "background-color";
 
-        // Make sure previous input is focused.
-        let focusedElement = inplaceEditor(elementRuleEditor.rule.textProps[0].editor.valueSpan).input;
-        is(focusedElement, focusedElement.ownerDocument.activeElement, "Correct element has focus");
+  info("Pressing return to commit and focus the new value field");
+  let onValueFocus = once(elementRuleEditor.element, "focus", true);
+  let onModifications = elementRuleEditor.rule._applyingModifications;
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
+  yield onValueFocus;
+  yield onModifications;
 
-        EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow);
-
-        is(elementRuleEditor.rule.textProps.length,  1, "Should have removed the new text property.");
-        is(elementRuleEditor.propertyList.children.length, 1, "Should have removed the property editor.");
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.doc.activeElement);
+  let textProp = elementRuleEditor.rule.textProps[0];
 
-        testEditProperty();
-      }));
-    });
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
-  });
+  is(elementRuleEditor.rule.textProps.length,  1, "Created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 1, "Created a property editor.");
+  is(editor, inplaceEditor(textProp.editor.valueSpan), "Editing the value span now.");
 
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
+  info("Entering a value and bluring the field to expect a rule change");
+  editor.input.value = "#XYZ";
+  let onBlur = once(editor.input, "blur");
+  let onModifications = elementRuleEditor.rule._applyingModifications;
+  editor.input.blur();
+  yield onBlur;
+  yield onModifications;
+
+  is(textProp.value, "#XYZ", "Text prop should have been changed.");
+  is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry");
 }
 
-function testEditProperty()
-{
-  let idRuleEditor = ruleView.element.children[1]._ruleEditor;
-  let propEditor = idRuleEditor.rule.textProps[0].editor;
-  waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
-    let input = aEditor.input;
-    waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
-      promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-        input = aEditor.input;
-        is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
+function* testCreateNewEscape(view) {
+  info("Test creating a new property and escaping");
+
+  let elementRuleEditor = view.element.children[0]._ruleEditor;
+
+  info("Focusing a new property name in the rule-view");
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused.");
+  let input = editor.input;
+
+  info("Entering a value in the property name editor");
+  input.value = "color";
+
+  info("Pressing return to commit and focus the new value field");
+  let onValueFocus = once(elementRuleEditor.element, "focus", true);
+  let onModifications = elementRuleEditor.rule._applyingModifications;
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
+  yield onValueFocus;
+  yield onModifications;
 
-        waitForEditorBlur(aEditor, function() {
-          promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-            let value = idRuleEditor.rule.domRule._rawStyle().getPropertyValue("border-color");
-            is(value, "red", "border-color should have been set.");
-            is(propEditor.isValid(), true, "red should be a valid entry");
-            testEditPropertyWithColon();
-          }));
-        });
+  // Getting the new value editor after focus
+  editor = inplaceEditor(view.doc.activeElement);
+  let textProp = elementRuleEditor.rule.textProps[1];
+
+  is(elementRuleEditor.rule.textProps.length,  2, "Created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 2, "Created a property editor.");
+  is(editor, inplaceEditor(textProp.editor.valueSpan), "Editing the value span now.");
+
+  info("Entering a property value");
+  editor.input.value = "red";
 
-        for (let ch of "red;") {
-          EventUtils.sendChar(ch, ruleWindow);
-        }
-      }));
-    });
-    for (let ch of "border-color:") {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-  });
+  info("Escaping out of the field");
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
 
-  EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1,
-                             { },
-                             ruleWindow);
+  info("Checking that the previous field is focused");
+  let focusedElement = inplaceEditor(elementRuleEditor.rule.textProps[0].editor.valueSpan).input;
+  is(focusedElement, focusedElement.ownerDocument.activeElement, "Correct element has focus");
+
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
+
+  is(elementRuleEditor.rule.textProps.length,  1, "Removed the new text property.");
+  is(elementRuleEditor.propertyList.children.length, 1, "Removed the property editor.");
 }
 
-function testEditPropertyWithColon()
-{
-  let idRuleEditor = ruleView.element.children[1]._ruleEditor;
+function* testEditProperty(view, name, value) {
+  info("Test editing existing property name/value fields");
+
+  let idRuleEditor = view.element.children[1]._ruleEditor;
   let propEditor = idRuleEditor.rule.textProps[0].editor;
-  waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
-    let input = aEditor.input;
-    waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
-      promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-        input = aEditor.input;
-        is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
 
-        waitForEditorBlur(aEditor, function() {
-          promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-            let value = idRuleEditor.rule.domRule._rawStyle().getPropertyValue("background-image");
-            is(value, TEST_URL, "background-image should have been set.");
-            is(propEditor.isValid(), true, "the test URL should be a valid entry");
-            finishTest();
-          }));
-        });
+  info("Focusing an existing property name in the rule-view");
+  let editor = yield focusEditableField(propEditor.nameSpan, 32, 1);
 
+  is(inplaceEditor(propEditor.nameSpan), editor, "The property name editor got focused");
+  let input = editor.input;
 
-        for (let ch of (TEST_URL + ";")) {
-          EventUtils.sendChar(ch, ruleWindow);
-        }
-      }));
-    });
-    for (let ch of "background-image:") {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-  });
+  info("Entering a new property name, including : to commit and focus the value");
+  let onValueFocus = once(idRuleEditor.element, "focus", true);
+  let onModifications = idRuleEditor.rule._applyingModifications;
+  for (let ch of name + ":") {
+    EventUtils.sendChar(ch, view.doc.defaultView);
+  }
+  yield onValueFocus;
+  yield onModifications;
 
-  EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1,
-                             { },
-                             ruleWindow);
-}
+  // Getting the value editor after focus
+  editor = inplaceEditor(view.doc.activeElement);
+  input = editor.input;
+  is(inplaceEditor(propEditor.valueSpan), editor, "Focus moved to the value.");
 
-function finishTest()
-{
-  inspector = ruleWindow = ruleView = null;
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  info("Entering a new value, including ; to commit and blur the value");
+  let onBlur = once(input, "blur");
+  let onModifications = idRuleEditor.rule._applyingModifications;
+  for (let ch of value + ";") {
+    EventUtils.sendChar(ch, view.doc.defaultView);
+  }
+  yield onBlur;
+  yield onModifications;
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true);
-    doc = content.document;
-    waitForFocus(startTest, content);
-  }, true);
-
-  content.location = "data:text/html,test rule view user changes";
+  let propValue = idRuleEditor.rule.domRule._rawStyle().getPropertyValue(name);
+  is(propValue, value, name + " should have been set.");
+  is(propEditor.isValid(), true, value + " should be a valid entry");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_focus.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_focus.js
@@ -1,65 +1,49 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
 // Test that focus doesn't leave the style editor when adding a property
 // (bug 719916)
 
-let doc;
-let inspector;
-let stylePanel;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,<h1>Some header text</h1>");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-function selectNode(aInspector, aRuleView)
-{
-  inspector = aInspector;
-  let node = content.document.getElementsByTagName("h1")[0];
-  inspector.selection.setNode(node);
-  inspector.once("inspector-updated", testFocus);
-}
+  info("Selecting the test node");
+  yield selectNode("h1", inspector);
 
-function testFocus()
-{
-  let win = inspector.sidebar.getWindowForTab("ruleview");
-  let brace = win.document.querySelectorAll(".ruleview-ruleclose")[0];
+  info("Getting the ruleclose brace element");
+  let brace = view.doc.querySelector(".ruleview-ruleclose");
 
-  waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
-    aEditor.input.value = "color";
-    waitForEditorFocus(brace.parentNode, function onEditingValue(aEditor) {
-      // If we actually get this focus we're ok.
-      ok(true, "We got focus.");
-      aEditor.input.value = "green";
+  info("Clicking on the brace element to focus the new property field");
+  let onFocus = once(brace.parentNode, "focus", true);
+  brace.click();
+  yield onFocus;
+
+  info("Entering a property name");
+  let editor = getCurrentInplaceEditor(view);
+  editor.input.value = "color";
 
-      // If we've retained focus, pressing return will start a new editor.
-      // If not, we'll wait here until we time out.
-      waitForEditorFocus(brace.parentNode, function onNewEditor(aEditor) {
-        aEditor.input.blur();
-        finishUp();
-      });
-      EventUtils.sendKey("return");
-    });
-    EventUtils.sendKey("return");
-  });
+  info("Typing ENTER to focus the next field: property value");
+  let onFocus = once(brace.parentNode, "focus", true);
+  EventUtils.sendKey("return");
+  yield onFocus;
+  ok(true, "The value field was focused");
 
-  brace.click();
-}
+  info("Entering a property value");
+  let editor = getCurrentInplaceEditor(view);
+  editor.input.value = "green";
 
-function finishUp()
-{
-  doc = inspector = stylePanel = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  info("Typing ENTER again should focus a new property name");
+  let onFocus = once(brace.parentNode, "focus", true);
+  EventUtils.sendKey("return");
+  yield onFocus;
+  ok(true, "The new property name field was focused");
+  getCurrentInplaceEditor(view).input.blur();
+});
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    doc.title = "Rule View Test";
-    waitForFocus(() => openRuleView(selectNode), content);
-  }, true);
-
-  content.location = "data:text/html,<h1>Some header text</h1>";
+function getCurrentInplaceEditor(view) {
+  return inplaceEditor(view.doc.activeElement);
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_inherit.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_inherit.js
@@ -1,116 +1,86 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
+"use strict";
 
-let inspector;
-let view;
+// Check that inherited properties appear as such in the rule-view
 
 let {ELEMENT_STYLE} = devtools.require("devtools/server/actors/styles");
 
-function simpleInherit(aInspector, aRuleView)
-{
-  inspector = aInspector;
-  view = aRuleView;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,browser_inspector_changes.js");
+  let {toolbox, inspector, view} = yield openRuleView();
 
+  yield simpleInherit(inspector, view);
+  yield emptyInherit(inspector, view);
+  yield elementStyleInherit(inspector, view);
+});
+
+function* simpleInherit(inspector, view) {
   let style = '' +
     '#test2 {' +
     '  background-color: green;' +
     '  color: purple;' +
     '}';
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
 
-  inspector.selection.setNode(doc.getElementById("test1"));
-  inspector.once("inspector-updated", () => {
-    let elementStyle = view._elementStyle;
+  yield selectNode("#test1", inspector);
 
-    is(elementStyle.rules.length, 2, "Should have 2 rules.");
-
-    let elementRule = elementStyle.rules[0];
-    ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
+  let elementStyle = view._elementStyle;
+  is(elementStyle.rules.length, 2, "Should have 2 rules.");
 
-    let inheritRule = elementStyle.rules[1];
-    is(inheritRule.selectorText, "#test2", "Inherited rule should be the one that includes inheritable properties.");
-    ok(!!inheritRule.inherited, "Rule should consider itself inherited.");
-    is(inheritRule.textProps.length, 1, "Should only display one inherited style");
-    let inheritProp = inheritRule.textProps[0];
-    is(inheritProp.name, "color", "color should have been inherited.");
+  let elementRule = elementStyle.rules[0];
+  ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
 
-    styleNode.parentNode.removeChild(styleNode);
+  let inheritRule = elementStyle.rules[1];
+  is(inheritRule.selectorText, "#test2", "Inherited rule should be the one that includes inheritable properties.");
+  ok(!!inheritRule.inherited, "Rule should consider itself inherited.");
+  is(inheritRule.textProps.length, 1, "Should only display one inherited style");
+  let inheritProp = inheritRule.textProps[0];
+  is(inheritProp.name, "color", "color should have been inherited.");
 
-    emptyInherit();
-  });
+  styleNode.remove();
 }
 
-function emptyInherit()
-{
+function* emptyInherit(inspector, view) {
   // No inheritable styles, this rule shouldn't show up.
   let style = '' +
     '#test2 {' +
     '  background-color: green;' +
     '}';
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
 
-  inspector.selection.setNode(doc.getElementById("test1"));
-  inspector.once("inspector-updated", () => {
-    let elementStyle = view._elementStyle;
+  yield selectNode("#test1", inspector);
 
-    is(elementStyle.rules.length, 1, "Should have 1 rule.");
-
-    let elementRule = elementStyle.rules[0];
-    ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
+  let elementStyle = view._elementStyle;
+  is(elementStyle.rules.length, 1, "Should have 1 rule.");
 
-    styleNode.parentNode.removeChild(styleNode);
+  let elementRule = elementStyle.rules[0];
+  ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
 
-    elementStyleInherit();
-  });
+  styleNode.parentNode.removeChild(styleNode);
 }
 
-function elementStyleInherit()
-{
-  doc.body.innerHTML = '<div id="test2" style="color: red"><div id="test1">Styled Node</div></div>';
-
-  inspector.selection.setNode(doc.getElementById("test1"));
-  inspector.once("inspector-updated", () => {
-    let elementStyle = view._elementStyle;
-
-    is(elementStyle.rules.length, 2, "Should have 2 rules.");
+function* elementStyleInherit(inspector, view) {
+  content.document.body.innerHTML = '<div id="test2" style="color: red"><div id="test1">Styled Node</div></div>';
 
-    let elementRule = elementStyle.rules[0];
-    ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
+  yield selectNode("#test1", inspector);
 
-    let inheritRule = elementStyle.rules[1];
-    is(inheritRule.domRule.type, ELEMENT_STYLE, "Inherited rule should be an element style, not a rule.");
-    ok(!!inheritRule.inherited, "Rule should consider itself inherited.");
-    is(inheritRule.textProps.length, 1, "Should only display one inherited style");
-    let inheritProp = inheritRule.textProps[0];
-    is(inheritProp.name, "color", "color should have been inherited.");
+  let elementStyle = view._elementStyle;
+  is(elementStyle.rules.length, 2, "Should have 2 rules.");
 
-    finishTest();
-  });
-}
-
-function finishTest()
-{
-  doc = inspector = view = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  let elementRule = elementStyle.rules[0];
+  ok(!elementRule.inherited, "Element style attribute should not consider itself inherited.");
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(() => openRuleView(simpleInherit), content);
-  }, true);
-
-  content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js";
+  let inheritRule = elementStyle.rules[1];
+  is(inheritRule.domRule.type, ELEMENT_STYLE, "Inherited rule should be an element style, not a rule.");
+  ok(!!inheritRule.inherited, "Rule should consider itself inherited.");
+  is(inheritRule.textProps.length, 1, "Should only display one inherited style");
+  let inheritProp = inheritRule.textProps[0];
+  is(inheritProp.name, "color", "color should have been inherited.");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js
@@ -1,102 +1,66 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
 // Test that changes are previewed when editing a property value
 
-let doc;
-let testElement;
-let ruleWindow;
-let ruleView;
-let inspector;
-
 // Format
 // {
 //   value : what to type in the field
 //   expected : expected computed style on the targeted element
 // }
-let testData = [
+const TEST_DATA = [
   {value: "inline", expected: "inline"},
   {value: "inline-block", expected: "inline-block"},
 
   // Invalid property values should not apply, and should fall back to default
   {value: "red", expected: "block"},
   {value: "something", expected: "block"},
 
   {escape: true, value: "inline", expected: "block"}
 ];
 
-function startTest()
-{
-  let style = '#testid {display:block;}';
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,test rule view live preview on user changes");
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid">Styled Node</div><span>inline element</span>';
-  testElement = doc.getElementById("testid");
+  let style = '#testid {display:block;}';
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = '<div id="testid">Styled Node</div><span>inline element</span>';
+  let testElement = getNode("#testid");
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    ruleWindow = aRuleView.doc.defaultView;
-    inspector.selection.setNode(testElement);
-    inspector.once("inspector-updated", () => loopTestData(0));
-  });
-}
+  let {toolbox, inspector, view} = yield openRuleView();
+  yield selectNode(testElement, inspector);
 
-function loopTestData(index)
-{
-  if(index === testData.length) {
-    finishTest();
-    return;
+  for (let data of TEST_DATA) {
+    yield testLivePreviewData(data, view, testElement);
   }
+});
 
+
+function* testLivePreviewData(data, ruleView, testElement) {
   let idRuleEditor = ruleView.element.children[1]._ruleEditor;
   let propEditor = idRuleEditor.rule.textProps[0].editor;
-  waitForEditorFocus(propEditor.element, function(aEditor) {
-    is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value.");
 
-    let thisTest = testData[index];
-
-    // Entering a correct value for the property
-    for (let ch of thisTest.value) {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-    if (thisTest.escape) {
-      EventUtils.synthesizeKey("VK_ESCAPE", {});
-    } else {
-      EventUtils.synthesizeKey("VK_RETURN", {});
-    }
-
-    // While the editor is still focused in, the display should have changed already
-    executeSoon(() => {
-      is(content.getComputedStyle(testElement).display,
-        testData[index].expected,
-        "Element should be previewed as " + testData[index].expected);
+  info("Focusing the property value inplace-editor");
+  let editor = yield focusEditableField(propEditor.valueSpan);
+  is(inplaceEditor(propEditor.valueSpan), editor, "The focused editor is the value");
 
-      loopTestData(index + 1);
-    });
-  });
-
-  EventUtils.synthesizeMouse(propEditor.valueSpan, 1, 1, {}, ruleWindow);
-}
+  info("Enter a value in the editor")
+  for (let ch of data.value) {
+    EventUtils.sendChar(ch, ruleView.doc.defaultView);
+  }
+  if (data.escape) {
+    EventUtils.synthesizeKey("VK_ESCAPE", {});
+  } else {
+    EventUtils.synthesizeKey("VK_RETURN", {});
+  }
 
-function finishTest()
-{
-  inspector = ruleWindow = ruleView = null;
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  yield wait(1);
+
+  // While the editor is still focused in, the display should have changed already
+  is(content.getComputedStyle(testElement).display,
+    data.expected,
+    "Element should be previewed as " + data.expected);
 }
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true);
-    doc = content.document;
-    waitForFocus(startTest, content);
-  }, true);
-
-  content.location = "data:text/html,test rule view live preview on user changes";
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js
@@ -1,87 +1,68 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let doc;
+"use strict";
+
+// Checking properties orders and overrides in the rule-view
 
-function simpleOverride(aInspector, aRuleView)
-{
-  doc.body.innerHTML = '<div id="testid">Styled Node</div>';
-  let element = doc.getElementById("testid");
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,browser_ruleview_manipulation.js");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-  aInspector.selection.setNode(element);
-  aInspector.once("inspector-updated", () => {
-    let elementStyle = aRuleView._elementStyle;
-
-    let elementRule = elementStyle.rules[0];
-    let firstProp = elementRule.createProperty("background-color", "green", "");
-    let secondProp = elementRule.createProperty("background-color", "blue", "");
-    is(elementRule.textProps[0], firstProp, "Rules should be in addition order.");
-    is(elementRule.textProps[1], secondProp, "Rules should be in addition order.");
+  info("Creating the test document and getting the test node");
+  content.document.body.innerHTML = '<div id="testid">Styled Node</div>';
+  let element = getNode("#testid");
 
-    promiseDone(elementRule._applyingModifications.then(() => {
-      is(element.style.getPropertyValue("background-color"), "blue", "Second property should have been used.");
+  yield selectNode(element, inspector);
 
-      secondProp.remove();
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "green", "After deleting second property, first should be used.");
+  let elementStyle = view._elementStyle;
+  let elementRule = elementStyle.rules[0];
 
-      secondProp = elementRule.createProperty("background-color", "blue", "");
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "blue", "New property should be used.");
+  info("Checking rules insertion order and checking the applied style");
+  let firstProp = elementRule.createProperty("background-color", "green", "");
+  let secondProp = elementRule.createProperty("background-color", "blue", "");
+  is(elementRule.textProps[0], firstProp, "Rules should be in addition order.");
+  is(elementRule.textProps[1], secondProp, "Rules should be in addition order.");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue", "Second property should have been used.");
 
-      is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
-      is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
-
-      secondProp.setEnabled(false);
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "green", "After disabling second property, first value should be used");
+  info("Removing the second property and checking the applied style again");
+  secondProp.remove();
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "green", "After deleting second property, first should be used.");
 
-      firstProp.setEnabled(false);
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "", "After disabling both properties, value should be empty.");
+  info("Creating a new second property and checking that the insertion order is still the same");
+  secondProp = elementRule.createProperty("background-color", "blue", "");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue", "New property should be used.");
+  is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
+  is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
 
-      secondProp.setEnabled(true);
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "blue", "Value should be set correctly after re-enabling");
+  info("Disabling the second property and checking the applied style");
+  secondProp.setEnabled(false);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "green", "After disabling second property, first value should be used");
 
-      firstProp.setEnabled(true);
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "blue", "Re-enabling an earlier property shouldn't make it override a later property.");
-      is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
-      is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
+  info("Disabling the first property too and checking the applied style");
+  firstProp.setEnabled(false);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "", "After disabling both properties, value should be empty.");
 
-      firstProp.setValue("purple", "");
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(element.style.getPropertyValue("background-color"), "blue", "Modifying an earlier property shouldn't override a later property.");
-      finishTest();
-    }));
-  });
-}
+  info("Re-enabling the second propertyt and checking the applied style");
+  secondProp.setEnabled(true);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue", "Value should be set correctly after re-enabling");
 
-function finishTest()
-{
-  doc = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  info("Re-enabling the first property and checking the insertion order is still respected");
+  firstProp.setEnabled(true);
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue", "Re-enabling an earlier property shouldn't make it override a later property.");
+  is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places.");
+  is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places.");
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(() => openRuleView(simpleOverride), content);
-  }, true);
-
-  content.location = "data:text/html;charset=utf-8,browser_ruleview_manipulation.js";
-}
+  info("Modifying the first property and checking the applied style");
+  firstProp.setValue("purple", "");
+  yield elementRule._applyingModifications;
+  is(element.style.getPropertyValue("background-color"), "blue", "Modifying an earlier property shouldn't override a later property.");
+});
--- a/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js
@@ -1,276 +1,233 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
 
-let doc;
-let ruleWindow;
-let ruleView;
-let inspector;
-let elementRuleEditor;
+// Test that the rule-view behaves correctly when entering mutliple and/or
+// unfinished properties/values in inplace-editors
+
+let test = asyncTest(function*() {
+  yield addTab("data:text/html,test rule view user changes");
+  content.document.body.innerHTML = "<h1>Testing Multiple Properties</h1>";
+
+  let {toolbox, inspector, view} = yield openRuleView();
 
-function startTest()
-{
-  doc.body.innerHTML = '<h1>Testing Multiple Properties</h1>';
+  yield testCreateNewMulti(inspector, view);
+  yield testCreateNewMultiDuplicates(inspector, view);
+  yield testCreateNewMultiPriority(inspector, view);
+  yield testCreateNewMultiUnfinished(inspector, view);
+  yield testCreateNewMultiPartialUnfinished(inspector, view);
+  yield testMultiValues(inspector, view);
+});
 
-  openRuleView((aInspector, aRuleView) => {
-    inspector = aInspector;
-    ruleView = aRuleView;
-    ruleWindow = aRuleView.doc.defaultView;
-    selectNewElement().then(testCreateNewMulti);
-  });
+/**
+ * Create a new test element, select it, and return the rule-view ruleEditor
+ */
+function* createAndSelectNewElement(inspector, view) {
+  info("Creating a new test element");
+  let newElement = content.document.createElement("div");
+  newElement.textContent = "Test Element";
+  content.document.body.appendChild(newElement);
+
+  info("Selecting the new element and waiting for the inspector to update");
+  yield selectNode(newElement, inspector);
+
+  info("Getting the rule-view rule editor for that new element");
+  return view.element.children[0]._ruleEditor;
 }
 
-/*
- * Add a new node to the DOM and resolve the promise once it is ready to use
- */
-function selectNewElement()
-{
-  let newElement = doc.createElement("div");
-  newElement.textContent = "Test Element";
-  doc.body.appendChild(newElement);
-
-  inspector.selection.setNode(newElement, "test");
-  let def = promise.defer();
-  ruleView.element.addEventListener("CssRuleViewRefreshed", function changed() {
-    ruleView.element.removeEventListener("CssRuleViewRefreshed", changed);
-    elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-    def.resolve();
-  });
-
-  return def.promise;
-}
-
-/*
+/**
  * Begin the creation of a new property, resolving after the editor
  * has been created.
  */
-function beginNewProp()
-{
-  let def = promise.defer();
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
+function* focusNewProperty(ruleEditor) {
+  info("Clicking on the close ruleEditor brace to start edition");
+  ruleEditor.closeBrace.scrollIntoView();
+  let editor = yield focusEditableField(ruleEditor.closeBrace);
 
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    is(elementRuleEditor.rule.textProps.length,  0, "Should be starting with one new text property.");
-    is(elementRuleEditor.propertyList.children.length, 1, "Should be starting with two property editors.");
+  is(inplaceEditor(ruleEditor.newPropSpan), editor, "Focused editor is the new property editor.");
+  is(ruleEditor.rule.textProps.length,  0, "Starting with one new text property.");
+  is(ruleEditor.propertyList.children.length, 1, "Starting with two property editors.");
 
-    def.resolve(aEditor);
-  });
-  elementRuleEditor.closeBrace.scrollIntoView();
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
-  return def.promise;
+  return editor;
 }
 
-/*
+/**
  * Fully create a new property, given some text input
  */
-function createNewProp(inputValue)
-{
-  let def = promise.defer();
-  beginNewProp().then((aEditor)=>{
-    aEditor.input.value = inputValue;
+function* createNewProperty(ruleEditor, inputValue) {
+  info("Creating a new property editor");
+  let editor = yield focusNewProperty(ruleEditor);
 
-    waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
-      promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => {
-        def.resolve();
-      }));
-    });
+  info("Entering the value " + inputValue);
+  editor.input.value = inputValue;
 
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
-  });
-
-  return def.promise;
+  info("Submitting the new value and waiting for value field focus");
+  let onFocus = once(ruleEditor.element, "focus", true);
+  EventUtils.synthesizeKey("VK_RETURN", {}, ruleEditor.element.ownerDocument.defaultView);
+  yield onFocus;
 }
 
-function testCreateNewMulti()
-{
-  createNewProp(
-    "color:blue;background : orange   ; text-align:center; border-color: green;"
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 4, "Should have created a new text property.");
-    is(elementRuleEditor.propertyList.children.length, 5, "Should have created a new property editor.");
+function* testCreateNewMulti(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor,
+    "color:blue;background : orange   ; text-align:center; border-color: green;");
 
-    is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "blue", "Should have correct property value");
+  is(ruleEditor.rule.textProps.length, 4, "Should have created a new text property.");
+  is(ruleEditor.propertyList.children.length, 5, "Should have created a new property editor.");
+
+  is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "blue", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[1].name, "background", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
-
-    is(elementRuleEditor.rule.textProps[2].name, "text-align", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[2].value, "center", "Should have correct property value");
+  is(ruleEditor.rule.textProps[1].name, "background", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[3].name, "border-color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[3].value, "green", "Should have correct property value");
+  is(ruleEditor.rule.textProps[2].name, "text-align", "Should have correct property name");
+  is(ruleEditor.rule.textProps[2].value, "center", "Should have correct property value");
 
-    selectNewElement().then(testCreateNewMultiDuplicates);
-  });
+  is(ruleEditor.rule.textProps[3].name, "border-color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[3].value, "green", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testCreateNewMultiDuplicates()
-{
-  createNewProp(
-    "color:red;color:orange;color:yellow;color:green;color:blue;color:indigo;color:violet;"
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 7, "Should have created new text properties.");
-    is(elementRuleEditor.propertyList.children.length, 8, "Should have created new property editors.");
+function* testCreateNewMultiDuplicates(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor,
+    "color:red;color:orange;color:yellow;color:green;color:blue;color:indigo;color:violet;");
 
-    is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "red", "Should have correct property value");
+  is(ruleEditor.rule.textProps.length, 7, "Should have created new text properties.");
+  is(ruleEditor.propertyList.children.length, 8, "Should have created new property editors.");
 
-    is(elementRuleEditor.rule.textProps[1].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
+  is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "red", "Should have correct property value");
+
+  is(ruleEditor.rule.textProps[1].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[2].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[2].value, "yellow", "Should have correct property value");
+  is(ruleEditor.rule.textProps[2].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[2].value, "yellow", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[3].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[3].value, "green", "Should have correct property value");
-
-    is(elementRuleEditor.rule.textProps[4].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[4].value, "blue", "Should have correct property value");
+  is(ruleEditor.rule.textProps[3].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[3].value, "green", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[5].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[5].value, "indigo", "Should have correct property value");
+  is(ruleEditor.rule.textProps[4].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[4].value, "blue", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[6].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[6].value, "violet", "Should have correct property value");
+  is(ruleEditor.rule.textProps[5].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[5].value, "indigo", "Should have correct property value");
 
-    selectNewElement().then(testCreateNewMultiPriority);
-  });
+  is(ruleEditor.rule.textProps[6].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[6].value, "violet", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testCreateNewMultiPriority()
-{
-  createNewProp(
-    "color:red;width:100px;height: 100px;"
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 3, "Should have created new text properties.");
-    is(elementRuleEditor.propertyList.children.length, 4, "Should have created new property editors.");
+function* testCreateNewMultiPriority(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor,
+    "color:red;width:100px;height: 100px;");
+
+  is(ruleEditor.rule.textProps.length, 3, "Should have created new text properties.");
+  is(ruleEditor.propertyList.children.length, 4, "Should have created new property editors.");
 
-    is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "red", "Should have correct property value");
-
-    is(elementRuleEditor.rule.textProps[1].name, "width", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "100px", "Should have correct property value");
+  is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "red", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[2].name, "height", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[2].value, "100px", "Should have correct property value");
+  is(ruleEditor.rule.textProps[1].name, "width", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "100px", "Should have correct property value");
 
-    selectNewElement().then(testCreateNewMultiUnfinished);
-  });
+  is(ruleEditor.rule.textProps[2].name, "height", "Should have correct property name");
+  is(ruleEditor.rule.textProps[2].value, "100px", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testCreateNewMultiUnfinished()
-{
-  createNewProp(
-    "color:blue;background : orange   ; text-align:center; border-color: "
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 4, "Should have created new text properties.");
-    is(elementRuleEditor.propertyList.children.length, 4, "Should have created property editors.");
+function* testCreateNewMultiUnfinished(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor,
+    "color:blue;background : orange   ; text-align:center; border-color: ");
 
-    for (let ch of "red") {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
+  is(ruleEditor.rule.textProps.length, 4, "Should have created new text properties.");
+  is(ruleEditor.propertyList.children.length, 4, "Should have created property editors.");
+
+  for (let ch of "red") {
+    EventUtils.sendChar(ch, view.doc.defaultView);
+  }
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
-    is(elementRuleEditor.rule.textProps.length, 4, "Should have the same number of text properties.");
-    is(elementRuleEditor.propertyList.children.length, 5, "Should have added the changed value editor.");
+  is(ruleEditor.rule.textProps.length, 4, "Should have the same number of text properties.");
+  is(ruleEditor.propertyList.children.length, 5, "Should have added the changed value editor.");
 
-    is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "blue", "Should have correct property value");
-
-    is(elementRuleEditor.rule.textProps[1].name, "background", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
+  is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "blue", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[2].name, "text-align", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[2].value, "center", "Should have correct property value");
+  is(ruleEditor.rule.textProps[1].name, "background", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[3].name, "border-color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[3].value, "red", "Should have correct property value");
+  is(ruleEditor.rule.textProps[2].name, "text-align", "Should have correct property name");
+  is(ruleEditor.rule.textProps[2].value, "center", "Should have correct property value");
 
-    selectNewElement().then(testCreateNewMultiPartialUnfinished);
-  });
+  is(ruleEditor.rule.textProps[3].name, "border-color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[3].value, "red", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
 
+function* testCreateNewMultiPartialUnfinished(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor, "width: 100px; heig");
 
-function testCreateNewMultiPartialUnfinished()
-{
-  createNewProp(
-    "width: 100px; heig"
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 2, "Should have created a new text property.");
-    is(elementRuleEditor.propertyList.children.length, 2, "Should have created a property editor.");
+  is(ruleEditor.rule.textProps.length, 2, "Should have created a new text property.");
+  is(ruleEditor.propertyList.children.length, 2, "Should have created a property editor.");
 
-    // Value is focused, lets add multiple rules here and make sure they get added
-    let valueEditor = elementRuleEditor.propertyList.children[1].querySelector("input");
-    valueEditor.value = "10px;background:orangered;color: black;";
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
+  // Value is focused, lets add multiple rules here and make sure they get added
+  let valueEditor = ruleEditor.propertyList.children[1].querySelector("input");
+  valueEditor.value = "10px;background:orangered;color: black;";
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
-    is(elementRuleEditor.rule.textProps.length, 4, "Should have added the changed value.");
-    is(elementRuleEditor.propertyList.children.length, 5, "Should have added the changed value editor.");
+  is(ruleEditor.rule.textProps.length, 4, "Should have added the changed value.");
+  is(ruleEditor.propertyList.children.length, 5, "Should have added the changed value editor.");
 
-    is(elementRuleEditor.rule.textProps[0].name, "width", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "100px", "Should have correct property value");
-
-    is(elementRuleEditor.rule.textProps[1].name, "heig", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "10px", "Should have correct property value");
+  is(ruleEditor.rule.textProps[0].name, "width", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "100px", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[2].name, "background", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[2].value, "orangered", "Should have correct property value");
+  is(ruleEditor.rule.textProps[1].name, "heig", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "10px", "Should have correct property value");
 
-    is(elementRuleEditor.rule.textProps[3].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[3].value, "black", "Should have correct property value");
+  is(ruleEditor.rule.textProps[2].name, "background", "Should have correct property name");
+  is(ruleEditor.rule.textProps[2].value, "orangered", "Should have correct property value");
 
-    selectNewElement().then(testMultiValues);
-  });
+  is(ruleEditor.rule.textProps[3].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[3].value, "black", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
 
-function testMultiValues()
-{
-  createNewProp(
-    "width:"
-  ).then(()=>{
-    is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property.");
-    is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
+function* testMultiValues(inspector, view) {
+  let ruleEditor = yield createAndSelectNewElement(inspector, view);
+  yield createNewProperty(ruleEditor, "width:");
 
-    // Value is focused, lets add multiple rules here and make sure they get added
-    let valueEditor = elementRuleEditor.propertyList.children[0].querySelector("input");
-    valueEditor.value = "height: 10px;color:blue"
-    EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow);
+  is(ruleEditor.rule.textProps.length, 1, "Should have created a new text property.");
+  is(ruleEditor.propertyList.children.length, 1, "Should have created a property editor.");
 
-    is(elementRuleEditor.rule.textProps.length, 2, "Should have added the changed value.");
-    is(elementRuleEditor.propertyList.children.length, 3, "Should have added the changed value editor.");
-
-    EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow);
-    is(elementRuleEditor.propertyList.children.length, 2, "Should have removed the value editor.");
-
-    is(elementRuleEditor.rule.textProps[0].name, "width", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[0].value, "height: 10px", "Should have correct property value");
+  // Value is focused, lets add multiple rules here and make sure they get added
+  let valueEditor = ruleEditor.propertyList.children[0].querySelector("input");
+  valueEditor.value = "height: 10px;color:blue"
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView);
 
-    is(elementRuleEditor.rule.textProps[1].name, "color", "Should have correct property name");
-    is(elementRuleEditor.rule.textProps[1].value, "blue", "Should have correct property value");
+  is(ruleEditor.rule.textProps.length, 2, "Should have added the changed value.");
+  is(ruleEditor.propertyList.children.length, 3, "Should have added the changed value editor.");
+
+  EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView);
+  is(ruleEditor.propertyList.children.length, 2, "Should have removed the value editor.");
 
-    finishTest();
-  });
-}
+  is(ruleEditor.rule.textProps[0].name, "width", "Should have correct property name");
+  is(ruleEditor.rule.textProps[0].value, "height: 10px", "Should have correct property value");
 
-function finishTest()
-{
-  inspector = ruleWindow = ruleView = doc = elementRuleEditor = null;
-  gBrowser.removeCurrentTab();
-  finish();
+  is(ruleEditor.rule.textProps[1].name, "color", "Should have correct property name");
+  is(ruleEditor.rule.textProps[1].value, "blue", "Should have correct property value");
+
+  yield inspector.once("inspector-updated");
 }
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true);
-    doc = content.document;
-    waitForFocus(startTest, content);
-  }, true);
-
-  content.location = "data:text/html,test rule view user changes";
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js
@@ -1,131 +1,84 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
-let win;
-let doc;
-let contentWindow;
-let inspector;
-let toolbox;
+"use strict";
 
-const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps.html";
+// Test that the stylesheet links in the rule view are correct when source maps
+// are involved
+
+const TESTCASE_URI = TEST_URL_ROOT + "sourcemaps.html";
 const PREF = "devtools.styleeditor.source-maps-enabled";
-
 const SCSS_LOC = "sourcemaps.scss:4";
 const CSS_LOC = "sourcemaps.css:1";
 
-function test()
-{
-  waitForExplicitFinish();
-
+let test = asyncTest(function*() {
+  info("Setting the " + PREF +  " pref to true");
   Services.prefs.setBoolPref(PREF, true);
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
-      true);
-    doc = content.document;
-    waitForFocus(openToolbox, content);
-  }, true);
+  info("Opening the test page and opening the inspector");
+  yield addTab(TESTCASE_URI);
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  info("Selecting the test node");
+  yield selectNode("div", inspector);
+
+  yield verifyLinkText(SCSS_LOC, view);
+
+  info("Setting the " + PREF + " pref to false");
+  Services.prefs.setBoolPref(PREF, false);
+  yield verifyLinkText(CSS_LOC, view);
+
+  info("Setting the " + PREF + " pref to true again");
+  Services.prefs.setBoolPref(PREF, true);
 
-  content.location = TESTCASE_URI;
-}
+  yield testClickingLink(toolbox, view);
+  yield checkDisplayedStylesheet(toolbox);
 
-function openToolbox() {
-  let target = TargetFactory.forTab(gBrowser.selectedTab);
+  info("Clearing the " + PREF + " pref");
+  Services.prefs.clearUserPref(PREF);
+});
 
-  gDevTools.showToolbox(target, "inspector").then(function(aToolbox) {
-    toolbox = aToolbox;
-    inspector = toolbox.getCurrentPanel();
-    inspector.sidebar.select("ruleview");
-    highlightNode();
-  });
+function* testClickingLink(toolbox, view) {
+  info("Listening for switch to the style editor");
+  let onStyleEditorReady = toolbox.once("styleeditor-ready");
+
+  info("Finding the stylesheet link and clicking it");
+  let link = getRuleViewLinkByIndex(view, 1);
+  link.scrollIntoView();
+  link.click();
+  yield onStyleEditorReady;
 }
 
-function highlightNode()
-{
-  // Highlight a node.
-  let div = content.document.getElementsByTagName("div")[0];
-
-  inspector.selection.setNode(div, "test");
-  inspector.once("inspector-updated", () => {
-    is(inspector.selection.node, div, "selection matches the div element");
-    testRuleViewLink();
-  });
-}
-
-function testRuleViewLink() {
-  verifyLinkText(SCSS_LOC, testTogglePref);
-}
-
-function testTogglePref() {
-  Services.prefs.setBoolPref(PREF, false);
+function checkDisplayedStylesheet(toolbox) {
+  let def = promise.defer();
 
-  verifyLinkText(CSS_LOC, () => {
-    Services.prefs.setBoolPref(PREF, true);
-
-    testClickingLink();
-  })
-}
-
-function testClickingLink() {
-  toolbox.once("styleeditor-ready", function(id, aToolbox) {
-    let panel = toolbox.getCurrentPanel();
-    panel.UI.on("editor-selected", (event, editor) => {
-      // The style editor selects the first sheet at first load before
-      // selecting the desired sheet.
-      if (editor.styleSheet.href.endsWith("scss")) {
-        info("original source editor selected");
-        editor.getSourceEditor().then(editorSelected);
-      }
-    });
+  let panel = toolbox.getCurrentPanel();
+  panel.UI.on("editor-selected", (event, editor) => {
+    // The style editor selects the first sheet at first load before
+    // selecting the desired sheet.
+    if (editor.styleSheet.href.endsWith("scss")) {
+      info("Original source editor selected");
+      editor.getSourceEditor().then(editorSelected).then(def.resolve, def.reject);
+    }
   });
 
-  let link = getLinkByIndex(1);
-
-  info("clicking rule view link");
-  link.scrollIntoView();
-  link.click();
+  return def.promise;
 }
 
 function editorSelected(editor) {
   let href = editor.styleSheet.href;
   ok(href.endsWith("sourcemaps.scss"), "selected stylesheet is correct one");
 
   let {line, col} = editor.sourceEditor.getCursor();
   is(line, 3, "cursor is at correct line number in original source");
-
-  finishUp();
 }
 
-/* Helpers */
-
-function verifyLinkText(text, callback) {
-  let label = getLinkByIndex(1).querySelector("label");
-
-  waitForSuccess({
-    name: "link text changed to display correct location: " + text,
-    validatorFn: function()
-    {
-      return label.getAttribute("value") == text;
-    },
-    successFn: callback,
-    failureFn: callback,
-  });
+function verifyLinkText(text, view) {
+  info("Verifying that the rule-view stylesheet link is " + text);
+  let label = getRuleViewLinkByIndex(view, 1).querySelector("label");
+  return waitForSuccess(
+    () => label.getAttribute("value") == text,
+    "Link text changed to display correct location: " + text
+  );
 }
-
-function getLinkByIndex(aIndex)
-{
-  let contentDoc = ruleView().doc;
-  contentWindow = contentDoc.defaultView;
-  let links = contentDoc.querySelectorAll(".ruleview-rule-source");
-  return links[aIndex];
-}
-
-function finishUp()
-{
-  gBrowser.removeCurrentTab();
-  contentWindow = doc = inspector = toolbox = win = null;
-  Services.prefs.clearUserPref(PREF);
-  finish();
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_override.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_override.js
@@ -1,182 +1,146 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test the display of overridden declarations in the rule-view
+
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,browser_ruleview_override.js");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-let doc;
-let inspector;
-let view;
+  yield simpleOverride(inspector, view);
+  yield partialOverride(inspector, view);
+  yield importantOverride(inspector, view);
+  yield disableOverride(inspector, view);
+});
 
-function simpleOverride(aInspector, aRuleView)
-{
-  inspector = aInspector;
-  view = aRuleView;
-  let style = '' +
+function* createTestContent(inspector, style) {
+  let onMutated = inspector.once("markupmutation");
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
+  yield onMutated;
+  yield selectNode("#testid", inspector);
+  return styleNode;
+}
+
+function* simpleOverride(inspector, view) {
+  let styleNode = yield createTestContent(inspector, '' +
     '#testid {' +
     '  background-color: blue;' +
     '} ' +
     '.testclass {' +
     '  background-color: green;' +
-    '}';
+    '}');
+
+  let elementStyle = view._elementStyle;
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
-  inspector.once("markupmutation", () => {
-    inspector.selection.setNode(doc.getElementById("testid"));
-    inspector.once("inspector-updated", () => {
-      let elementStyle = view._elementStyle;
-
-      let idRule = elementStyle.rules[1];
-      let idProp = idRule.textProps[0];
-      is(idProp.name, "background-color", "First ID prop should be background-color");
-      ok(!idProp.overridden, "ID prop should not be overridden.");
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
+  is(idProp.name, "background-color", "First ID prop should be background-color");
+  ok(!idProp.overridden, "ID prop should not be overridden.");
 
-      let classRule = elementStyle.rules[2];
-      let classProp = classRule.textProps[0];
-      is(classProp.name, "background-color", "First class prop should be background-color");
-      ok(classProp.overridden, "Class property should be overridden.");
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  is(classProp.name, "background-color", "First class prop should be background-color");
+  ok(classProp.overridden, "Class property should be overridden.");
 
-      // Override background-color by changing the element style.
-      let elementRule = elementStyle.rules[0];
-      elementRule.createProperty("background-color", "purple", "");
-      promiseDone(elementRule._applyingModifications.then(() => {
-        let elementProp = elementRule.textProps[0];
-        is(classProp.name, "background-color", "First element prop should now be background-color");
-        ok(!elementProp.overridden, "Element style property should not be overridden");
-        ok(idProp.overridden, "ID property should be overridden");
-        ok(classProp.overridden, "Class property should be overridden");
+  // Override background-color by changing the element style.
+  let elementRule = elementStyle.rules[0];
+  elementRule.createProperty("background-color", "purple", "");
+  yield elementRule._applyingModifications;
 
-        styleNode.parentNode.removeChild(styleNode);
-        partialOverride();
-      }));
-    });
-  });
+  let elementProp = elementRule.textProps[0];
+  is(classProp.name, "background-color", "First element prop should now be background-color");
+  ok(!elementProp.overridden, "Element style property should not be overridden");
+  ok(idProp.overridden, "ID property should be overridden");
+  ok(classProp.overridden, "Class property should be overridden");
+
+  styleNode.remove();
 }
 
-function partialOverride()
-{
-  let style = '' +
+function* partialOverride(inspector, view) {
+  let styleNode = yield createTestContent(inspector, '' +
     // Margin shorthand property...
     '.testclass {' +
     '  margin: 2px;' +
     '}' +
     // ... will be partially overridden.
     '#testid {' +
     '  margin-left: 1px;' +
-    '}';
+    '}');
+
+  let elementStyle = view._elementStyle;
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
-  inspector.once("markupmutation", () => {
-    inspector.selection.setNode(doc.getElementById("testid"));
-    inspector.once("inspector-updated", () => {
-      let elementStyle = view._elementStyle;
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  ok(!classProp.overridden,
+    "Class prop shouldn't be overridden, some props are still being used.");
 
-      let classRule = elementStyle.rules[2];
-      let classProp = classRule.textProps[0];
-      ok(!classProp.overridden, "Class prop shouldn't be overridden, some props are still being used.");
-      for (let computed of classProp.computed) {
-        if (computed.name.indexOf("margin-left") == 0) {
-          ok(computed.overridden, "margin-left props should be overridden.");
-        } else {
-          ok(!computed.overridden, "Non-margin-left props should not be overridden.");
-        }
-      }
+  for (let computed of classProp.computed) {
+    if (computed.name.indexOf("margin-left") == 0) {
+      ok(computed.overridden, "margin-left props should be overridden.");
+    } else {
+      ok(!computed.overridden, "Non-margin-left props should not be overridden.");
+    }
+  }
 
-      styleNode.parentNode.removeChild(styleNode);
-
-      importantOverride();
-    });
-  });
+  styleNode.remove();
 }
 
-function importantOverride()
-{
-  let style = '' +
+function* importantOverride(inspector, view) {
+  let styleNode = yield createTestContent(inspector, '' +
     // Margin shorthand property...
     '.testclass {' +
     '  background-color: green !important;' +
     '}' +
     // ... will be partially overridden.
     '#testid {' +
     '  background-color: blue;' +
-    '}';
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
-  inspector.once("markupmutation", () => {
-    inspector.selection.setNode(doc.getElementById("testid"));
-    inspector.once("inspector-updated", () => {
-      let elementStyle = view._elementStyle;
+    '}');
+
+  let elementStyle = view._elementStyle;
 
-      let idRule = elementStyle.rules[1];
-      let idProp = idRule.textProps[0];
-      ok(idProp.overridden, "Not-important rule should be overridden.");
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
+  ok(idProp.overridden, "Not-important rule should be overridden.");
 
-      let classRule = elementStyle.rules[2];
-      let classProp = classRule.textProps[0];
-      ok(!classProp.overridden, "Important rule should not be overridden.");
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  ok(!classProp.overridden, "Important rule should not be overridden.");
 
-      styleNode.parentNode.removeChild(styleNode);
+  styleNode.remove();
 
-      let elementRule = elementStyle.rules[0];
-      let elementProp = elementRule.createProperty("background-color", "purple", "important");
-      promiseDone(elementRule._applyingModifications.then(() => {
-        ok(classProp.overridden, "New important prop should override class property.");
-        ok(!elementProp.overridden, "New important prop should not be overriden.");
+  let elementRule = elementStyle.rules[0];
+  let elementProp = elementRule.createProperty("background-color", "purple", "important");
+  yield elementRule._applyingModifications;
 
-        disableOverride();
-      }));
-    });
-  });
+  ok(classProp.overridden, "New important prop should override class property.");
+  ok(!elementProp.overridden, "New important prop should not be overriden.");
 }
 
-function disableOverride()
-{
-  let style = '' +
+function* disableOverride(inspector, view) {
+  let styleNode = yield createTestContent(inspector, '' +
     '#testid {' +
     '  background-color: blue;' +
     '}' +
     '.testclass {' +
     '  background-color: green;' +
-    '}';
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
-  inspector.once("markupmutation", () => {
-    inspector.selection.setNode(doc.getElementById("testid"));
-    inspector.once("inspector-updated", () => {
-      let elementStyle = view._elementStyle;
+    '}');
 
-      let idRule = elementStyle.rules[1];
-      let idProp = idRule.textProps[0];
-      idProp.setEnabled(false);
-      promiseDone(idRule._applyingModifications.then(() => {
-        let classRule = elementStyle.rules[2];
-        let classProp = classRule.textProps[0];
-        ok(!classProp.overridden, "Class prop should not be overridden after id prop was disabled.");
+  let elementStyle = view._elementStyle;
 
-        styleNode.parentNode.removeChild(styleNode);
+  let idRule = elementStyle.rules[1];
+  let idProp = idRule.textProps[0];
 
-        finishTest();
-      }));
-    });
-  });
-}
-
-function finishTest()
-{
-  doc = inspector = view = null;
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  idProp.setEnabled(false);
+  yield idRule._applyingModifications;
 
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(() => openRuleView(simpleOverride), content);
-  }, true);
+  let classRule = elementStyle.rules[2];
+  let classProp = classRule.textProps[0];
+  ok(!classProp.overridden, "Class prop should not be overridden after id prop was disabled.");
 
-  content.location = "data:text/html;charset=utf-8,browser_ruleview_override.js";
+  styleNode.remove();
+  yield inspector.once("inspector-updated");
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js
@@ -1,320 +1,273 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_URI = TEST_URL_ROOT + "browser_ruleview_pseudoelement.html";
+
+let test = asyncTest(function*() {
+  yield addTab(TEST_URI);
+  let {toolbox, inspector, view} = yield openRuleView();
+
+  yield testTopLeft(inspector, view);
+  yield testTopRight(inspector, view);
+  yield testBottomRight(inspector, view);
+  yield testBottomLeft(inspector, view);
+  yield testParagraph(inspector, view);
+  yield testBody(inspector, view);
+});
 
-let doc;
-let inspector;
-let view;
+function* testTopLeft(inspector, view) {
+  let {
+    rules,
+    element,
+    elementStyle
+  } = yield assertPseudoElementRulesNumbers("#topleft", inspector, view, {
+    elementRulesNb: 4,
+    afterRulesNb: 1,
+    beforeRulesNb: 2,
+    firstLineRulesNb: 0,
+    firstLetterRulesNb: 0,
+    selectionRulesNb: 0
+  });
+
+  let gutters = assertGutters(view);
+
+  // Make sure that clicking on the twisty hides pseudo elements
+  let expander = gutters[0].querySelector(".ruleview-expander");
+  ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded");
+  expander.click();
+  ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty");
+  expander.click();
+  ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again");
+
+  // Make sure that dblclicking on the header container also toggles the pseudo elements
+  EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview"));
+  ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking");
+
+  let defaultView = element.ownerDocument.defaultView;
+  let elementRule = rules.elementRules[0];
+  let elementRuleView = [].filter.call(view.element.children, e => {
+    return e._ruleEditor && e._ruleEditor.rule === elementRule;
+  })[0]._ruleEditor;
+
+  let elementAfterRule = rules.afterRules[0];
+  let elementAfterRuleView = [].filter.call(view.element.children, (e) => {
+    return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
+  })[0]._ruleEditor;
 
-const TEST_URI = "http://example.com/browser/browser/" +
-                 "devtools/styleinspector/test/" +
-                 "browser_ruleview_pseudoelement.html";
+  is
+  (
+    convertTextPropsToString(elementAfterRule.textProps),
+    "background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " +
+    "border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px",
+    "TopLeft after properties are correct"
+  );
+
+  let elementBeforeRule = rules.beforeRules[0];
+  let elementBeforeRuleView = [].filter.call(view.element.children, (e) => {
+    return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
+  })[0]._ruleEditor;
+
+  is
+  (
+    convertTextPropsToString(elementBeforeRule.textProps),
+    "top: 0px; left: 0px",
+    "TopLeft before properties are correct"
+  );
+
+  let firstProp = elementAfterRuleView.addProperty("background-color", "rgb(0, 255, 0)", "");
+  let secondProp = elementAfterRuleView.addProperty("padding", "100px", "");
+
+  is (firstProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 2],
+      "First added property is on back of array");
+  is (secondProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 1],
+      "Second added property is on back of array");
+
+  yield elementAfterRule._applyingModifications;
 
-function testPseudoElements(aInspector, aRuleView)
-{
-  inspector = aInspector;
-  view = aRuleView;
+  is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"),
+    "rgb(0, 255, 0)", "Added property should have been used.");
+  is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"),
+    "100px", "Added property should have been used.");
+  is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"),
+    "32px", "Added property should not apply to element");
+
+  secondProp.setEnabled(false);
+  yield elementAfterRule._applyingModifications;
+
+  is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "0px",
+    "Disabled property should have been used.");
+  is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px",
+    "Added property should not apply to element");
 
-  testTopLeft();
+  secondProp.setEnabled(true);
+  yield elementAfterRule._applyingModifications;
+
+  is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "100px",
+    "Enabled property should have been used.");
+  is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px",
+    "Added property should not apply to element");
+
+  let firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", "");
+  yield elementRule._applyingModifications;
+
+  is(defaultView.getComputedStyle(element).getPropertyValue("background-color"), "rgb(0, 0, 255)",
+    "Added property should have been used.");
+  is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), "rgb(0, 255, 0)",
+    "Added prop does not apply to pseudo");
 }
 
-function testTopLeft()
-{
-  testNode(doc.querySelector("#topleft"), (element, elementStyle) => {
-    let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; });
-    let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; });
-    let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; });
-    let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; });
-    let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; });
-    let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; });
-
-    is(elementRules.length, 4, "TopLeft has the correct number of non psuedo element rules");
-    is(afterRules.length, 1, "TopLeft has the correct number of :after rules");
-    is(beforeRules.length, 2, "TopLeft has the correct number of :before rules");
-    is(firstLineRules.length, 0, "TopLeft has the correct number of :first-line rules");
-    is(firstLetterRules.length, 0, "TopLeft has the correct number of :first-letter rules");
-    is(selectionRules.length, 0, "TopLeft has the correct number of :selection rules");
-
-    let gutters = view.element.querySelectorAll(".theme-gutter");
-    is (gutters.length, 3, "There are three gutter headings");
-    is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
-    is (gutters[1].textContent, "This Element", "Gutter heading is correct");
-    is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
+function* testTopRight(inspector, view) {
+  let {
+    rules,
+    element,
+    elementStyle
+  } = yield assertPseudoElementRulesNumbers("#topright", inspector, view, {
+    elementRulesNb: 4,
+    afterRulesNb: 1,
+    beforeRulesNb: 2,
+    firstLineRulesNb: 0,
+    firstLetterRulesNb: 0,
+    selectionRulesNb: 0
+  });
 
-    // Make sure that clicking on the twisty hides pseudo elements
-    let expander = gutters[0].querySelector(".ruleview-expander");
-    ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded");
-    expander.click();
-    ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty");
-    expander.click();
-    ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again");
-
-    // Make sure that dblclicking on the header container also toggles the pseudo elements
-    EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview"));
-    ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking");
-
-    let defaultView = element.ownerDocument.defaultView;
-    let elementRule = elementRules[0];
-    let elementRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementRule;
-    })[0]._ruleEditor;
-
-    let elementAfterRule = afterRules[0];
-    let elementAfterRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementAfterRule;
-    })[0]._ruleEditor;
-
-    is
-    (
-      convertTextPropsToString(elementAfterRule.textProps),
-      "background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " +
-      "border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px",
-      "TopLeft after properties are correct"
-    );
+  let gutters = assertGutters(view);
 
-    let elementBeforeRule = beforeRules[0];
-    let elementBeforeRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule;
-    })[0]._ruleEditor;
-
-    is
-    (
-      convertTextPropsToString(elementBeforeRule.textProps),
-      "top: 0px; left: 0px",
-      "TopLeft before properties are correct"
-    );
-
-    let firstProp = elementAfterRuleView.addProperty("background-color", "rgb(0, 255, 0)", "");
-    let secondProp = elementAfterRuleView.addProperty("padding", "100px", "");
-
-    is (firstProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 2],
-        "First added property is on back of array");
-    is (secondProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 1],
-        "Second added property is on back of array");
-
-    promiseDone(elementAfterRule._applyingModifications.then(() => {
-      is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"),
-        "rgb(0, 255, 0)", "Added property should have been used.");
-      is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"),
-        "100px", "Added property should have been used.");
-      is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"),
-        "32px", "Added property should not apply to element");
+  let expander = gutters[0].querySelector(".ruleview-expander");
+  ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements remain collapsed after switching element");
+  expander.scrollIntoView();
+  expander.click();
+  ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are shown again after clicking twisty");
+}
 
-      secondProp.setEnabled(false);
-
-      return elementAfterRule._applyingModifications;
-    }).then(() => {
-      is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "0px",
-        "Disabled property should have been used.");
-      is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px",
-        "Added property should not apply to element");
-
-      secondProp.setEnabled(true);
-
-      return elementAfterRule._applyingModifications;
-    }).then(() => {
-      is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "100px",
-        "Enabled property should have been used.");
-      is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px",
-        "Added property should not apply to element");
-
-      let firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", "");
-
-      return elementRule._applyingModifications;
-    }).then(() => {
-      is(defaultView.getComputedStyle(element).getPropertyValue("background-color"), "rgb(0, 0, 255)",
-        "Added property should have been used.");
-      is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), "rgb(0, 255, 0)",
-        "Added prop does not apply to pseudo");
-
-      testTopRight();
-    }));
+function* testBottomRight(inspector, view) {
+  yield assertPseudoElementRulesNumbers("#bottomright", inspector, view, {
+    elementRulesNb: 4,
+    afterRulesNb: 1,
+    beforeRulesNb: 3,
+    firstLineRulesNb: 0,
+    firstLetterRulesNb: 0,
+    selectionRulesNb: 0
   });
 }
 
-function testTopRight()
-{
-  testNode(doc.querySelector("#topright"), (element, elementStyle) => {
-
-    let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; });
-    let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; });
-    let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; });
-    let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; });
-    let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; });
-    let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; });
-
-    is(elementRules.length, 4, "TopRight has the correct number of non psuedo element rules");
-    is(afterRules.length, 1, "TopRight has the correct number of :after rules");
-    is(beforeRules.length, 2, "TopRight has the correct number of :before rules");
-    is(firstLineRules.length, 0, "TopRight has the correct number of :first-line rules");
-    is(firstLetterRules.length, 0, "TopRight has the correct number of :first-letter rules");
-    is(selectionRules.length, 0, "TopRight has the correct number of :selection rules");
-
-    let gutters = view.element.querySelectorAll(".theme-gutter");
-    is (gutters.length, 3, "There are three gutter headings");
-    is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
-    is (gutters[1].textContent, "This Element", "Gutter heading is correct");
-    is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
-
-    let expander = gutters[0].querySelector(".ruleview-expander");
-    ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements remain collapsed after switching element");
-    expander.scrollIntoView();
-    expander.click();
-    ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are shown again after clicking twisty");
-
-    testBottomRight();
-  });
-}
-
-function testBottomRight()
-{
-  testNode(doc.querySelector("#bottomright"), (element, elementStyle) => {
-
-    let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; });
-    let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; });
-    let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; });
-    let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; });
-    let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; });
-    let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; });
-
-    is(elementRules.length, 4, "BottomRight has the correct number of non psuedo element rules");
-    is(afterRules.length, 1, "BottomRight has the correct number of :after rules");
-    is(beforeRules.length, 3, "BottomRight has the correct number of :before rules");
-    is(firstLineRules.length, 0, "BottomRight has the correct number of :first-line rules");
-    is(firstLetterRules.length, 0, "BottomRight has the correct number of :first-letter rules");
-    is(selectionRules.length, 0, "BottomRight has the correct number of :selection rules");
-
-    testBottomLeft();
-  });
-}
-
-function testBottomLeft()
-{
-  testNode(doc.querySelector("#bottomleft"), (element, elementStyle) => {
-
-    let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; });
-    let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; });
-    let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; });
-    let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; });
-    let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; });
-    let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; });
-
-    is(elementRules.length, 4, "BottomLeft has the correct number of non psuedo element rules");
-    is(afterRules.length, 1, "BottomLeft has the correct number of :after rules");
-    is(beforeRules.length, 2, "BottomLeft has the correct number of :before rules");
-    is(firstLineRules.length, 0, "BottomLeft has the correct number of :first-line rules");
-    is(firstLetterRules.length, 0, "BottomLeft has the correct number of :first-letter rules");
-    is(selectionRules.length, 0, "BottomLeft has the correct number of :selection rules");
-
-    testParagraph();
+function* testBottomLeft(inspector, view) {
+  yield assertPseudoElementRulesNumbers("#bottomleft", inspector, view, {
+    elementRulesNb: 4,
+    afterRulesNb: 1,
+    beforeRulesNb: 2,
+    firstLineRulesNb: 0,
+    firstLetterRulesNb: 0,
+    selectionRulesNb: 0
   });
 }
 
-function testParagraph()
-{
-  testNode(doc.querySelector("#bottomleft p"), (element, elementStyle) => {
-
-    let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; });
-    let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; });
-    let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; });
-    let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; });
-    let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; });
-    let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; });
+function* testParagraph(inspector, view) {
+  let {
+    rules,
+    element,
+    elementStyle
+  } = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
+    elementRulesNb: 3,
+    afterRulesNb: 0,
+    beforeRulesNb: 0,
+    firstLineRulesNb: 1,
+    firstLetterRulesNb: 1,
+    selectionRulesNb: 1
+  });
 
-    is(elementRules.length, 3, "Paragraph has the correct number of non psuedo element rules");
-    is(afterRules.length, 0, "Paragraph has the correct number of :after rules");
-    is(beforeRules.length, 0, "Paragraph has the correct number of :before rules");
-    is(firstLineRules.length, 1, "Paragraph has the correct number of :first-line rules");
-    is(firstLetterRules.length, 1, "Paragraph has the correct number of :first-letter rules");
-    is(selectionRules.length, 1, "Paragraph has the correct number of :selection rules");
+  let gutters = assertGutters(view);
 
-    let gutters = view.element.querySelectorAll(".theme-gutter");
-    is (gutters.length, 3, "There are three gutter headings");
-    is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
-    is (gutters[1].textContent, "This Element", "Gutter heading is correct");
-    is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
-
-    let elementFirstLineRule = firstLineRules[0];
-    let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
-    })[0]._ruleEditor;
+  let elementFirstLineRule = rules.firstLineRules[0];
+  let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => {
+    return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule;
+  })[0]._ruleEditor;
 
-    is
-    (
-      convertTextPropsToString(elementFirstLineRule.textProps),
-      "background: none repeat scroll 0% 0% blue",
-      "Paragraph first-line properties are correct"
-    );
+  is
+  (
+    convertTextPropsToString(elementFirstLineRule.textProps),
+    "background: none repeat scroll 0% 0% blue",
+    "Paragraph first-line properties are correct"
+  );
 
-    let elementFirstLetterRule = firstLetterRules[0];
-    let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule;
-    })[0]._ruleEditor;
+  let elementFirstLetterRule = rules.firstLetterRules[0];
+  let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => {
+    return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule;
+  })[0]._ruleEditor;
 
-    is
-    (
-      convertTextPropsToString(elementFirstLetterRule.textProps),
-      "color: red; font-size: 130%",
-      "Paragraph first-letter properties are correct"
-    );
+  is
+  (
+    convertTextPropsToString(elementFirstLetterRule.textProps),
+    "color: red; font-size: 130%",
+    "Paragraph first-letter properties are correct"
+  );
 
-    let elementSelectionRule = selectionRules[0];
-    let elementSelectionRuleView = [].filter.call(view.element.children, (e) => {
-      return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule;
-    })[0]._ruleEditor;
+  let elementSelectionRule = rules.selectionRules[0];
+  let elementSelectionRuleView = [].filter.call(view.element.children, (e) => {
+    return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule;
+  })[0]._ruleEditor;
 
-    is
-    (
-      convertTextPropsToString(elementSelectionRule.textProps),
-      "color: white; background: none repeat scroll 0% 0% black",
-      "Paragraph first-letter properties are correct"
-    );
-
-    testBody();
-  });
+  is
+  (
+    convertTextPropsToString(elementSelectionRule.textProps),
+    "color: white; background: none repeat scroll 0% 0% black",
+    "Paragraph first-letter properties are correct"
+  );
 }
 
-function testBody() {
+function* testBody(inspector, view) {
+  let {element, elementStyle} = yield testNode("body", inspector, view);
 
-  testNode(doc.querySelector("body"), (element, elementStyle) => {
-
-    let gutters = view.element.querySelectorAll(".theme-gutter");
-    is (gutters.length, 0, "There are no gutter headings");
+  let gutters = view.element.querySelectorAll(".theme-gutter");
+  is (gutters.length, 0, "There are no gutter headings");
+}
 
-    finishTest();
-  });
-
+function convertTextPropsToString(textProps) {
+  return textProps.map(t => t.name + ": " + t.value).join("; ");
 }
-function convertTextPropsToString(textProps) {
-  return textProps.map((t) => {
-    return t.name + ": " + t.value;
-  }).join("; ");
+
+function* testNode(selector, inspector, view) {
+  let element = getNode(selector);
+  yield selectNode(element, inspector);
+  let elementStyle = view._elementStyle;
+  return {element: element, elementStyle: elementStyle};
 }
 
-function testNode(node, cb)
-{
-  inspector.once("inspector-updated", () => {
-    cb(node, view._elementStyle)
-  });
-  inspector.selection.setNode(node);
+function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
+  let {element, elementStyle} = yield testNode(selector, inspector, view);
+
+  let rules = {
+    elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement),
+    afterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":after"),
+    beforeRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":before"),
+    firstLineRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-line"),
+    firstLetterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-letter"),
+    selectionRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":-moz-selection")
+  };
+
+  is(rules.elementRules.length, ruleNbs.elementRulesNb, selector +
+    " has the correct number of non pseudo element rules");
+  is(rules.afterRules.length, ruleNbs.afterRulesNb, selector +
+    " has the correct number of :after rules");
+  is(rules.beforeRules.length, ruleNbs.beforeRulesNb, selector +
+    " has the correct number of :before rules");
+  is(rules.firstLineRules.length, ruleNbs.firstLineRulesNb, selector +
+    " has the correct number of :first-line rules");
+  is(rules.firstLetterRules.length, ruleNbs.firstLetterRulesNb, selector +
+    " has the correct number of :first-letter rules");
+  is(rules.selectionRules.length, ruleNbs.selectionRulesNb, selector +
+    " has the correct number of :selection rules");
+
+  return {rules: rules, element: element, elementStyle: elementStyle};
 }
 
-function finishTest()
-{
-  doc = inspector = view = null;
-  gBrowser.removeCurrentTab();
-  finish();
+function assertGutters(view) {
+  let gutters = view.element.querySelectorAll(".theme-gutter");
+  is (gutters.length, 3, "There are 3 gutter headings");
+  is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct");
+  is (gutters[1].textContent, "This Element", "Gutter heading is correct");
+  is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct");
+  return gutters;
 }
-
-function test()
-{
-  waitForExplicitFinish();
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function(evt) {
-    gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
-    doc = content.document;
-    waitForFocus(() => openRuleView(testPseudoElements), content);
-  }, true);
-
-  content.location = TEST_URI;
-}
--- a/browser/devtools/styleinspector/test/browser_ruleview_ui.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_ui.js
@@ -1,252 +1,211 @@
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test all sorts of additions and updates of properties in the rule-view
+// FIXME: TO BE SPLIT IN *MANY* SMALLER TESTS
 
-let doc;
-let inspector;
-let ruleWindow;
-let ruleView;
+let test = asyncTest(function*() {
+  yield addTab("data:text/html;charset=utf-8,browser_ruleview_ui.js");
+  let {toolbox, inspector, view} = yield openRuleView();
 
-function startTest(aInspector, aRuleView)
-{
-  inspector = aInspector;
-  ruleWindow = aRuleView.doc.defaultView;
-  ruleView = aRuleView;
+  yield testContentAfterNodeSelection(inspector, view);
+  yield testCancelNew(inspector, view);
+  yield testCancelNewOnEscape(inspector, view);
+  yield testCreateNew(inspector, view);
+  yield testEditProperty(inspector, view);
+  yield testDisableProperty(inspector, view);
+  yield testPropertyStillMarkedDirty(inspector, view);
+});
+
+function* testContentAfterNodeSelection(inspector, ruleView) {
   let style = "" +
     "#testid {" +
     "  background-color: blue;" +
     "}" +
     ".testclass, .unmatched {" +
     "  background-color: green;" +
     "}";
 
-  let styleNode = addStyle(doc, style);
-  doc.body.innerHTML = "<div id='testid' class='testclass'>Styled Node</div>" +
-                       "<div id='testid2'>Styled Node</div>";
+  let styleNode = addStyle(content.document, style);
+  content.document.body.innerHTML = "<div id='testid' class='testclass'>Styled Node</div>" +
+                                    "<div id='testid2'>Styled Node</div>";
+
+  yield selectNode("#testid", inspector);
+  is(ruleView.element.querySelectorAll("#noResults").length, 0,
+    "After a highlight, no longer has a no-results element.");
 
-  let testElement = doc.getElementById("testid");
-  inspector.selection.setNode(testElement);
-  inspector.once("inspector-updated", () => {
-    is(ruleView.element.querySelectorAll("#noResults").length, 0, "After a highlight, no longer has a no-results element.");
-    inspector.selection.setNode(null);
-    inspector.once("inspector-updated", () => {
-      is(ruleView.element.querySelectorAll("#noResults").length, 1, "After highlighting null, has a no-results element again.");
-      inspector.selection.setNode(testElement);
-      inspector.once("inspector-updated", () => {
-        let classEditor = ruleView.element.children[2]._ruleEditor;
-        is(classEditor.selectorText.querySelector(".ruleview-selector-matched").textContent, ".testclass", ".textclass should be matched.");
-        is(classEditor.selectorText.querySelector(".ruleview-selector-unmatched").textContent, ".unmatched", ".unmatched should not be matched.");
+  yield clearCurrentNodeSelection(inspector)
+  is(ruleView.element.querySelectorAll("#noResults").length, 1,
+    "After highlighting null, has a no-results element again.");
 
-        testCancelNew();
-      });
-    });
-  });
+  yield selectNode("#testid", inspector);
+  let classEditor = ruleView.element.children[2]._ruleEditor;
+  is(classEditor.selectorText.querySelector(".ruleview-selector-matched").textContent,
+    ".testclass", ".textclass should be matched.");
+  is(classEditor.selectorText.querySelector(".ruleview-selector-unmatched").textContent,
+    ".unmatched", ".unmatched should not be matched.");
 }
 
-function testCancelNew()
-{
+function* testCancelNew(inspector, ruleView) {
   // Start at the beginning: start to add a rule to the element's style
   // declaration, but leave it empty.
 
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    waitForEditorBlur(aEditor, function () {
-      ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel.");
-      is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
-      ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
-      testCancelNewOnEscape();
-    });
-    aEditor.input.blur();
-  });
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
+
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "Property editor is focused");
 
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
+  let onBlur = once(editor.input, "blur");
+  editor.input.blur();
+  yield onBlur;
+
+  ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel.");
+  is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property.");
+  ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
 }
 
-function testCancelNewOnEscape()
-{
+function* testCancelNewOnEscape(inspector, ruleView) {
   // Start at the beginning: start to add a rule to the element's style
   // declaration, add some text, then press escape.
 
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-    for (let ch of "background") {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-    waitForEditorBlur(aEditor, function () {
-      ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel.");
-      is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
-      ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
-      testCreateNew();
-    });
-    EventUtils.synthesizeKey("VK_ESCAPE", { });
-  });
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
 
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
-}
-
-function testCreateNew()
-{
-  // Create a new property.
-  let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
-  waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
-
-    let input = aEditor.input;
-
-    ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected.");
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "Next focused editor should be the new property editor.");
+  for (let ch of "background") {
+    EventUtils.sendChar(ch, ruleView.doc.defaultView);
+  }
 
-    // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665).
-    EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow);
-    input.select();
-
-    input.value = "background-color";
-
-    waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
-      promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => {
-        is(elementRuleEditor.rule.textProps.length,  1, "Should have created a new text property.");
-        is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
-        let textProp = elementRuleEditor.rule.textProps[0];
-        is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
+  let onBlur = once(editor.input, "blur");
+  EventUtils.synthesizeKey("VK_ESCAPE", {});
+  yield onBlur;
 
-        aEditor.input.value = "purple";
-        waitForEditorBlur(aEditor, function() {
-          expectRuleChange(elementRuleEditor.rule).then(() => {
-            is(textProp.value, "purple", "Text prop should have been changed.");
-            testEditProperty();
-          });
-        });
-
-        aEditor.input.blur();
-      }));
-    });
-    EventUtils.sendKey("return", ruleWindow);
-  });
-
-  EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1,
-                             { },
-                             ruleWindow);
+  ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel.");
+  is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
+  ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
 }
 
-function testEditProperty()
-{
-  let idRuleEditor = ruleView.element.children[1]._ruleEditor;
-  let propEditor = idRuleEditor.rule.textProps[0].editor;
-  waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
-    is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
+function* testCreateNew(inspector, ruleView) {
+  // Create a new property.
+  let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
+  let editor = yield focusEditableField(elementRuleEditor.closeBrace);
 
-    let input = aEditor.input;
+  is(inplaceEditor(elementRuleEditor.newPropSpan), editor,
+    "Next focused editor should be the new property editor.");
 
-    dump("SELECTION END IS: " + input.selectionEnd + "\n");
-    ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected.");
+  let input = editor.input;
 
-    // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665).
-    EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow);
-    input.select();
-
-    waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
-      promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-        is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
+  ok(input.selectionStart === 0 && input.selectionEnd === input.value.length,
+    "Editor contents are selected.");
 
-        input = aEditor.input;
-
-        ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected.");
+  // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665).
+  EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.doc.defaultView);
+  input.select();
 
-        // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665).
-        EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow);
-        input.select();
+  info("Entering the property name");
+  input.value = "background-color";
 
-        waitForEditorBlur(aEditor, function() {
-          promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-            is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "red",
-               "border-color should have been set.");
+  info("Pressing RETURN and waiting for the value field focus");
+  let onFocus = once(elementRuleEditor.element, "focus", true);
+  EventUtils.sendKey("return", ruleView.doc.defaultView);
+  yield onFocus;
+  yield elementRuleEditor.rule._applyingModifications;
 
-            let props = ruleView.element.querySelectorAll(".ruleview-property");
-            for (let i = 0; i < props.length; i++) {
-              is(props[i].hasAttribute("dirty"), i <= 1,
-                "props[" + i + "] marked dirty as appropriate");
-            }
-            testDisableProperty();
-          }));
-        });
+  editor = inplaceEditor(ruleView.doc.activeElement);
 
-        for (let ch of "red;") {
-          EventUtils.sendChar(ch, ruleWindow);
-          is(propEditor.warning.hidden, true,
-            "warning triangle is hidden or shown as appropriate");
-        }
-      }));
-    });
-    for (let ch of "border-color:") {
-      EventUtils.sendChar(ch, ruleWindow);
-    }
-  });
+  is(elementRuleEditor.rule.textProps.length,  1, "Should have created a new text property.");
+  is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
+  let textProp = elementRuleEditor.rule.textProps[0];
+  is(editor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
 
-  EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1,
-                             { },
-                             ruleWindow);
+  editor.input.value = "purple";
+  let onBlur = once(editor.input, "blur");
+  editor.input.blur();
+  yield onBlur;
+  yield elementRuleEditor.rule._applyingModifications;
+
+  is(textProp.value, "purple", "Text prop should have been changed.");
 }
 
-function testDisableProperty()
-{
+function* testEditProperty(inspector, ruleView) {
   let idRuleEditor = ruleView.element.children[1]._ruleEditor;
   let propEditor = idRuleEditor.rule.textProps[0].editor;
 
-  propEditor.enable.click();
-  promiseDone(expectRuleChange(idRuleEditor.rule).then(() => {
-    is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "", "Border-color should have been unset.");
+  let editor = yield focusEditableField(propEditor.nameSpan);
+  let input = editor.input;
+  is(inplaceEditor(propEditor.nameSpan), editor, "Next focused editor should be the name editor.");
+
+  ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected.");
+
+  // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665).
+  EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.doc.defaultView);
+  input.select();
+
+  info("Entering property name followed by a colon to focus the value");
+  let onFocus = once(idRuleEditor.element, "focus", true);
+  for (let ch of "border-color:") {
+    EventUtils.sendChar(ch, ruleView.doc.defaultView);
+  }
+  yield onFocus;
+  yield idRuleEditor.rule._applyingModifications;