Bug 1503896 - (Part 6) Add test for tracking changes to rule selectors; r=pbro
authorRazvan Caliman <rcaliman@mozilla.com>
Wed, 07 Nov 2018 10:33:32 +0000
changeset 444828 10a65f18e697a58685832661d670242408b2a11a
parent 444827 ecc6903c579bf13a3f79ee77c5700e5defc0ce6b
child 444829 891cd385f0ae6c38b8a218dde732ff467ea2af0f
push id35003
push userncsoregi@mozilla.com
push dateWed, 07 Nov 2018 16:16:52 +0000
treeherdermozilla-central@4407a6d3e374 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1503896
milestone65.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 1503896 - (Part 6) Add test for tracking changes to rule selectors; r=pbro Depends on D11116 Differential Revision: https://phabricator.services.mozilla.com/D11117
devtools/client/inspector/changes/components/CSSDeclaration.js
devtools/client/inspector/changes/test/browser.ini
devtools/client/inspector/changes/test/browser_changes_rule_selector.js
devtools/client/shared/test/shared-redux-head.js
--- a/devtools/client/inspector/changes/components/CSSDeclaration.js
+++ b/devtools/client/inspector/changes/components/CSSDeclaration.js
@@ -21,17 +21,17 @@ class CSSDeclaration extends PureCompone
     return {
       className: "",
     };
   }
 
   render() {
     const { property, value, className } = this.props;
 
-    return dom.div({ className },
+    return dom.div({ className: `declaration ${className}` },
       dom.span({ className: "declaration-name theme-fg-color5"}, property),
       ":",
       dom.span({ className: "declaration-value theme-fg-color1"}, value),
       ";"
     );
   }
 }
 
--- a/devtools/client/inspector/changes/test/browser.ini
+++ b/devtools/client/inspector/changes/test/browser.ini
@@ -10,8 +10,9 @@ support-files =
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
   !/devtools/client/shared/test/test-actor.js
   !/devtools/client/shared/test/test-actor-registry.js
 
 [browser_changes_declaration_disable.js]
 [browser_changes_declaration_edit_value.js]
 [browser_changes_declaration_remove.js]
+[browser_changes_rule_selector.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/changes/test/browser_changes_rule_selector.js
@@ -0,0 +1,66 @@
+/* vim: set 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 renaming the selector of a CSS declaration in the Rule view is tracked as
+// one rule removal with the old selector and one rule addition with the new selector.
+
+const TEST_URI = `
+  <style type='text/css'>
+    div {
+      color: red;
+    }
+  </style>
+  <div></div>
+`;
+
+add_task(async function() {
+  await addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  const { inspector, view: ruleView } = await openRuleView();
+  const { document: doc, store } = selectChangesView(inspector);
+  const panel = doc.querySelector("#sidebar-panel-changes");
+
+  await selectNode("div", inspector);
+  const ruleEditor = getRuleViewRuleEditor(ruleView, 1);
+
+  info("Focusing the first rule's selector name in the Rule view");
+  const editor = await focusEditableField(ruleView, ruleEditor.selectorText);
+  info("Entering a new selector name");
+  editor.input.value = ".test";
+
+  // Expect two "TRACK_CHANGE" actions: one for rule removal, one for rule addition.
+  const onTrackChange = waitUntilAction(store, "TRACK_CHANGE", 2);
+  const onRuleViewChanged = once(ruleView, "ruleview-changed");
+  info("Pressing Enter key to commit the change");
+  EventUtils.synthesizeKey("KEY_Enter");
+  info("Waiting for rule view to update");
+  await onRuleViewChanged;
+  info("Wait for the change to be tracked");
+  await onTrackChange;
+
+  const rules = panel.querySelectorAll(".rule");
+  is(rules.length, 2, "Two rules were tracked as changed");
+
+  const firstSelector = rules.item(0).querySelector(".selector");
+  is(firstSelector.title, "div", "Old selector name was tracked.");
+  ok(firstSelector.classList.contains("diff-remove"), "Old selector was removed.");
+
+  const secondSelector = rules.item(1).querySelector(".selector");
+  is(secondSelector.title, ".test", "New selector name was tracked.");
+  ok(secondSelector.classList.contains("diff-add"), "New selector was added.");
+
+  info("Checking that the two rules have identical declarations");
+  const firstDecl = rules.item(0).querySelectorAll(".declaration");
+  is(firstDecl.length, 1, "First rule has only one declaration");
+  is(firstDecl.item(0).textContent, "color:red;", "First rule has correct declaration");
+  ok(firstDecl.item(0).classList.contains("diff-remove"),
+    "First rule has declaration tracked as removed");
+
+  const secondDecl = rules.item(1).querySelectorAll(".declaration");
+  is(secondDecl.length, 1, "Second rule has only one declaration");
+  is(secondDecl.item(0).textContent, "color:red;", "Second rule has correct declaration");
+  ok(secondDecl.item(0).classList.contains("diff-add"),
+    "Second rule has declaration tracked as added");
+});
--- a/devtools/client/shared/test/shared-redux-head.js
+++ b/devtools/client/shared/test/shared-redux-head.js
@@ -38,33 +38,38 @@ function waitUntilState(store, predicate
   // Fire the check immediately in case the action has already occurred
   check();
 
   return deferred.promise;
 }
 
 /**
  * Wait until a particular action has been emitted by the store.
- * @param Store store
+ * @param {Store} store
  *        The Redux store being used.
- * @param string actionType
+ * @param {String} actionType
  *        The expected action to wait for.
+ * @param {Number} count
+ *         Number of times to expect the action to occur. Default is once.
  * @return Promise
  *         Resolved once the expected action is emitted by the store.
  */
-function waitUntilAction(store, actionType) {
+function waitUntilAction(store, actionType, count = 1) {
   const deferred = defer();
   const unsubscribe = store.subscribe(check);
   const history = store.history;
   let index = history.length;
 
   info(`Waiting for action "${actionType}"`);
   function check() {
     const action = history[index++];
     if (action && action.type === actionType) {
       info(`Found action "${actionType}"`);
-      unsubscribe();
-      deferred.resolve(store.getState());
+      count--;
+      if (count === 0) {
+        unsubscribe();
+        deferred.resolve(store.getState());
+      }
     }
   }
 
   return deferred.promise;
 }