diff --git a/browser/devtools/styleinspector/rule-view.js b/browser/devtools/styleinspector/rule-view.js index 648aa840f01e..ce3387f46ddf 100644 --- a/browser/devtools/styleinspector/rule-view.js +++ b/browser/devtools/styleinspector/rule-view.js @@ -1116,7 +1116,7 @@ function CssRuleView(aInspector, aDoc, aStore, aPageStyle) { this.store = aStore || {}; this.pageStyle = aPageStyle; - this._highlightedElements = []; + this._editorsExpandedForFilter = []; this._outputParser = new OutputParser(); this._buildContextMenu = this._buildContextMenu.bind(this); @@ -1640,6 +1640,7 @@ CssRuleView.prototype = { this.searchField.removeAttribute("filled"); } + this._clearHighlights(); this._clearRules(); this._createEditors(); @@ -1701,7 +1702,7 @@ CssRuleView.prototype = { this._prefObserver.destroy(); this._outputParser = null; - this._highlightedElements = null; + this._editorsExpandedForFilter = null; // Remove context menu if (this._contextmenu) { @@ -1995,10 +1996,6 @@ CssRuleView.prototype = { return; } - if (this._highlightedElements.length > 0) { - this.clearHighlight(); - } - for (let rule of this._elementStyle.rules) { if (rule.domRule.system) { continue; @@ -2087,7 +2084,6 @@ CssRuleView.prototype = { for (let selectorNode of selectorNodes) { if (selectorNode.textContent.toLowerCase().includes(aValue)) { selectorNode.classList.add("ruleview-highlight"); - this._highlightedElements.push(selectorNode); isHighlighted = true; } } @@ -2105,37 +2101,106 @@ CssRuleView.prototype = { let propertyValue = textProp.editor.valueSpan.textContent.toLowerCase(); let propertyName = textProp.name.toLowerCase(); - // If the input value matches a property line like `font-family: arial`, - // then check to make sure the name and value match. Otherwise, just - // compare the input string directly against the name and value elements. - let matches = false; - if (propertyMatch && name && value) { - matches = propertyName.includes(name) && propertyValue.includes(value); - } else { - matches = (name && propertyName.includes(name)) || - (value && propertyValue.includes(value)); + let editor = textProp.editor; + + let isPropertyHighlighted = this._highlightMatches(editor.container, { + searchName: name, + searchValue: value, + propertyName: propertyName, + propertyValue: propertyValue, + propertyMatch: propertyMatch + }); + + let isComputedHighlighted = false; + + // Highlight search matches in the computed list of properties + for (let computed of textProp.computed) { + if (computed.element) { + let computedName = computed.name; + let computedValue = computed.value; + + isComputedHighlighted = this._highlightMatches(computed.element, { + searchName: name, + searchValue: value, + propertyName: computedName, + propertyValue: computedValue, + propertyMatch: propertyMatch + }) ? true : isComputedHighlighted; + } } - if (matches) { - // if (matchTextProperty || matchNameOrValue) { - textProp.editor.element.classList.add("ruleview-highlight"); - this._highlightedElements.push(textProp.editor.element); + if (isPropertyHighlighted || isComputedHighlighted) { isHighlighted = true; } + + // Expand the computed list if a computed rule is highlighted and the + // property rule is not highlighted + if (!isPropertyHighlighted && isComputedHighlighted && + !editor.computed.classList.contains("styleinspector-open")) { + editor.expandForFilter(); + this._editorsExpandedForFilter.push(editor); + } } return isHighlighted; }, /** - * Clear all search filter highlights in the panel. + * Helper function for highlightRules that carries out highlighting the given + * element if the provided search terms match the property, and returns + * a boolean indicating whether or not the search terms match. + * + * @param {DOMNode} aElement + * The node to highlight if search terms match + * @param {String} searchName + * The parsed search name + * @param {String} searchValue + * The parsed search value + * @param {String} propertyName + * The property name of a rule + * @param {String} propertyValue + * The property value of a rule + * @param {Boolean} propertyMatch + * Whether or not the search term matches a property line like + * `font-family: arial` */ - clearHighlight: function() { - for (let element of this._highlightedElements) { + _highlightMatches: function(aElement, { searchName, searchValue, propertyName, + propertyValue, propertyMatch }) { + let matches = false; + + // If the inputted search value matches a property line like + // `font-family: arial`, then check to make sure the name and value match. + // Otherwise, just compare the inputted search string directly against the + // name and value of the rule property. + if (propertyMatch && searchName && searchValue) { + matches = propertyName.includes(searchName) && + propertyValue.includes(searchValue); + } else { + matches = (searchName && propertyName.includes(searchName)) || + (searchValue && propertyValue.includes(searchValue)); + } + + if (matches) { + aElement.classList.add("ruleview-highlight"); + } + + return matches; + }, + + /** + * Clear all search filter highlights in the panel, and close the computed + * list if toggled opened + */ + _clearHighlights: function() { + for (let element of this.element.querySelectorAll(".ruleview-highlight")) { element.classList.remove("ruleview-highlight"); } - this._highlightedElements = []; + for (let editor of this._editorsExpandedForFilter) { + editor.collapseForFilter(); + } + + this._editorsExpandedForFilter = []; } }; @@ -2593,19 +2658,23 @@ TextPropertyEditor.prototype = { this.element = this.doc.createElementNS(HTML_NS, "li"); this.element.classList.add("ruleview-property"); + this.container = createChild(this.element, "div", { + class: "ruleview-propertycontainer" + }); + // The enable checkbox will disable or enable the rule. - this.enable = createChild(this.element, "div", { + this.enable = createChild(this.container, "div", { class: "ruleview-enableproperty theme-checkbox", tabindex: "-1" }); // Click to expand the computed properties of the text property. - this.expander = createChild(this.element, "span", { + this.expander = createChild(this.container, "span", { class: "ruleview-expander theme-twisty" }); this.expander.addEventListener("click", this._onExpandClicked, true); - this.nameContainer = createChild(this.element, "span", { + this.nameContainer = createChild(this.container, "span", { class: "ruleview-namecontainer" }); @@ -2621,8 +2690,8 @@ TextPropertyEditor.prototype = { // Create a span that will hold the property and semicolon. // Use this span to create a slightly larger click target // for the value. - let propertyContainer = createChild(this.element, "span", { - class: "ruleview-propertycontainer" + let propertyContainer = createChild(this.container, "span", { + class: "ruleview-propertyvaluecontainer" }); @@ -2655,7 +2724,7 @@ TextPropertyEditor.prototype = { appendText(propertyContainer, ";"); - this.warning = createChild(this.element, "div", { + this.warning = createChild(this.container, "div", { class: "ruleview-warning", hidden: "", title: CssLogic.l10n("rule.warning.title"), @@ -2948,6 +3017,10 @@ TextPropertyEditor.prototype = { }); appendText(li, ";"); + + // Store the computed style element for easy access when highlighting + // styles + computed.element = li; } // Show or hide the expander as needed. @@ -2973,16 +3046,46 @@ TextPropertyEditor.prototype = { }, /** - * Handles clicks on the computed property expander. + * Handles clicks on the computed property expander. If the computed list is + * open due to user expanding or style filtering, collapse the computed list + * and close the expander. Otherwise, add .styleinspector-open class which + * is used to expand the computed list and tracks whether or not the computed + * list is expanded by manually by the user. */ _onExpandClicked: function(aEvent) { - this.computed.classList.toggle("styleinspector-open"); - if (this.computed.classList.contains("styleinspector-open")) { - this.expander.setAttribute("open", "true"); + if (this.computed.classList.contains("filter-open") || + this.computed.classList.contains("styleinspector-open")) { + this.expander.removeAttribute("open"); + this.computed.classList.remove("filter-open"); + this.computed.classList.remove("styleinspector-open"); } else { + this.expander.setAttribute("open", "true"); + this.computed.classList.add("styleinspector-open"); + } + + aEvent.stopPropagation(); + }, + + /** + * Expands the computed list when a computed property is matched by the style + * filtering. The .filter-open class is used to track whether or not the + * computed list was toggled opened by the filter. + */ + expandForFilter: function() { + if (!this.computed.classList.contains("styleinspector-open")) { + this.computed.classList.add("filter-open"); + this.expander.setAttribute("open", "true"); + } + }, + + /** + * Collapses the computed list that was expanded by style filtering. + */ + collapseForFilter: function() { + this.computed.classList.remove("filter-open"); + if (!this.computed.classList.contains("styleinspector-open")) { this.expander.removeAttribute("open"); } - aEvent.stopPropagation(); }, /** diff --git a/browser/devtools/styleinspector/ruleview.css b/browser/devtools/styleinspector/ruleview.css index 398850079859..25c88f7d3c02 100644 --- a/browser/devtools/styleinspector/ruleview.css +++ b/browser/devtools/styleinspector/ruleview.css @@ -47,12 +47,12 @@ body { cursor: text; } -.ruleview-propertycontainer { +.ruleview-propertyvaluecontainer { cursor: text; padding-right: 15px; } -.ruleview-propertycontainer a { +.ruleview-propertyvaluecontainer a { cursor: pointer; } @@ -61,6 +61,10 @@ body { display: none; } +.ruleview-computedlist.filter-open { + display: block; +} + .ruleview-expandable-container { display: none; } diff --git a/browser/devtools/styleinspector/test/browser.ini b/browser/devtools/styleinspector/test/browser.ini index c536c6edeb9d..51c2c4eef203 100644 --- a/browser/devtools/styleinspector/test/browser.ini +++ b/browser/devtools/styleinspector/test/browser.ini @@ -112,6 +112,14 @@ skip-if = e10s # Bug 1090340 [browser_ruleview_refresh-on-attribute-change_01.js] [browser_ruleview_refresh-on-attribute-change_02.js] [browser_ruleview_refresh-on-style-change.js] +[browser_ruleview_search-filter-computed-list_01.js] +[browser_ruleview_search-filter-computed-list_02.js] +[browser_ruleview_search-filter-computed-list_03.js] +[browser_ruleview_search-filter-computed-list_04.js] +[browser_ruleview_search-filter-computed-list_05.js] +[browser_ruleview_search-filter-computed-list_06.js] +[browser_ruleview_search-filter-computed-list_clear.js] +[browser_ruleview_search-filter-computed-list_expander.js] [browser_ruleview_search-filter_01.js] [browser_ruleview_search-filter_02.js] [browser_ruleview_search-filter_03.js] diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js new file mode 100644 index 000000000000..adfbcc215d2d --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_01.js @@ -0,0 +1,66 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// for property values. + +const SEARCH = "0px" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); + + ok(!computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is not highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(!computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is not highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js new file mode 100644 index 000000000000..9c5b4f0397dd --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_02.js @@ -0,0 +1,66 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// for property names. + +const SEARCH = "margin" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is correctly highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is correctly highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js new file mode 100644 index 000000000000..7034a8496fa1 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_03.js @@ -0,0 +1,66 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// for property line input. + +const SEARCH = "margin-top:4px" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(ruleEditor.expander.getAttribute("open"), "Expander is open."); + ok(!ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is not highlighted."); + ok(computed.classList.contains("filter-open"), + "margin computed list is open."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is not highlighted."); + ok(!computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is not highlighted."); + ok(!computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is not highlighted."); + ok(!computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is not highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js new file mode 100644 index 000000000000..a0e92886f739 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_04.js @@ -0,0 +1,66 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// for parsed property value. + +const SEARCH = ":4px" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is correctly highlighted."); + ok(!computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is not highlighted."); + ok(computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is correctly highlighted."); + ok(!computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is not highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js new file mode 100644 index 000000000000..c3987d977e5c --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_05.js @@ -0,0 +1,66 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// for parsed property name. + +const SEARCH = "margin-top:" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(ruleEditor.expander.getAttribute("open"), "Expander is open."); + ok(!ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is not highlighted."); + ok(computed.classList.contains("filter-open"), + "margin computed list is open."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is correctly highlighted."); + ok(!computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is not highlighted."); + ok(!computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is not highlighted."); + ok(!computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is not highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js new file mode 100644 index 000000000000..4884cc9e0205 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_06.js @@ -0,0 +1,104 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter works properly in the computed list +// when modifying the existing search filter value + +const SEARCH = "margin-" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); + yield testRemoveTextInFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(ruleEditor.expander.getAttribute("open"), "Expander is open."); + ok(!ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is not highlighted."); + ok(computed.classList.contains("filter-open"), + "margin computed list is open."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is correctly highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is correctly highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} + +function* testRemoveTextInFilter(inspector, ruleView) { + info("Press backspace and set filter text to \"margin\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win); + yield inspector.once("ruleview-filtered"); + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); + + ok(computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is correctly highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is correctly highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js new file mode 100644 index 000000000000..1364793d3e3f --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_clear.js @@ -0,0 +1,94 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the rule view search filter clear button works properly and clears +// the highlighted rules in the computed list. + +const SEARCH = "0px" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testAddTextInFilter(inspector, view); + yield testClearSearchFilter(inspector, view); +}); + +function* testAddTextInFilter(inspector, ruleView) { + info("Setting filter text to \"" + SEARCH + "\""); + + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); + + ok(!computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is not highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(!computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is not highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} + +function* testClearSearchFilter(inspector, ruleView) { + info("Clearing the search filter"); + + let doc = ruleView.doc; + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let searchClearButton = ruleView.searchClearButton; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + EventUtils.synthesizeMouseAtCenter(searchClearButton, {}, win); + + yield onRuleViewFiltered; + + info("Check the search filter is cleared and no rules are highlighted"); + is(ruleView.element.children.length, 3, "Should have 3 rules."); + ok(!searchField.value, "Search filter is cleared"); + ok(!doc.querySelectorAll(".ruleview-highlight").length, + "No rules are higlighted"); + + let ruleEditor = getRuleViewRuleEditor(ruleView, 1).rule.textProps[0].editor; + let computed = ruleEditor.computed; + + ok(!ruleEditor.expander.getAttribute("open"), "Expander is closed."); + ok(!computed.classList.contains("filter-open"), + "margin computed list is closed."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js new file mode 100644 index 000000000000..ae13c0f9d6bc --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter-computed-list_expander.js @@ -0,0 +1,99 @@ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Tests that the expanded computed list for a property remains open after +// clearing the rule view search filter. + +const SEARCH = "0px" + +let TEST_URI = [ + '', + '

Styled Node

' +].join("\n"); + +add_task(function*() { + yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI)); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode("#testid", inspector); + yield testOpenExpanderAndAddTextInFilter(inspector, view); + yield testClearSearchFilter(inspector, view); +}); + +function* testOpenExpanderAndAddTextInFilter(inspector, ruleView) { + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + let rule = getRuleViewRuleEditor(ruleView, 1).rule; + let ruleEditor = rule.textProps[0].editor; + let computed = ruleEditor.computed; + + info("Opening the computed list of margin property") + ruleEditor.expander.click(); + + info("Setting filter text to \"" + SEARCH + "\""); + searchField.focus(); + synthesizeKeys(SEARCH, win); + yield onRuleViewFiltered; + + info("Check that the correct rules are visible"); + is(ruleView.element.children.length, 2, "Should have 2 rules."); + is(getRuleViewRuleEditor(ruleView, 0).rule.selectorText, "element", + "First rule is inline element."); + + is(rule.selectorText, "#testid", "Second rule is #testid."); + ok(ruleEditor.expander.getAttribute("open"), "Expander is open."); + ok(ruleEditor.container.classList.contains("ruleview-highlight"), + "margin text property is correctly highlighted."); + ok(!computed.classList.contains("filter-open"), + "margin computed list does not contain filter-open class."); + ok(computed.classList.contains("styleinspector-open"), + "margin computed list contains styleinspector-open class."); + + ok(!computed.children[0].classList.contains("ruleview-highlight"), + "margin-top computed property is not highlighted."); + ok(computed.children[1].classList.contains("ruleview-highlight"), + "margin-right computed property is correctly highlighted."); + ok(!computed.children[2].classList.contains("ruleview-highlight"), + "margin-bottom computed property is not highlighted."); + ok(computed.children[3].classList.contains("ruleview-highlight"), + "margin-left computed property is correctly highlighted."); +} + +function* testClearSearchFilter(inspector, ruleView) { + info("Clearing the search filter"); + + let doc = ruleView.doc; + let win = ruleView.doc.defaultView; + let searchField = ruleView.searchField; + let searchClearButton = ruleView.searchClearButton; + let onRuleViewFiltered = inspector.once("ruleview-filtered"); + + EventUtils.synthesizeMouseAtCenter(searchClearButton, {}, win); + + yield onRuleViewFiltered; + + info("Check the search filter is cleared and no rules are highlighted"); + is(ruleView.element.children.length, 3, "Should have 3 rules."); + ok(!searchField.value, "Search filter is cleared"); + ok(!doc.querySelectorAll(".ruleview-highlight").length, + "No rules are higlighted"); + + let ruleEditor = getRuleViewRuleEditor(ruleView, 1).rule.textProps[0].editor; + let computed = ruleEditor.computed; + + ok(ruleEditor.expander.getAttribute("open"), "Expander is open."); + ok(!computed.classList.contains("filter-open"), + "margin computed list does not contain filter-open class."); + ok(computed.classList.contains("styleinspector-open"), + "margin computed list contains styleinspector-open class."); +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js b/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js index b07a37056c4a..4e29d2ca77dc 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_search-filter_01.js @@ -6,6 +6,8 @@ // Tests that the rule view search filter works properly for property values. +const SEARCH = "00F"; + let TEST_URI = [ '