Bug 1190047 - [Rule View] Ensure changes to swatches are reverted to the original value on escape r=bgrins
authorGabriel Luong <gabriel.luong@gmail.com>
Tue, 04 Aug 2015 15:03:02 -0700
changeset 287802 78512934fdb82bd679aa3e5584ab12d03df39c3a
parent 287801 3148797b3c42b8d05a4c0500332b2d01c37c97c1
child 287803 3301c85aa6713f50caf3c8e63893b7e2904d3945
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1190047
milestone42.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 1190047 - [Rule View] Ensure changes to swatches are reverted to the original value on escape r=bgrins
browser/devtools/shared/widgets/Tooltip.js
browser/devtools/styleinspector/rule-view.js
browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
browser/devtools/styleinspector/test/browser_ruleview_cubicbezier-revert-on-ESC.js
browser/devtools/styleinspector/test/browser_ruleview_filtereditor-revert-on-ESC.js
--- a/browser/devtools/shared/widgets/Tooltip.js
+++ b/browser/devtools/shared/widgets/Tooltip.js
@@ -1020,23 +1020,27 @@ SwatchBasedEditorTooltip.prototype = {
    * tooltip knows about. That means from now on, clicking on that swatch will
    * toggle the editor.
    *
    * @param {node} swatchEl
    *        The element to add
    * @param {object} callbacks
    *        Callbacks that will be executed when the editor wants to preview a
    *        value change, or revert a change, or commit a change.
+   *        - onShow: will be called when one of the swatch tooltip is shown
    *        - onPreview: will be called when one of the sub-classes calls
    *        preview
    *        - onRevert: will be called when the user ESCapes out of the tooltip
    *        - onCommit: will be called when the user presses ENTER or clicks
    *        outside the tooltip.
    */
   addSwatch: function(swatchEl, callbacks={}) {
+    if (!callbacks.onShow) {
+      callbacks.onShow = function() {};
+    }
     if (!callbacks.onPreview) {
       callbacks.onPreview = function() {};
     }
     if (!callbacks.onRevert) {
       callbacks.onRevert = function() {};
     }
     if (!callbacks.onCommit) {
       callbacks.onCommit = function() {};
@@ -1064,16 +1068,17 @@ SwatchBasedEditorTooltip.prototype = {
 
     if (event.shiftKey) {
       event.stopPropagation();
       return;
     }
     if (swatch) {
       this.activeSwatch = event.target;
       this.show();
+      swatch.callbacks.onShow();
       event.stopPropagation();
     }
   },
 
   /**
    * Not called by this parent class, needs to be taken care of by sub-classes
    */
   preview: function(value) {
--- a/browser/devtools/styleinspector/rule-view.js
+++ b/browser/devtools/styleinspector/rule-view.js
@@ -2844,16 +2844,19 @@ function TextPropertyEditor(aRuleEditor,
   this.browserWindow = this.doc.defaultView.top;
   this.removeOnRevert = this.prop.value === "";
 
   this._onEnableClicked = this._onEnableClicked.bind(this);
   this._onExpandClicked = this._onExpandClicked.bind(this);
   this._onStartEditing = this._onStartEditing.bind(this);
   this._onNameDone = this._onNameDone.bind(this);
   this._onValueDone = this._onValueDone.bind(this);
+  this._onSwatchCommit = this._onSwatchCommit.bind(this);
+  this._onSwatchPreview = this._onSwatchPreview.bind(this);
+  this._onSwatchRevert = this._onSwatchRevert.bind(this);
   this._onValidate = throttle(this._previewValue, 10, this);
   this.update = this.update.bind(this);
 
   this._create();
   this.update();
 }
 
 TextPropertyEditor.prototype = {
@@ -3070,17 +3073,17 @@ TextPropertyEditor.prototype = {
       this.enable.setAttribute("checked", "");
     } else {
       this.enable.style.visibility = "visible";
       this.enable.removeAttribute("checked");
     }
 
     this.warning.hidden = this.editing || this.isValid();
 
-    if ((this.prop.overridden || !this.prop.enabled) && !this.editing) {
+    if (this.prop.overridden || !this.prop.enabled) {
       this.element.classList.add("ruleview-overridden");
     } else {
       this.element.classList.remove("ruleview-overridden");
     }
 
     let name = this.prop.name;
     this.nameSpan.textContent = name;
 
@@ -3125,48 +3128,51 @@ TextPropertyEditor.prototype = {
     // Attach the color picker tooltip to the color swatches
     this._colorSwatchSpans =
       this.valueSpan.querySelectorAll("." + colorSwatchClass);
     if (this.ruleEditor.isEditable) {
       for (let span of this._colorSwatchSpans) {
         // Adding this swatch to the list of swatches our colorpicker
         // knows about
         this.ruleView.tooltips.colorPicker.addSwatch(span, {
-          onPreview: () => this._previewValue(this.valueSpan.textContent),
-          onCommit: () => this._onValueDone(this.valueSpan.textContent, true),
-          onRevert: () => this._onValueDone(undefined, false)
+          onShow: this._onStartEditing,
+          onPreview: this._onSwatchPreview,
+          onCommit: this._onSwatchCommit,
+          onRevert: this._onSwatchRevert
         });
       }
     }
 
     // Attach the cubic-bezier tooltip to the bezier swatches
     this._bezierSwatchSpans =
       this.valueSpan.querySelectorAll("." + bezierSwatchClass);
     if (this.ruleEditor.isEditable) {
       for (let span of this._bezierSwatchSpans) {
         // Adding this swatch to the list of swatches our colorpicker
         // knows about
         this.ruleView.tooltips.cubicBezier.addSwatch(span, {
-          onPreview: () => this._previewValue(this.valueSpan.textContent),
-          onCommit: () => this._onValueDone(this.valueSpan.textContent, true),
-          onRevert: () => this._onValueDone(undefined, false)
+          onShow: this._onStartEditing,
+          onPreview: this._onSwatchPreview,
+          onCommit: this._onSwatchCommit,
+          onRevert: this._onSwatchRevert
         });
       }
     }
 
     // Attach the filter editor tooltip to the filter swatch
     let span = this.valueSpan.querySelector("." + filterSwatchClass);
     if (this.ruleEditor.isEditable) {
       if (span) {
         parserOptions.filterSwatch = true;
 
         this.ruleView.tooltips.filterEditor.addSwatch(span, {
-          onPreview: () => this._previewValue(this.valueSpan.textContent),
-          onCommit: () => this._onValueDone(this.valueSpan.textContent, true),
-          onRevert: () => this._onValueDone(undefined, false)
+          onShow: this._onStartEditing,
+          onPreview: this._onSwatchPreview,
+          onCommit: this._onSwatchCommit,
+          onRevert: this._onSwatchRevert
         }, outputParser, parserOptions);
       }
     }
 
     // Populate the computed styles.
     this._updateComputed();
 
     // Update the rule property highlight.
@@ -3418,16 +3424,40 @@ TextPropertyEditor.prototype = {
         if (!this.editing) {
           this.remove();
         }
       }, 0);
     }
   },
 
   /**
+   * Called when the swatch editor wants to commit a value change.
+   */
+  _onSwatchCommit: function() {
+    this._onValueDone(this.valueSpan.textContent, true);
+    this.update();
+  },
+
+  /**
+   * Called when the swatch editor wants to preview a value change.
+   */
+  _onSwatchPreview: function() {
+    this._previewValue(this.valueSpan.textContent);
+  },
+
+  /**
+   * Called when the swatch editor closes from an ESC. Revert to the original
+   * value of this property before editing.
+   */
+  _onSwatchRevert: function() {
+    this.rule.setPropertyEnabled(this.prop, this.prop.enabled);
+    this.update();
+  },
+
+  /**
    * Parse a value string and break it into pieces, starting with the
    * first value, and into an array of additional properties (if any).
    *
    * Example: Calling with "red; width: 100px" would return
    * { firstValue: "red", propertiesToAdd: [{ name: "width", value: "100px" }] }
    *
    * @param {string} aValue
    *        The string to parse
--- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-revert-on-ESC.js
@@ -1,56 +1,121 @@
 /* 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 a color change in the color picker is reverted when ESC is pressed
 
-const PAGE_CONTENT = [
-  '<style type="text/css">',
-  '  body {',
-  '    background-color: #ededed;',
-  '  }',
-  '</style>',
-  'Testing the color picker tooltip!'
+let TEST_URI = [
+  "<style type='text/css'>",
+  "  body {",
+  "    background-color: #EDEDED;",
+  "  }",
+  "</style>",
 ].join("\n");
 
 add_task(function*() {
-  yield addTab("data:text/html;charset=utf-8,rule view color picker tooltip test");
-  content.document.body.innerHTML = PAGE_CONTENT;
-  let {toolbox, inspector, view} = yield openRuleView();
-
-  let swatch = getRuleViewProperty(view, "body", "background-color").valueSpan
-    .querySelector(".ruleview-colorswatch");
-  yield testPressingEscapeRevertsChanges(swatch, view);
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  let {view} = yield openRuleView();
+  yield testPressingEscapeRevertsChanges(view);
+  yield testPressingEscapeRevertsChangesAndDisables(view);
 });
 
-function* testPressingEscapeRevertsChanges(swatch, ruleView) {
-  let cPicker = ruleView.tooltips.colorPicker;
+function* testPressingEscapeRevertsChanges(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-colorswatch");
+  let cPicker = view.tooltips.colorPicker;
 
   let onShown = cPicker.tooltip.once("shown");
   swatch.click();
   yield onShown;
 
-  yield simulateColorPickerChange(ruleView, cPicker, [0, 0, 0, 1], {
+  yield simulateColorPickerChange(view, 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(ruleView, "body", "background-color").valueSpan.textContent,
-    "#000", "The text of the background-color css property was updated");
+  is(propEditor.valueSpan.textContent, "#000",
+    "The text of the background-color css property was updated");
 
   let spectrum = yield cPicker.spectrum;
 
-  // ESC out of the color picker
+  info("Pressing ESCAPE to close the tooltip");
   let onHidden = cPicker.tooltip.once("hidden");
   EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
   yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
 
-  yield waitForSuccess(() => {
-    return content.getComputedStyle(content.document.body).backgroundColor === "rgb(237, 237, 237)";
-  }, "The element's background-color was reverted");
+  yield waitForComputedStyleProperty("body", null, "background-color",
+    "rgb(237, 237, 237)");
+  is(propEditor.valueSpan.textContent, "#EDEDED",
+    "Got expected property value.");
 }
+
+function* testPressingEscapeRevertsChangesAndDisables(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-colorswatch");
+  let cPicker = view.tooltips.colorPicker;
+
+  info("Disabling background-color property");
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled,
+    "background-color property is disabled.");
+  let newValue = yield getRulePropertyValue("background-color");
+  is(newValue, "", "background-color should have been unset.");
+
+  let onShown = cPicker.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
+    "property overridden is not displayed.");
+  is(propEditor.enable.style.visibility, "hidden",
+    "property enable checkbox is hidden.");
+
+  let spectrum = yield cPicker.spectrum;
+  info("Simulating a color picker change in the widget");
+  spectrum.rgb = [0, 0, 0, 1];
+  yield ruleEditor.rule._applyingModifications;
+
+  info("Pressing ESCAPE to close the tooltip");
+  let onHidden = cPicker.tooltip.once("hidden");
+  EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
+  yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled,
+    "background-color property is disabled.");
+  newValue = yield getRulePropertyValue("background-color");
+  is(newValue, "", "background-color should have been unset.");
+  is(propEditor.valueSpan.textContent, "#EDEDED",
+    "Got expected property value.");
+}
+
+function* getRulePropertyValue(name) {
+  let propValue = yield executeInContent("Test:GetRulePropertyValue", {
+    styleSheetIndex: 0,
+    ruleIndex: 0,
+    name: name
+  });
+  return propValue;
+}
--- a/browser/devtools/styleinspector/test/browser_ruleview_cubicbezier-revert-on-ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_cubicbezier-revert-on-ESC.js
@@ -1,53 +1,119 @@
 /* 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 changes made to the cubic-bezier timing-function in the cubic-bezier
-// tooltip are reverted when ESC is pressed
+// Test that changes made to the cubic-bezier timing-function in the
+// cubic-bezier tooltip are reverted when ESC is pressed
 
-const PAGE_CONTENT = [
-  '<style type="text/css">',
-  '  body {',
-  '    animation-timing-function: linear;',
-  '  }',
-  '</style>',
+let TEST_URI = [
+  "<style type='text/css'>",
+  "  body {",
+  "    animation-timing-function: linear;",
+  "  }",
+  "</style>",
 ].join("\n");
 
 add_task(function*() {
-  yield addTab("data:text/html;charset=utf-8,rule view cubic-bezier tooltip test");
-  content.document.body.innerHTML = PAGE_CONTENT;
-  let {toolbox, inspector, view} = yield openRuleView();
-
-  info("Getting the bezier swatch element");
-  let swatch = getRuleViewProperty(view, "body", "animation-timing-function").valueSpan
-    .querySelector(".ruleview-bezierswatch");
-  yield testPressingEscapeRevertsChanges(swatch, view);
+  yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
+  let {view} = yield openRuleView();
+  yield testPressingEscapeRevertsChanges(view);
+  yield testPressingEscapeRevertsChangesAndDisables(view);
 });
 
-function* testPressingEscapeRevertsChanges(swatch, ruleView) {
-  let bezierTooltip = ruleView.tooltips.cubicBezier;
+function* testPressingEscapeRevertsChanges(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-bezierswatch");
+  let bezierTooltip = view.tooltips.cubicBezier;
 
   let onShown = bezierTooltip.tooltip.once("shown");
   swatch.click();
   yield onShown;
 
   let widget = yield bezierTooltip.widget;
   info("Simulating a change of curve in the widget");
   widget.coordinates = [0.1, 2, 0.9, -1];
-  let expected = "cubic-bezier(0.1, 2, 0.9, -1)";
+  yield ruleEditor.rule._applyingModifications;
 
-  yield waitForSuccess(() => {
-    return content.getComputedStyle(content.document.body).animationTimingFunction === expected;
-  }, "Waiting for the change to be previewed on the element");
+  yield waitForComputedStyleProperty("body", null, "animation-timing-function",
+    "cubic-bezier(0.1, 2, 0.9, -1)");
+  is(propEditor.valueSpan.textContent, "cubic-bezier(.1,2,.9,-1)",
+    "Got expected property value.");
 
   info("Pressing ESCAPE to close the tooltip");
   let onHidden = bezierTooltip.tooltip.once("hidden");
   EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
   yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
 
-  yield waitForSuccess(() => {
-    return content.getComputedStyle(content.document.body).animationTimingFunction === "cubic-bezier(0, 0, 1, 1)";
-  }, "Waiting for the change to be reverted on the element");
+  yield waitForComputedStyleProperty("body", null, "animation-timing-function",
+    "cubic-bezier(0, 0, 1, 1)");
+  is(propEditor.valueSpan.textContent, "linear",
+    "Got expected property value.");
 }
+
+function* testPressingEscapeRevertsChangesAndDisables(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-bezierswatch");
+  let bezierTooltip = view.tooltips.cubicBezier;
+
+  info("Disabling animation-timing-function property");
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled,
+    "animation-timing-function property is disabled.");
+  let newValue = yield getRulePropertyValue("animation-timing-function");
+  is(newValue, "", "animation-timing-function should have been unset.");
+
+  let onShown = bezierTooltip.tooltip.once("shown");
+  swatch.click();
+  yield onShown;
+
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
+    "property overridden is not displayed.");
+  is(propEditor.enable.style.visibility, "hidden",
+    "property enable checkbox is hidden.");
+
+  let widget = yield bezierTooltip.widget;
+  info("Simulating a change of curve in the widget");
+  widget.coordinates = [0.1, 2, 0.9, -1];
+  yield ruleEditor.rule._applyingModifications;
+
+  info("Pressing ESCAPE to close the tooltip");
+  let onHidden = bezierTooltip.tooltip.once("hidden");
+  EventUtils.sendKey("ESCAPE", widget.parent.ownerDocument.defaultView);
+  yield onHidden;
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled,
+    "animation-timing-function property is disabled.");
+  newValue = yield getRulePropertyValue("animation-timing-function");
+  is(newValue, "", "animation-timing-function should have been unset.");
+  is(propEditor.valueSpan.textContent, "linear",
+    "Got expected property value.");
+}
+
+function* getRulePropertyValue(name) {
+  let propValue = yield executeInContent("Test:GetRulePropertyValue", {
+    styleSheetIndex: 0,
+    ruleIndex: 0,
+    name: name
+  });
+  return propValue;
+}
--- a/browser/devtools/styleinspector/test/browser_ruleview_filtereditor-revert-on-ESC.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_filtereditor-revert-on-ESC.js
@@ -1,38 +1,104 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Tests the Filter Editor Tooltip reverting changes on ESC
+// Tests that changes made to the Filter Editor Tooltip are reverted when
+// ESC is pressed
 
 const TEST_URL = TEST_URL_ROOT + "doc_filter.html";
 
 add_task(function*() {
   yield addTab(TEST_URL);
-
-  let {toolbox, inspector, view} = yield openRuleView();
+  let {view} = yield openRuleView();
+  yield testPressingEscapeRevertsChanges(view);
+  yield testPressingEscapeRevertsChangesAndDisables(view);
+});
 
-  info("Getting the filter swatch element");
-  let swatch = getRuleViewProperty(view, "body", "filter").valueSpan
-    .querySelector(".ruleview-filterswatch");
+function* testPressingEscapeRevertsChanges(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-filterswatch");
+  let filterTooltip = view.tooltips.filterEditor;
 
-  let filterTooltip = view.tooltips.filterEditor;
   let onShow = filterTooltip.tooltip.once("shown");
   swatch.click();
   yield onShow;
 
   let widget = yield filterTooltip.widget;
+  widget.setCssValue("blur(2px)");
+  yield ruleEditor.rule._applyingModifications;
 
-  widget.setCssValue("blur(2px)");
   yield waitForComputedStyleProperty("body", null, "filter", "blur(2px)");
-
-  ok(true, "Changes previewed on the element");
+  is(propEditor.valueSpan.textContent, "blur(2px)",
+    "Got expected property value.");
 
   info("Pressing ESCAPE to close the tooltip");
   EventUtils.sendKey("ESCAPE", widget.styleWindow);
+  yield ruleEditor.rule._applyingModifications;
 
-  yield waitForSuccess(() => {
-    const computed = content.getComputedStyle(content.document.body);
-    return computed.filter === "blur(2px) contrast(2)";
-  }, "Waiting for the change to be reverted on the element");
-});
+  yield waitForComputedStyleProperty("body", null, "filter",
+    "blur(2px) contrast(2)");
+  is(propEditor.valueSpan.textContent, "blur(2px) contrast(2)",
+    "Got expected property value.");
+}
+
+function* testPressingEscapeRevertsChangesAndDisables(view) {
+  let ruleEditor = getRuleViewRuleEditor(view, 1);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+  let swatch = propEditor.valueSpan.querySelector(".ruleview-filterswatch");
+  let filterTooltip = view.tooltips.filterEditor;
+
+  info("Disabling filter property");
+  propEditor.enable.click();
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled,
+    "filter property is disabled.");
+  let newValue = yield getRulePropertyValue("filter");
+  is(newValue, "", "filter should have been unset.");
+
+  let onShow = filterTooltip.tooltip.once("shown");
+  swatch.click();
+  yield onShow;
+
+  ok(!propEditor.element.classList.contains("ruleview-overridden"),
+    "property overridden is not displayed.");
+  is(propEditor.enable.style.visibility, "hidden",
+    "property enable checkbox is hidden.");
+
+  let widget = yield filterTooltip.widget;
+  widget.setCssValue("blur(2px)");
+  yield ruleEditor.rule._applyingModifications;
+
+  info("Pressing ESCAPE to close the tooltip");
+  EventUtils.sendKey("ESCAPE", widget.styleWindow);
+  yield ruleEditor.rule._applyingModifications;
+
+  ok(propEditor.element.classList.contains("ruleview-overridden"),
+    "property is overridden.");
+  is(propEditor.enable.style.visibility, "visible",
+    "property enable checkbox is visible.");
+  ok(!propEditor.enable.getAttribute("checked"),
+    "property enable checkbox is not checked.");
+  ok(!propEditor.prop.enabled, "filter property is disabled.");
+  newValue = yield getRulePropertyValue("filter");
+  is(newValue, "", "filter should have been unset.");
+  is(propEditor.valueSpan.textContent, "blur(2px) contrast(2)",
+    "Got expected property value.");
+}
+
+function* getRulePropertyValue(name) {
+  let propValue = yield executeInContent("Test:GetRulePropertyValue", {
+    styleSheetIndex: 0,
+    ruleIndex: 0,
+    name: name
+  });
+  return propValue;
+}