Bug 1246677 - 3 - Remove all usages of getNode in ruleview tests; r=tromey
☠☠ backed out by 8d2eef5f7249 ☠ ☠
authorPatrick Brosset <pbrosset@mozilla.com>
Mon, 15 Feb 2016 10:11:17 +0100
changeset 285498 34e6b56e419d6a0fd1eb74a3676fe924775eb234
parent 285497 5067508e5db4b626978ec32deec2e274720010c0
child 285499 e4f6cc6197cbe96800989280435f4378cccee0ce
push id72403
push usercbook@mozilla.com
push dateThu, 25 Feb 2016 10:59:17 +0000
treeherdermozilla-inbound@3b913f81cb98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstromey
bugs1246677
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1246677 - 3 - Remove all usages of getNode in ruleview tests; r=tromey MozReview-Commit-ID: 6EIQ1lhE3C9
devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
devtools/client/inspector/rules/test/head.js
--- a/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
+++ b/devtools/client/inspector/rules/test/browser_rules_edit-property-order.js
@@ -1,82 +1,89 @@
 /* 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";
 
 // Checking properties orders and overrides in the rule-view.
 
-const TEST_URI = "<div id='testid'>Styled Node</div>";
+const TEST_URI = "<style>#testid {}</style><div id='testid'>Styled Node</div>";
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
-  let element = getNode("#testid");
   let elementStyle = view._elementStyle;
-  let elementRule = elementStyle.rules[0];
+  let elementRule = elementStyle.rules[1];
 
   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.");
+  let firstProp = yield addProperty(view, 1, "background-color", "green");
+  let secondProp = yield addProperty(view, 1, "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.");
+     "Rules should be in addition order.");
+
+  // rgb(0, 0, 255) = blue
+  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
+     "Second property should have been 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.");
+  yield removeProperty(view, secondProp);
+  // rgb(0, 128, 0) = green
+  is((yield getValue("#testid", "background-color")), "rgb(0, 128, 0)",
+     "After deleting second property, first should be used.");
 
   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 still the same");
+
+  secondProp = yield addProperty(view, 1, "background-color", "blue");
+
+  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
+     "New property should be used.");
   is(elementRule.textProps[0], firstProp,
-    "Rules shouldn't have switched places.");
+     "Rules shouldn't have switched places.");
   is(elementRule.textProps[1], secondProp,
-    "Rules shouldn't have switched places.");
+     "Rules shouldn't have switched places.");
 
   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");
+  yield togglePropStatus(view, secondProp);
+
+  is((yield getValue("#testid", "background-color")), "rgb(0, 128, 0)",
+     "After disabling second property, first value should be used");
 
   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.");
+  yield togglePropStatus(view, firstProp);
+
+  is((yield getValue("#testid", "background-color")), "transparent",
+     "After disabling both properties, value should be empty.");
 
   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");
+  yield togglePropStatus(view, secondProp);
+
+  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
+     "Value should be set correctly after re-enabling");
 
   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 still respected");
+  yield togglePropStatus(view, firstProp);
+
+  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
+     "Re-enabling an earlier property shouldn't make it override " +
+     "a later property.");
   is(elementRule.textProps[0], firstProp,
-    "Rules shouldn't have switched places.");
+     "Rules shouldn't have switched places.");
   is(elementRule.textProps[1], secondProp,
-    "Rules shouldn't have switched places.");
-
+     "Rules shouldn't have switched places.");
   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.");
+  yield setProperty(view, firstProp, "purple");
+
+  is((yield getValue("#testid", "background-color")), "rgb(0, 0, 255)",
+     "Modifying an earlier property shouldn't override a later property.");
 });
+
+function* getValue(selector, propName) {
+  let value = yield getComputedStyleProperty(selector, null, propName);
+  return value;
+}
--- a/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_01.js
@@ -60,25 +60,19 @@ function* testMoxy(inspector, view) {
   });
 
   assertGutters(view, {
     guttersNbs: 2,
     gutterHeading: ["Keyframes boxy", "Keyframes moxy"]
   });
 }
 
-function* testNode(selector, inspector, view) {
-  let element = getNode(selector);
+function* assertKeyframeRules(selector, inspector, view, expected) {
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
-  return {element, elementStyle};
-}
-
-function* assertKeyframeRules(selector, inspector, view, expected) {
-  let {element, elementStyle} = yield testNode(selector, inspector, view);
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
     keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
   };
 
   is(rules.elementRules.length, expected.elementRulesNb, selector +
     " has the correct number of non keyframe element rules");
@@ -88,18 +82,16 @@ function* assertKeyframeRules(selector, 
   let i = 0;
   for (let keyframeRule of rules.keyframeRules) {
     ok(keyframeRule.keyframes.name == expected.keyframesRules[i],
       keyframeRule.keyframes.name + " has the correct keyframes name");
     ok(keyframeRule.domRule.keyText == expected.keyframeRules[i],
       keyframeRule.domRule.keyText + " selector heading is correct");
     i++;
   }
-
-  return {rules, element, elementStyle};
 }
 
 function assertGutters(view, expected) {
   let gutters = view.element.querySelectorAll(".theme-gutter");
 
   is(gutters.length, expected.guttersNbs,
     "There are " + gutters.length + " gutter headings");
 
--- a/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframes-rule_02.js
@@ -14,17 +14,17 @@ add_task(function*() {
   let {inspector, view} = yield openRuleView();
   yield testPacman(inspector, view);
   yield testBoxy(inspector, view);
 });
 
 function* testPacman(inspector, view) {
   info("Test content in the keyframes rule of #pacman");
 
-  let {rules} = yield getKeyframeRules("#pacman", inspector, view);
+  let rules = yield getKeyframeRules("#pacman", inspector, view);
 
   info("Test text properties for Keyframes #pacman");
 
   is(convertTextPropsToString(rules.keyframeRules[0].textProps),
     "left: 750px",
     "Keyframe pacman (100%) property is correct"
   );
 
@@ -48,17 +48,17 @@ function* testPacman(inspector, view) {
 
   // is(defaultView.getComputedStyle(element).getPropertyValue("opacity"), "0",
   //   "Added opacity property should have been used.");
 }
 
 function* testBoxy(inspector, view) {
   info("Test content in the keyframes rule of #boxy");
 
-  let {rules} = yield getKeyframeRules("#boxy", inspector, view);
+  let rules = yield getKeyframeRules("#boxy", inspector, view);
 
   info("Test text properties for Keyframes #boxy");
 
   is(convertTextPropsToString(rules.keyframeRules[0].textProps),
     "background-color: blue",
     "Keyframe boxy (10%) property is correct"
   );
 
@@ -73,20 +73,18 @@ function* testBoxy(inspector, view) {
   );
 }
 
 function convertTextPropsToString(textProps) {
   return textProps.map(t => t.name + ": " + t.value).join("; ");
 }
 
 function* getKeyframeRules(selector, inspector, view) {
-  let element = getNode(selector);
-
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
     keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
   };
 
-  return {rules, element, elementStyle};
+  return rules;
 }
--- a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_01.js
@@ -22,17 +22,17 @@ add_task(function*() {
   yield testParagraph(inspector, view);
   yield testBody(inspector, view);
 
   Services.prefs.clearUserPref(PSEUDO_PREF);
 });
 
 function* testTopLeft(inspector, view) {
   let selector = "#topleft";
-  let {rules} = yield assertPseudoElementRulesNumbers(selector,
+  let rules = yield assertPseudoElementRulesNumbers(selector,
     inspector, view, {
       elementRulesNb: 4,
       firstLineRulesNb: 2,
       firstLetterRulesNb: 1,
       selectionRulesNb: 0
     }
   );
 
@@ -150,17 +150,17 @@ function* testBottomLeft(inspector, view
     elementRulesNb: 4,
     firstLineRulesNb: 1,
     firstLetterRulesNb: 1,
     selectionRulesNb: 0
   });
 }
 
 function* testParagraph(inspector, view) {
-  let {rules} = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
+  let rules = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, {
     elementRulesNb: 3,
     firstLineRulesNb: 1,
     firstLetterRulesNb: 1,
     selectionRulesNb: 1
   });
 
   assertGutters(view);
 
@@ -187,24 +187,23 @@ function* testBody(inspector, view) {
   is(gutters.length, 0, "There are no gutter headings");
 }
 
 function convertTextPropsToString(textProps) {
   return textProps.map(t => t.name + ": " + t.value).join("; ");
 }
 
 function* testNode(selector, inspector, view) {
-  let element = getNode(selector);
   yield selectNode(selector, inspector);
   let elementStyle = view._elementStyle;
-  return {element: element, elementStyle: elementStyle};
+  return elementStyle;
 }
 
 function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
-  let {element, elementStyle} = yield testNode(selector, inspector, view);
+  let elementStyle = yield testNode(selector, inspector, view);
 
   let rules = {
     elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement),
     firstLineRules: elementStyle.rules.filter(rule =>
       rule.pseudoElement === ":first-line"),
     firstLetterRules: elementStyle.rules.filter(rule =>
       rule.pseudoElement === ":first-letter"),
     selectionRules: elementStyle.rules.filter(rule =>
@@ -215,17 +214,17 @@ function* assertPseudoElementRulesNumber
      selector + " has the correct number of non pseudo element 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, element, elementStyle};
+  return rules;
 }
 
 function getGutters(view) {
   return view.element.querySelectorAll(".theme-gutter");
 }
 
 function assertGutters(view) {
   let gutters = getGutters(view);
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_01.js
@@ -17,36 +17,35 @@ const TEST_URI = `
   </style>
   <div id="testid" class="testclass" style="margin-top: 1px; padding-top: 5px;">
     Styled Node
   </div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view} = yield openRuleView();
-  let testElement = getNode("#testid");
+  let {inspector, view, testActor} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
   info("Checking that the rule-view has the element, #testid and " +
     ".testclass selectors");
   checkRuleViewContent(view, ["element", "#testid", ".testclass"]);
 
   info("Changing the node's ID attribute and waiting for the " +
     "rule-view refresh");
   let ruleViewRefreshed = inspector.once("rule-view-refreshed");
-  testElement.setAttribute("id", "differentid");
+  yield testActor.setAttribute("#testid", "id", "differentid");
   yield ruleViewRefreshed;
 
   info("Checking that the rule-view doesn't have the #testid selector anymore");
   checkRuleViewContent(view, ["element", ".testclass"]);
 
   info("Reverting the ID attribute change");
   ruleViewRefreshed = inspector.once("rule-view-refreshed");
-  testElement.setAttribute("id", "testid");
+  yield testActor.setAttribute("#differentid", "id", "testid");
   yield ruleViewRefreshed;
 
   info("Checking that the rule-view has all the selectors again");
   checkRuleViewContent(view, ["element", "#testid", ".testclass"]);
 });
 
 function checkRuleViewContent(view, expectedSelectors) {
   let selectors = view.styleDocument
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-attribute-change_02.js
@@ -10,138 +10,138 @@
 const TEST_URI = `
   <div id="testid" class="testclass" style="margin-top: 1px; padding-top: 5px;">
     Styled Node
   </div>
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view} = yield openRuleView();
-  let testElement = getNode("#testid");
+  let {inspector, view, testActor} = yield openRuleView();
   yield selectNode("#testid", inspector);
 
   yield testPropertyChanges(inspector, view);
-  yield testPropertyChange0(inspector, view, testElement);
-  yield testPropertyChange1(inspector, view, testElement);
-  yield testPropertyChange2(inspector, view, testElement);
-  yield testPropertyChange3(inspector, view, testElement);
-  yield testPropertyChange4(inspector, view, testElement);
-  yield testPropertyChange5(inspector, view, testElement);
-  yield testPropertyChange6(inspector, view, testElement);
+  yield testPropertyChange0(inspector, view, "#testid", testActor);
+  yield testPropertyChange1(inspector, view, "#testid", testActor);
+  yield testPropertyChange2(inspector, view, "#testid", testActor);
+  yield testPropertyChange3(inspector, view, "#testid", testActor);
+  yield testPropertyChange4(inspector, view, "#testid", testActor);
+  yield testPropertyChange5(inspector, view, "#testid", testActor);
+  yield testPropertyChange6(inspector, view, "#testid", testActor);
 });
 
 function* testPropertyChanges(inspector, ruleView) {
   info("Adding a second margin-top value in the element selector");
   let ruleEditor = ruleView._elementStyle.rules[0].editor;
   let onRefreshed = inspector.once("rule-view-refreshed");
   ruleEditor.addProperty("margin-top", "5px", "");
   yield onRefreshed;
 
   let rule = ruleView._elementStyle.rules[0];
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "Original margin property active");
 }
 
-function* testPropertyChange0(inspector, ruleView, testElement) {
-  yield changeElementStyle(testElement, "margin-top: 1px; padding-top: 5px",
-    inspector);
+function* testPropertyChange0(inspector, ruleView, selector, testActor) {
+  yield changeElementStyle(selector, "margin-top: 1px; padding-top: 5px",
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], true, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], false, "margin-top", "5px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange1(inspector, ruleView, testElement) {
+function* testPropertyChange1(inspector, ruleView, selector, testActor) {
   info("Now set it back to 5px, the 5px value should be re-enabled.");
-  yield changeElementStyle(testElement, "margin-top: 5px; padding-top: 5px;",
-    inspector);
+  yield changeElementStyle(selector, "margin-top: 5px; padding-top: 5px;",
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], true, "margin-top", "5px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange2(inspector, ruleView, testElement) {
+function* testPropertyChange2(inspector, ruleView, selector, testActor) {
   info("Set the margin property to a value that doesn't exist in the editor.");
   info("Should reuse the currently-enabled element (the second one.)");
-  yield changeElementStyle(testElement, "margin-top: 15px; padding-top: 5px;",
-    inspector);
+  yield changeElementStyle(selector, "margin-top: 15px; padding-top: 5px;",
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[0], false, "margin-top", "1px",
     "First margin property re-enabled");
   validateTextProp(rule.textProps[2], true, "margin-top", "15px",
     "Second margin property disabled");
 }
 
-function* testPropertyChange3(inspector, ruleView, testElement) {
+function* testPropertyChange3(inspector, ruleView, selector, testActor) {
   info("Remove the padding-top attribute. Should disable the padding " +
     "property but not remove it.");
-  yield changeElementStyle(testElement, "margin-top: 5px;", inspector);
+  yield changeElementStyle(selector, "margin-top: 5px;", inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[1], false, "padding-top", "5px",
     "Padding property disabled");
 }
 
-function* testPropertyChange4(inspector, ruleView, testElement) {
+function* testPropertyChange4(inspector, ruleView, selector, testActor) {
   info("Put the padding-top attribute back in, should re-enable the " +
     "padding property.");
-  yield changeElementStyle(testElement, "margin-top: 5px; padding-top: 25px",
-    inspector);
+  yield changeElementStyle(selector, "margin-top: 5px; padding-top: 25px",
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3,
     "Correct number of properties");
   validateTextProp(rule.textProps[1], true, "padding-top", "25px",
     "Padding property enabled");
 }
 
-function* testPropertyChange5(inspector, ruleView, testElement) {
+function* testPropertyChange5(inspector, ruleView, selector, testActor) {
   info("Add an entirely new property");
-  yield changeElementStyle(testElement,
-    "margin-top: 5px; padding-top: 25px; padding-left: 20px;", inspector);
+  yield changeElementStyle(selector,
+    "margin-top: 5px; padding-top: 25px; padding-left: 20px;",
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 4,
     "Added a property");
   validateTextProp(rule.textProps[3], true, "padding-left", "20px",
     "Padding property enabled");
 }
 
-function* testPropertyChange6(inspector, ruleView, testElement) {
+function* testPropertyChange6(inspector, ruleView, selector, testActor) {
   info("Add an entirely new property again");
-  yield changeElementStyle(testElement, "background: red " +
+  yield changeElementStyle(selector, "background: red " +
     "url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%",
-    inspector);
+    inspector, testActor);
 
   let rule = ruleView._elementStyle.rules[0];
   is(rule.editor.element.querySelectorAll(".ruleview-property").length, 5,
     "Added a property");
   validateTextProp(rule.textProps[4], true, "background",
                    "red url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0%",
                    "shortcut property correctly set");
 }
 
-function* changeElementStyle(testElement, style, inspector) {
+function* changeElementStyle(selector, style, inspector, testActor) {
   let onRefreshed = inspector.once("rule-view-refreshed");
-  testElement.setAttribute("style", style);
+  yield testActor.setAttribute(selector, "style", style);
   yield onRefreshed;
 }
 
 function validateTextProp(aProp, aEnabled, aName, aValue, aDesc) {
   is(aProp.enabled, aEnabled, aDesc + ": enabled.");
   is(aProp.name, aName, aDesc + ": name.");
   is(aProp.value, aValue, aDesc + ": value.");
 
--- a/devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
+++ b/devtools/client/inspector/rules/test/browser_rules_refresh-on-style-change.js
@@ -8,27 +8,27 @@
 // changed
 
 const TEST_URI = "<div id='testdiv' style='font-size: 10px;''>Test div!</div>";
 
 add_task(function*() {
   Services.prefs.setCharPref("devtools.defaultColorUnit", "name");
 
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
-  let {inspector, view} = yield openRuleView();
+  let {inspector, view, testActor} = yield openRuleView();
   yield selectNode("#testdiv", inspector);
 
   let fontSize = getRuleViewPropertyValue(view, "element", "font-size");
   is(fontSize, "10px", "The rule view shows the right font-size");
 
   info("Changing the node's style and waiting for the update");
   let onUpdated = inspector.once("rule-view-refreshed");
-  let div = getNode("#testdiv");
-  div.style.cssText = "font-size: 3em; color: lightgoldenrodyellow; " +
-    "text-align: right; text-transform: uppercase";
+  yield testActor.setAttribute("#testdiv", "style",
+    "font-size: 3em; color: lightgoldenrodyellow; " +
+    "text-align: right; text-transform: uppercase");
   yield onUpdated;
 
   let textAlign = getRuleViewPropertyValue(view, "element", "text-align");
   is(textAlign, "right", "The rule view shows the new text align.");
   let color = getRuleViewPropertyValue(view, "element", "color");
   is(color, "lightgoldenrodyellow", "The rule view shows the new color.");
   fontSize = getRuleViewPropertyValue(view, "element", "font-size");
   is(fontSize, "3em", "The rule view shows the new font size.");
--- a/devtools/client/inspector/rules/test/head.js
+++ b/devtools/client/inspector/rules/test/head.js
@@ -43,41 +43,27 @@ addTab = function(url) {
 /**
  * Open the toolbox, with the inspector tool visible, and the rule-view
  * sidebar tab selected.
  *
  * @return a promise that resolves when the inspector is ready and the rule
  * view is visible and ready
  */
 function openRuleView() {
-  return openInspectorSidebarTab("ruleview").then(({toolbox, inspector}) => {
+  return openInspectorSidebarTab("ruleview").then(data => {
     return {
-      toolbox,
-      inspector,
-      view: inspector.ruleview.view
+      toolbox: data.toolbox,
+      inspector: data.inspector,
+      testActor: data.testActor,
+      view: data.inspector.ruleview.view
     };
   });
 }
 
 /**
- * Simple DOM node accesor function that takes either a node or a string css
- * selector as argument and returns the corresponding node
- *
- * @param {String|DOMNode} nodeOrSelector
- * @return {DOMNode|CPOW} Note that in e10s mode a CPOW object is returned which
- * doesn't implement *all* of the DOMNode's properties
- */
-function getNode(nodeOrSelector) {
-  info("Getting the node for '" + nodeOrSelector + "'");
-  return typeof nodeOrSelector === "string" ?
-    content.document.querySelector(nodeOrSelector) :
-    nodeOrSelector;
-}
-
-/**
  * Set the inspector's current selection to null so that no node is selected
  *
  * @param {InspectorPanel} inspector
  *        The instance of InspectorPanel currently loaded in the toolbox
  * @return a promise that resolves when the inspector is updated
  */
 function clearCurrentNodeSelection(inspector) {
   info("Clearing the current selection");
@@ -203,16 +189,31 @@ function executeInContent(name, data={},
 function* getComputedStyleProperty(selector, pseudo, propName) {
   return yield executeInContent("Test:GetComputedStylePropertyValue",
                                 {selector,
                                 pseudo,
                                 name: propName});
 }
 
 /**
+ * Get an element's inline style property value.
+ * @param {TestActor} testActor
+ * @param {String} selector
+ *        The selector used to obtain the element.
+ * @param {String} name
+ *        name of the property.
+ */
+function getStyle(testActor, selector, propName) {
+  return testActor.eval(`
+    content.document.querySelector("${selector}")
+                    .style.getPropertyValue("${propName}");
+  `);
+}
+
+/**
  * Send an async message to the frame script and wait until the requested
  * computed style property has the expected value.
  *
  * @param {String} selector
  *        The selector used to obtain the element.
  * @param {String} pseudo
  *        pseudo id to query, or null.
  * @param {String} prop
@@ -574,16 +575,115 @@ function getRuleViewLinkTextByIndex(view
  */
 function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) {
   return nodeIndex !== undefined ?
     view.element.children[childrenIndex].childNodes[nodeIndex]._ruleEditor :
     view.element.children[childrenIndex]._ruleEditor;
 }
 
 /**
+ * Simulate adding a new property in an existing rule in the rule-view.
+ *
+ * @param {CssRuleView} view
+ *        The instance of the rule-view panel
+ * @param {Number} ruleIndex
+ *        The index of the rule to use. Note that if ruleIndex is 0, you might
+ *        want to also listen to markupmutation events in your test since
+ *        that's going to change the style attribute of the selected node.
+ * @param {String} name
+ *        The name for the new property
+ * @param {String} value
+ *        The value for the new property
+ * @return {TextProperty} The instance of the TextProperty that was added
+ */
+var addProperty = Task.async(function*(view, ruleIndex, name, value) {
+  info("Adding new property " + name + ":" + value + " to rule " + ruleIndex);
+
+  let ruleEditor = getRuleViewRuleEditor(view, ruleIndex);
+  let editor = yield focusNewRuleViewProperty(ruleEditor);
+
+  info("Adding name " + name);
+  editor.input.value = name;
+  let onNameAdded = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onNameAdded;
+
+  // Focus has moved to the value inplace-editor automatically.
+  editor = inplaceEditor(view.styleDocument.activeElement);
+  let textProps = ruleEditor.rule.textProps;
+  let textProp = textProps[textProps.length - 1];
+
+  info("Adding value " + value);
+  editor.input.value = value;
+  let onValueAdded = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onValueAdded;
+
+  // Blur the new property field that was focused by default.
+  view.styleDocument.activeElement.blur();
+  return textProp;
+});
+
+/**
+ * Simulate changing the value of a property in a rule in the rule-view.
+ *
+ * @param {CssRuleView} view
+ *        The instance of the rule-view panel
+ * @param {TextProperty} textProp
+ *        The instance of the TextProperty to be changed
+ * @param {String} value
+ *        The new value to be used
+ */
+var setProperty = Task.async(function*(view, textProp, value) {
+  let editor = yield focusEditableField(view, textProp.editor.valueSpan);
+
+  let onRuleViewRefreshed = view.once("ruleview-changed");
+  editor.input.value = value;
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onRuleViewRefreshed;
+
+  view.styleDocument.activeElement.blur();
+});
+
+/**
+ * Simulate removing a property from an existing rule in the rule-view.
+ *
+ * @param {CssRuleView} view
+ *        The instance of the rule-view panel
+ * @param {TextProperty} textProp
+ *        The instance of the TextProperty to be removed
+ */
+var removeProperty = Task.async(function*(view, textProp) {
+  yield focusEditableField(view, textProp.editor.nameSpan);
+
+  let onModifications = view.once("ruleview-changed");
+  info("Deleting the property name now");
+  EventUtils.synthesizeKey("VK_DELETE", {}, view.styleWindow);
+  EventUtils.synthesizeKey("VK_RETURN", {}, view.styleWindow);
+  yield onModifications;
+
+  // Blur the new property field that was focused by default.
+  view.styleDocument.activeElement.blur();
+});
+
+/**
+ * Simulate clicking the enable/disable checkbox next to a property in a rule.
+ *
+ * @param {CssRuleView} view
+ *        The instance of the rule-view panel
+ * @param {TextProperty} textProp
+ *        The instance of the TextProperty to be enabled/disabled
+ */
+var togglePropStatus = Task.async(function*(view, textProp) {
+  let onRuleViewRefreshed = view.once("ruleview-changed");
+  textProp.editor.enable.click();
+  yield onRuleViewRefreshed;
+});
+
+/**
  * Click on a rule-view's close brace to focus a new property name editor
  *
  * @param {RuleEditor} ruleEditor
  *        An instance of RuleEditor that will receive the new property
  * @return a promise that resolves to the newly created editor when ready and
  * focused
  */
 var focusNewRuleViewProperty = Task.async(function*(ruleEditor) {