Bug 1246677 - 3 - Remove all usages of getNode in ruleview tests draft
authorPatrick Brosset <pbrosset@mozilla.com>
Thu, 11 Feb 2016 11:50:17 +0100
changeset 330655 60b5facfb092907f1746cf3f029a810861d9ab3d
parent 330654 b45072b89826eff44fba8089948c611641f244e0
child 330656 a30d6d613fe5ca45780232ddd9cb1235cb4ae059
push id10801
push userpbrosset@mozilla.com
push dateFri, 12 Feb 2016 13:33:31 +0000
bugs1246677
milestone47.0a1
Bug 1246677 - 3 - Remove all usages of getNode in ruleview tests 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
@@ -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
@@ -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) {