diff --git a/browser/devtools/styleinspector/test/browser.ini b/browser/devtools/styleinspector/test/browser.ini index b18aa29a6e37..ba2b398c1907 100644 --- a/browser/devtools/styleinspector/test/browser.ini +++ b/browser/devtools/styleinspector/test/browser.ini @@ -4,19 +4,31 @@ support-files = head.js browser_bug722196_identify_media_queries.html browser_styleinspector_bug_677930_urls_clickable/browser_styleinspector_bug_677930_urls_clickable.css + browser_bug683672.html + browser_bug705707_is_content_stylesheet.html + browser_bug705707_is_content_stylesheet_imported.css + browser_bug705707_is_content_stylesheet_imported2.css + browser_bug705707_is_content_stylesheet_linked.css + browser_bug705707_is_content_stylesheet_script.css + browser_bug705707_is_content_stylesheet.xul + browser_bug705707_is_content_stylesheet_xul.css + test-image.png + browser_styleinspector_bug_677930_urls_clickable.html + browser_ruleview_pseudoelement.html + sourcemaps.html + sourcemaps.css + sourcemaps.css.map + sourcemaps.scss + browser_ruleview_734259_style_editor_link.css [browser_bug683672.js] -support-files = browser_bug683672.html [browser_styleinspector_bug_672746_default_styles.js] [browser_styleinspector_bug_672744_search_filter.js] [browser_bug589375_keybindings.js] -skip-if = true # awaiting promise-based init [browser_styleinspector_bug_689759_no_results_placeholder.js] [browser_bug_692400_element_style.js] [browser_csslogic_inherited.js] [browser_ruleview_734259_style_editor_link.js] -support-files = - browser_ruleview_734259_style_editor_link.css [browser_ruleview_editor.js] [browser_ruleview_editor_changedvalues.js] [browser_ruleview_copy.js] @@ -29,14 +41,6 @@ support-files = [browser_ruleview_update.js] [browser_ruleview_livepreview.js] [browser_bug705707_is_content_stylesheet.js] -support-files = - browser_bug705707_is_content_stylesheet.html - browser_bug705707_is_content_stylesheet_imported.css - browser_bug705707_is_content_stylesheet_imported2.css - browser_bug705707_is_content_stylesheet_linked.css - browser_bug705707_is_content_stylesheet_script.css - browser_bug705707_is_content_stylesheet.xul - browser_bug705707_is_content_stylesheet_xul.css [browser_bug722196_property_view_media_queries.js] [browser_bug722196_rule_view_media_queries.js] [browser_bug_592743_specificity.js] @@ -44,16 +48,12 @@ support-files = [browser_computedview_734259_style_editor_link.js] [browser_computedview_copy.js] [browser_styleinspector_bug_677930_urls_clickable.js] -support-files = - test-image.png - browser_styleinspector_bug_677930_urls_clickable.html [browser_bug893965_css_property_completion_new_property.js] [browser_bug893965_css_property_completion_existing_property.js] [browser_bug894376_css_value_completion_new_property_value_pair.js] [browser_bug894376_css_value_completion_existing_property_value_pair.js] [browser_ruleview_bug_902966_revert_value_on_ESC.js] [browser_ruleview_pseudoelement.js] -support-files = browser_ruleview_pseudoelement.html [browser_computedview_bug835808_keyboard_nav.js] [browser_bug913014_matched_expand.js] [browser_bug765105_background_image_tooltip.js] @@ -62,11 +62,6 @@ support-files = browser_ruleview_pseudoelement.html [browser_bug702577_fontfamily_tooltip_longhand.js] [browser_bug940500_rule_view_pick_gradient_color.js] [browser_ruleview_original_source_link.js] -support-files = - sourcemaps.html - sourcemaps.css - sourcemaps.css.map - sourcemaps.scss [browser_computedview_original_source_link.js] [browser_bug946331_close_tooltip_on_new_selection.js] [browser_bug942297_user_property_reset.js] @@ -80,3 +75,4 @@ support-files = [browser_ruleview_colorpicker-and-image-tooltip_01.js] [browser_ruleview_colorpicker-and-image-tooltip_02.js] [browser_ruleview_colorpicker-multiple-changes.js] +[browser_ruleview_add_property_01.js] diff --git a/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js b/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js index c19529f889c8..6e5a25801461 100644 --- a/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js +++ b/browser/devtools/styleinspector/test/browser_bug589375_keybindings.js @@ -1,92 +1,44 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -// Tests that the key bindings work properly. +"use strict"; -let doc; -let inspector; -let computedView; -let iframe; +// Test computed view key bindings -function createDocument() -{ - doc.body.innerHTML = '' + 'Some styled text' + ''; - doc.title = "Style Inspector key binding test"; - openInspector(openComputedView); -} + let {toolbox, inspector, view} = yield openComputedView(); -function openComputedView(aInspector) -{ - inspector = aInspector; - iframe = inspector._toolbox.frame; + info("Selecting the test node"); + yield selectNode(".matches", inspector); - Services.obs.addObserver(runTests, "StyleInspector-populated", false); - - inspector.sidebar.select("computedview"); -} - -function runTests() -{ - Services.obs.removeObserver(runTests, "StyleInspector-populated"); - computedView = getComputedView(); - - var span = doc.querySelector(".matches"); - ok(span, "captain, we have the matches span"); - - inspector.selection.setNode(span); - - is(span, computedView.viewedElement, - "style inspector node matches the selected node"); - is(computedView.viewedElement, computedView.cssLogic.viewedElement, - "cssLogic node matches the cssHtmlTree node"); - - info("checking keybindings"); - - let searchbar = computedView.searchField; - let propView = getFirstVisiblePropertyView(); + let propView = getFirstVisiblePropertyView(view); let rulesTable = propView.matchedSelectorsContainer; - let matchedExpander = propView.matchedExpander; + let matchedExpander = propView.element; - info("Adding focus event handler to search filter"); - searchbar.addEventListener("focus", function searchbarFocused() { - searchbar.removeEventListener("focus", searchbarFocused); - info("search filter is focused"); - info("tabbing to property expander node"); - EventUtils.synthesizeKey("VK_TAB", {}, iframe.contentWindow); - }); + info("Focusing the property"); + let onMatchedExpanderFocus = once(matchedExpander, "focus", true); + EventUtils.synthesizeMouseAtCenter(matchedExpander, {}, view.styleWindow); + yield onMatchedExpanderFocus; - info("Adding focus event handler to property expander"); - matchedExpander.addEventListener("focus", function expanderFocused() { - matchedExpander.removeEventListener("focus", expanderFocused); - info("property expander is focused"); - info("checking expand / collapse"); - testKey(iframe.contentWindow, "VK_SPACE", rulesTable); - testKey(iframe.contentWindow, "VK_RETURN", rulesTable); + yield checkToggleKeyBinding(view.styleWindow, "VK_SPACE", rulesTable, inspector); + yield checkToggleKeyBinding(view.styleWindow, "VK_RETURN", rulesTable, inspector); + yield checkHelpLinkKeybinding(view); +}); - checkHelpLinkKeybinding(); - computedView.destroy(); - finishUp(); - }); - - info("Making sure that the style inspector panel is focused"); - SimpleTest.waitForFocus(function windowFocused() { - info("window is focused"); - info("focusing search filter"); - searchbar.focus(); - }, iframe.contentWindow); -} - -function getFirstVisiblePropertyView() -{ +function getFirstVisiblePropertyView(view) { let propView = null; - computedView.propertyViews.some(function(aPropView) { - if (aPropView.visible) { - propView = aPropView; + view.propertyViews.some(p => { + if (p.visible) { + propView = p; return true; } return false; @@ -95,47 +47,33 @@ function getFirstVisiblePropertyView() return propView; } -function testKey(aContext, aVirtKey, aRulesTable) -{ - info("testing " + aVirtKey + " key"); - info("expanding rules table"); - EventUtils.synthesizeKey(aVirtKey, {}, aContext); - isnot(aRulesTable.innerHTML, "", "rules Table is populated"); - info("collapsing rules table"); - EventUtils.synthesizeKey(aVirtKey, {}, aContext); - is(aRulesTable.innerHTML, "", "rules Table is not populated"); +function* checkToggleKeyBinding(win, key, rulesTable, inspector) { + info("Pressing " + key + " key a couple of times to check that the property gets expanded/collapsed"); + + let onExpand = inspector.once("computed-view-property-expanded"); + let onCollapse = inspector.once("computed-view-property-collapsed"); + + info("Expanding the property"); + EventUtils.synthesizeKey(key, {}, win); + yield onExpand; + isnot(rulesTable.innerHTML, "", "The property has been expanded"); + + info("Collapsing the property"); + EventUtils.synthesizeKey(key, {}, win); + yield onCollapse; + is(rulesTable.innerHTML, "", "The property has been collapsed"); } -function checkHelpLinkKeybinding() -{ - info("checking help link keybinding"); - let propView = getFirstVisiblePropertyView(); +function checkHelpLinkKeybinding(view) { + info("Check that MDN link is opened on \"F1\""); + let def = promise.defer(); - info("check that MDN link is opened on \"F1\""); - let linkClicked = false; + let propView = getFirstVisiblePropertyView(view); propView.mdnLinkClick = function(aEvent) { - linkClicked = true; + ok(true, "Pressing F1 opened the MDN link"); + def.resolve(); }; - EventUtils.synthesizeKey("VK_F1", {}, iframe.contentWindow); - is(linkClicked, true, "MDN link will be shown"); -} -function finishUp() -{ - doc = inspector = iframe = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,default styles test"; + EventUtils.synthesizeKey("VK_F1", {}, view.styleWindow); + return def.promise; } diff --git a/browser/devtools/styleinspector/test/browser_bug683672.js b/browser/devtools/styleinspector/test/browser_bug683672.js index bc885c5d5daa..467a921e77d5 100644 --- a/browser/devtools/styleinspector/test/browser_bug683672.js +++ b/browser/devtools/styleinspector/test/browser_bug683672.js @@ -1,79 +1,36 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -// Tests that the style inspector works properly +"use strict"; -let doc; -let inspector; -let div; -let computedView; +// Checking selector counts, matched rules and titles in the computed-view -const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/test/browser_bug683672.html"; +const {PropertyView} = devtools.require("devtools/styleinspector/computed-view"); +const TEST_URI = TEST_URL_ROOT + "browser_bug683672.html"; -let tempScope = {}; -let {CssHtmlTree, PropertyView} = devtools.require("devtools/styleinspector/computed-view"); -let {console} = Cu.import("resource://gre/modules/devtools/Console.jsm", {}); +let test = asyncTest(function*() { + yield addTab(TEST_URI); + let {toolbox, inspector, view} = yield openComputedView(); -function test() -{ - waitForExplicitFinish(); - addTab(TEST_URI); - browser.addEventListener("load", tabLoaded, true); -} + yield selectNode("#test", inspector); + yield testMatchedSelectors(view); +}); -function tabLoaded() -{ - browser.removeEventListener("load", tabLoaded, true); - doc = content.document; - openComputedView(selectNode); -} - -function selectNode(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; - - div = content.document.getElementById("test"); - ok(div, "captain, we have the div"); - - inspector.selection.setNode(div); - inspector.once("inspector-updated", runTests); -} - -function runTests() -{ - testMatchedSelectors().then(() => { - info("finishing up"); - finishUp(); - }); -} - -function testMatchedSelectors() -{ +function* testMatchedSelectors(view) { info("checking selector counts, matched rules and titles"); - is(div, computedView.viewedElement.rawNode(), + is(getNode("#test"), view.viewedElement.rawNode(), "style inspector node matches the selected node"); - let propertyView = new PropertyView(computedView, "color"); + let propertyView = new PropertyView(view, "color"); propertyView.buildMain(); propertyView.buildSelectorContainer(); propertyView.matchedExpanded = true; - return propertyView.refreshMatchedSelectors().then(() => { - let numMatchedSelectors = propertyView.matchedSelectors.length; - is(numMatchedSelectors, 6, - "CssLogic returns the correct number of matched selectors for div"); + yield propertyView.refreshMatchedSelectors(); - is(propertyView.hasMatchedSelectors, true, - "hasMatchedSelectors returns true"); - }).then(null, (err) => console.error(err)); -} - -function finishUp() -{ - doc = inspector = div = computedView = null; - gBrowser.removeCurrentTab(); - finish(); + let numMatchedSelectors = propertyView.matchedSelectors.length; + is(numMatchedSelectors, 6, "CssLogic returns the correct number of matched selectors for div"); + is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors returns true"); } diff --git a/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js b/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js index b511888325c0..3ae695d56e0c 100644 --- a/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js +++ b/browser/devtools/styleinspector/test/browser_bug702577_fontfamily_tooltip_longhand.js @@ -1,11 +1,10 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ -let contentDoc; -let inspector; -let ruleView; -let computedView; +"use strict"; + +// Test the fontfamily tooltip on longhand properties const PAGE_CONTENT = [ '"; } -function finishUp() -{ - CssLogic = CssSelector = tempScope = null; - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,Computed view specificity test"; +function getExpectedSpecificity(selectorText) { + return TEST_DATA.filter(i=>i.text === selectorText)[0].expected; } diff --git a/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js b/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js index 2f3d464f2b58..6b789ca8a6ca 100644 --- a/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js +++ b/browser/devtools/styleinspector/test/browser_bug_692400_element_style.js @@ -1,77 +1,44 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -// Tests for selector text errors. +"use strict"; -let doc; -let computedView; +// Tests for matched selector texts in the computed view -function createDocument() -{ - doc.body.innerHTML = "
"; +let test = asyncTest(function*() { + yield addTab("data:text/html,
"); - doc.title = "Style Inspector Selector Text Test"; + info("Opening the computed view"); + let {toolbox, inspector, view} = yield openComputedView(); - openComputedView(startTests); -} + info("Selecting the test node"); + yield selectNode("div", inspector); + info("Checking the color property view"); + let propertyView = getPropertyView(view, "color"); + ok(propertyView, "found PropertyView for color"); + is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true"); -function startTests(aInspector, aComputedView) -{ - computedView = aComputedView; + info("Expanding the matched selectors"); + propertyView.matchedExpanded = true; + yield propertyView.refreshMatchedSelectors(); - let div = doc.querySelector("div"); - ok(div, "captain, we have the test div"); + let span = propertyView.matchedSelectorsContainer.querySelector("span.rule-text"); + ok(span, "Found the first table row"); - aInspector.selection.setNode(div); - aInspector.once("inspector-updated", SI_checkText); -} + let selector = propertyView.matchedSelectorViews[0]; + ok(selector, "Found the first matched selector view"); +}); -function SI_checkText() -{ +function getPropertyView(computedView, name) { let propertyView = null; - computedView.propertyViews.some(function(aView) { - if (aView.name == "color") { - propertyView = aView; + computedView.propertyViews.some(function(view) { + if (view.name == name) { + propertyView = view; return true; } return false; }); - - ok(propertyView, "found PropertyView for color"); - - is(propertyView.hasMatchedSelectors, true, "hasMatchedSelectors is true"); - - propertyView.matchedExpanded = true; - propertyView.refreshMatchedSelectors().then(() => { - - let span = propertyView.matchedSelectorsContainer.querySelector("span.rule-text"); - ok(span, "found the first table row"); - - let selector = propertyView.matchedSelectorViews[0]; - ok(selector, "found the first matched selector view"); - - finishUp(); - }); -} - -function finishUp() -{ - doc = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,selector text test, bug 692400"; + return propertyView; } diff --git a/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js b/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js index c4a73e4798cc..488fe0804c36 100644 --- a/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js +++ b/browser/devtools/styleinspector/test/browser_computedview_734259_style_editor_link.js @@ -2,9 +2,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let inspector; -let computedView; +"use strict"; + +// Test the links from the computed view to the style editor const STYLESHEET_URL = "data:text/css,"+encodeURIComponent( [".highlight {", @@ -40,128 +40,75 @@ const DOCUMENT_URL = "data:text/html,"+encodeURIComponent( '', ''].join("\n")); +let test = asyncTest(function*() { + yield addTab(DOCUMENT_URL); + info("Opening the computed-view"); + let {toolbox, inspector, view} = yield openComputedView(); -function selectNode(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; + info("Selecting the test node"); + yield selectNode("span", inspector); - let span = doc.querySelector("span"); - ok(span, "captain, we have the span"); + yield testInlineStyle(view, inspector); + yield testInlineStyleSheet(view, toolbox); + yield testExternalStyleSheet(view, toolbox); +}); - inspector.selection.setNode(span); - inspector.once("inspector-updated", testInlineStyle); -} +function* testInlineStyle(view, inspector) { + info("Testing inline style"); -function testInlineStyle() -{ - expandProperty(0, function propertyExpanded() { - Services.ww.registerNotification(function onWindow(aSubject, aTopic) { - if (aTopic != "domwindowopened") { - return; - } - info("window opened"); - let win = aSubject.QueryInterface(Ci.nsIDOMWindow); - win.addEventListener("load", function windowLoad() { - win.removeEventListener("load", windowLoad); - info("window load completed"); - let windowType = win.document.documentElement.getAttribute("windowtype"); - is(windowType, "navigator:view-source", "view source window is open"); - info("closing window"); - win.close(); - Services.ww.unregisterNotification(onWindow); - executeSoon(() => { - testInlineStyleSheet(); - }); - }); - }); - let link = getLinkByIndex(0); - link.click(); - }); -} + yield expandComputedViewPropertyByIndex(view, inspector, 0); -function testInlineStyleSheet() -{ - info("clicking an inline stylesheet"); - - let target = TargetFactory.forTab(gBrowser.selectedTab); - let toolbox = gDevTools.getToolbox(target); - toolbox.once("styleeditor-selected", () => { - let panel = toolbox.getCurrentPanel(); - - panel.UI.once("editor-selected", (event, editor) => { - validateStyleEditorSheet(editor, 0); - executeSoon(() => { - testExternalStyleSheet(toolbox); - }); - }); - }); - - let link = getLinkByIndex(2); + let onWindow = waitForWindow(); + info("Clicking on the first rule-link in the computed-view"); + let link = getComputedViewLinkByIndex(view, 0); link.click(); + + let win = yield onWindow; + + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "navigator:view-source", "View source window is open"); + info("Closing window"); + win.close(); } -function testExternalStyleSheet(toolbox) { - info ("clicking an external stylesheet"); +function* testInlineStyleSheet(view, toolbox) { + info("Testing inline stylesheet"); + info("Listening for toolbox switch to the styleeditor"); + let onSwitch = waitForStyleEditor(toolbox); + + info("Clicking an inline stylesheet"); + let link = getComputedViewLinkByIndex(view, 2); + link.click(); + let editor = yield onSwitch; + + ok(true, "Switched to the style-editor panel in the toolbox"); + + validateStyleEditorSheet(editor, 0); +} + +function* testExternalStyleSheet(view, toolbox) { + info("Testing external stylesheet"); + + info("Waiting for the stylesheet editor to be selected"); let panel = toolbox.getCurrentPanel(); - panel.UI.once("editor-selected", (event, editor) => { - is(toolbox.currentToolId, "styleeditor", "style editor selected"); - validateStyleEditorSheet(editor, 1); - finishUp(); - }); + let onSelected = panel.UI.once("editor-selected"); - toolbox.selectTool("inspector").then(function () { - info("inspector selected"); - let link = getLinkByIndex(1); - link.click(); - }); + info("Switching back to the inspector panel in the toolbox"); + yield toolbox.selectTool("inspector"); + + info("Clicking on an external stylesheet link"); + let link = getComputedViewLinkByIndex(view, 1); + link.click(); + let editor = yield onSelected; + + is(toolbox.currentToolId, "styleeditor", "The style editor is selected again"); + validateStyleEditorSheet(editor, 1); } -function validateStyleEditorSheet(aEditor, aExpectedSheetIndex) -{ - info("validating style editor stylesheet"); - let sheet = doc.styleSheets[aExpectedSheetIndex]; - is(aEditor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet"); -} - -function expandProperty(aIndex, aCallback) -{ - info("expanding property " + aIndex); - let contentDoc = computedView.styleDocument; - let expando = contentDoc.querySelectorAll(".expandable")[aIndex]; - - expando.click(); - - inspector.once("computed-view-property-expanded", aCallback); -} - -function getLinkByIndex(aIndex) -{ - let contentDoc = computedView.styleDocument; - let links = contentDoc.querySelectorAll(".rule-link .link"); - return links[aIndex]; -} - -function finishUp() -{ - doc = inspector = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(function () { openComputedView(selectNode); }, content); - }, true); - - content.location = DOCUMENT_URL; +function validateStyleEditorSheet(editor, expectedSheetIndex) { + info("Validating style editor stylesheet"); + let sheet = content.document.styleSheets[expectedSheetIndex]; + is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet"); } diff --git a/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js b/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js index 2a13bb2aad5d..e9fd9dbfd5f1 100644 --- a/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js +++ b/browser/devtools/styleinspector/test/browser_computedview_bug835808_keyboard_nav.js @@ -1,28 +1,15 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ -// Tests that the style inspector works properly +"use strict"; -let doc, computedView, inspector; +// Tests the computed-view keyboard navigation -function test() -{ - waitForExplicitFinish(); +let test = asyncTest(function*() { + yield addTab("data:text/html,computed view keyboard nav test"); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad(evt) { - gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,computed view context menu test"; -} - -function createDocument() -{ - doc.body.innerHTML = '
\n' + @@ -38,57 +25,38 @@ function createDocument() '

more text

\n' + '

even more text

' + '
'; - doc.title = "Computed view keyboard navigation test"; + content.document.title = "Computed view keyboard navigation test"; - openComputedView(startTests); -} + info("Opening the computed-view"); + let {toolbox, inspector, view} = yield openComputedView(); -function startTests(aInspector, aComputedView) -{ - computedView = aComputedView; - inspector = aInspector; - testTabThrougStyles(); -} + info("Selecting the test node"); + yield selectNode("span", inspector); -function endTests() -{ - computedView = inspector = doc = null; - gBrowser.removeCurrentTab(); - finish(); -} + info("Selecting the first computed style in the list"); + let firstStyle = view.styleDocument.querySelector(".property-view"); + ok(firstStyle, "First computed style found in panel"); + firstStyle.focus(); -function testTabThrougStyles() -{ - let span = doc.querySelector("span"); + info("Tab to select the 2nd style and press return"); + let onExpanded = inspector.once("computed-view-property-expanded"); + EventUtils.synthesizeKey("VK_TAB", {}); + EventUtils.synthesizeKey("VK_RETURN", {}); + yield onExpanded; - inspector.once("computed-view-refreshed", () => { - // Selecting the first computed style in the list - let firstStyle = computedView.styleDocument.querySelector(".property-view"); - ok(firstStyle, "First computed style found in panel"); - firstStyle.focus(); + info("Verify the 2nd style has been expanded"); + let secondStyleSelectors = view.styleDocument.querySelectorAll( + ".property-content .matchedselectors")[1]; + ok(secondStyleSelectors.childNodes.length > 0, "Matched selectors expanded"); - // Tab to select the 2nd style, press return - EventUtils.synthesizeKey("VK_TAB", {}); - EventUtils.synthesizeKey("VK_RETURN", {}); - inspector.once("computed-view-property-expanded", () => { - // Verify the 2nd style has been expanded - let secondStyleSelectors = computedView.styleDocument.querySelectorAll( - ".property-content .matchedselectors")[1]; - ok(secondStyleSelectors.childNodes.length > 0, "Matched selectors expanded"); + info("Tab back up and test the same thing, with space"); + let onExpanded = inspector.once("computed-view-property-expanded"); + EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}); + EventUtils.synthesizeKey("VK_SPACE", {}); + yield onExpanded; - // Tab back up and test the same thing, with space - EventUtils.synthesizeKey("VK_TAB", {shiftKey: true}); - EventUtils.synthesizeKey("VK_SPACE", {}); - inspector.once("computed-view-property-expanded", () => { - // Verify the 1st style has been expanded too - let firstStyleSelectors = computedView.styleDocument.querySelectorAll( - ".property-content .matchedselectors")[0]; - ok(firstStyleSelectors.childNodes.length > 0, "Matched selectors expanded"); - - endTests(); - }); - }); - }); - - inspector.selection.setNode(span); -} + info("Verify the 1st style has been expanded too"); + let firstStyleSelectors = view.styleDocument.querySelectorAll( + ".property-content .matchedselectors")[0]; + ok(firstStyleSelectors.childNodes.length > 0, "Matched selectors expanded"); +}); diff --git a/browser/devtools/styleinspector/test/browser_computedview_copy.js b/browser/devtools/styleinspector/test/browser_computedview_copy.js index 0d73b88cb7df..8a583fd65ea4 100644 --- a/browser/devtools/styleinspector/test/browser_computedview_copy.js +++ b/browser/devtools/styleinspector/test/browser_computedview_copy.js @@ -1,20 +1,20 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ -// Tests that the style inspector works properly +"use strict"; -let doc; -let win; -let computedView; +// Tests that properties can be selected and copied from the computed view XPCOMUtils.defineLazyGetter(this, "osString", function() { return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; }); -function createDocument() -{ - doc.body.innerHTML = '
\n' + @@ -30,132 +30,89 @@ function createDocument() '

more text

\n' + '

even more text

' + '
'; - doc.title = "Computed view context menu test"; + content.document.title = "Computed view context menu test"; - openComputedView(selectNode); -} + info("Opening the computed view"); + let {toolbox, inspector, view} = yield openComputedView(); -function selectNode(aInspector, aComputedView) -{ - computedView = aComputedView; - win = aInspector.sidebar.getWindowForTab("computedview"); + info("Selecting the test node"); + yield selectNode("span", inspector); - let span = doc.querySelector("span"); - ok(span, "captain, we have the span"); + yield checkCopySelection(view); + yield checkSelectAll(view); +}); - aInspector.selection.setNode(span); - aInspector.once("inspector-updated", runStyleInspectorTests); -} +function checkCopySelection(view) { + info("Testing selection copy"); - -function runStyleInspectorTests() -{ - let contentDocument = computedView.styleDocument; - let prop = contentDocument.querySelector(".property-view"); - ok(prop, "captain, we have the property-view node"); - - checkCopySelection(); -} - -function checkCopySelection() -{ - let contentDocument = computedView.styleDocument; + let contentDocument = view.styleDocument; let props = contentDocument.querySelectorAll(".property-view"); ok(props, "captain, we have the property-view nodes"); - let range = document.createRange(); + let range = contentDocument.createRange(); range.setStart(props[1], 0); range.setEnd(props[3], 3); - win.getSelection().addRange(range); + contentDocument.defaultView.getSelection().addRange(range); - info("Checking that cssHtmlTree.siBoundCopy() " + - " returns the correct clipboard value"); + info("Checking that cssHtmlTree.siBoundCopy() returns the correct clipboard value"); let expectedPattern = "font-family: helvetica,sans-serif;[\\r\\n]+" + "font-size: 16px;[\\r\\n]+" + "font-variant: small-caps;[\\r\\n]*"; - SimpleTest.waitForClipboard(function CS_boundCopyCheck() { - return checkClipboardData(expectedPattern); - }, - function() { + return waitForClipboard(() => { fireCopyEvent(props[0]); - }, - checkSelectAll, - function() { - failedClipboard(expectedPattern, checkSelectAll); + }, () => { + return checkClipboardData(expectedPattern); + }).then(() => {}, () => { + failedClipboard(expectedPattern); }); } -function checkSelectAll() -{ - let contentDoc = computedView.styleDocument; +function checkSelectAll(view) { + info("Testing select-all copy"); + + let contentDoc = view.styleDocument; let prop = contentDoc.querySelector(".property-view"); info("Checking that _SelectAll() then copy returns the correct clipboard value"); - computedView._onSelectAll(); + view._onSelectAll(); let expectedPattern = "color: #FF0;[\\r\\n]+" + "font-family: helvetica,sans-serif;[\\r\\n]+" + "font-size: 16px;[\\r\\n]+" + "font-variant: small-caps;[\\r\\n]*"; - SimpleTest.waitForClipboard(function() { - return checkClipboardData(expectedPattern); - }, - function() { + return waitForClipboard(() => { fireCopyEvent(prop); - }, - finishUp, - function() { - failedClipboard(expectedPattern, finishUp); + }, () => { + return checkClipboardData(expectedPattern); + }).then(() => {}, () => { + failedClipboard(expectedPattern); }); } -function checkClipboardData(aExpectedPattern) -{ +function checkClipboardData(expectedPattern) { let actual = SpecialPowers.getClipboardData("text/unicode"); - let expectedRegExp = new RegExp(aExpectedPattern, "g"); + let expectedRegExp = new RegExp(expectedPattern, "g"); return expectedRegExp.test(actual); } -function failedClipboard(aExpectedPattern, aCallback) -{ +function failedClipboard(expectedPattern) { // Format expected text for comparison let terminator = osString == "WINNT" ? "\r\n" : "\n"; - aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); - aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); - aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); + expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); + expectedPattern = expectedPattern.replace(/\\\(/g, "("); + expectedPattern = expectedPattern.replace(/\\\)/g, ")"); let actual = SpecialPowers.getClipboardData("text/unicode"); // Trim the right hand side of our strings. This is because expectedPattern // accounts for windows sometimes adding a newline to our copied data. - aExpectedPattern = aExpectedPattern.trimRight(); + expectedPattern = expectedPattern.trimRight(); actual = actual.trimRight(); dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + "results (escaped for accurate comparison):\n"); info("Actual: " + escape(actual)); - info("Expected: " + escape(aExpectedPattern)); - aCallback(); -} - -function finishUp() -{ - computedView = doc = win = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,computed view context menu test"; + info("Expected: " + escape(expectedPattern)); } diff --git a/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js b/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js index ef2e3ab8a2c8..c44e8638b5f9 100644 --- a/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js +++ b/browser/devtools/styleinspector/test/browser_computedview_original_source_link.js @@ -2,136 +2,67 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let win; -let doc; -let inspector; -let computedView; -let toolbox; +"use strict"; -const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps.html"; +// Test that the computed view shows the original source link when source maps +// are enabled + +const TESTCASE_URI = TEST_URL_ROOT_SSL + "sourcemaps.html"; const PREF = "devtools.styleeditor.source-maps-enabled"; - const SCSS_LOC = "sourcemaps.scss:4"; const CSS_LOC = "sourcemaps.css:1"; -function test() -{ - waitForExplicitFinish(); - +let test = asyncTest(function*() { + info("Turning the pref " + PREF + " on"); Services.prefs.setBoolPref(PREF, true); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(function () { openComputedView(highlightNode); }, content); - }, true); + yield addTab(TESTCASE_URI); + let {toolbox, inspector, view} = yield openComputedView(); - content.location = TESTCASE_URI; -} + info("Select the test node"); + yield selectNode("div", inspector); -function highlightNode(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; + info("Expanding the first property"); + yield expandComputedViewPropertyByIndex(view, inspector, 0); - // Highlight a node. - let div = content.document.getElementsByTagName("div")[0]; - ok(div, "div to select exists") + info("Verifying the link text"); + yield verifyLinkText(view, SCSS_LOC); - inspector.selection.setNode(div); - inspector.once("inspector-updated", () => { - is(inspector.selection.node, div, "selection matches the div element"); - - expandProperty(0, testComputedViewLink); - }); -} - -function testComputedViewLink() { - verifyLinkText(SCSS_LOC, testTogglePref); -} - -function testTogglePref() { + info("Toggling the pref"); Services.prefs.setBoolPref(PREF, false); - verifyLinkText(CSS_LOC, () => { - Services.prefs.setBoolPref(PREF, true); + info("Verifying that the link text has changed after the pref change"); + yield verifyLinkText(view, CSS_LOC); - testClickingLink(); - }) -} + info("Toggling the pref again"); + Services.prefs.setBoolPref(PREF, true); -function testClickingLink() { - let target = TargetFactory.forTab(gBrowser.selectedTab); - let toolbox = gDevTools.getToolbox(target); + info("Testing that clicking on the link works"); + yield testClickingLink(toolbox, view); - toolbox.once("styleeditor-ready", function(id, aToolbox) { - let panel = toolbox.getCurrentPanel(); - panel.UI.on("editor-selected", (event, editor) => { - // The style editor selects the first sheet at first load before - // selecting the desired sheet. - if (editor.styleSheet.href.endsWith("scss")) { - info("original source editor selected"); - editor.getSourceEditor().then(editorSelected); - } - }); - }); + info("Turning the pref " + PREF + " off"); + Services.prefs.clearUserPref(PREF); +}); - let link = getLinkByIndex(0); +function* testClickingLink(toolbox, view) { + let onEditor = waitForStyleEditor(toolbox, "sourcemaps.scss"); - info("clicking rule view link"); + info("Clicking the computedview stylesheet link"); + let link = getComputedViewLinkByIndex(view, 0); link.scrollIntoView(); link.click(); -} -function editorSelected(editor) { - let href = editor.styleSheet.href; - ok(href.endsWith("sourcemaps.scss"), "selected stylesheet is correct one"); + let editor = yield onEditor; let {line, col} = editor.sourceEditor.getCursor(); is(line, 3, "cursor is at correct line number in original source"); - - finishUp(); } -/* Helpers */ -function expandProperty(aIndex, aCallback) -{ - info("expanding property " + aIndex); - let contentDoc = computedView.styleDocument; - let expando = contentDoc.querySelectorAll(".expandable")[aIndex]; +function verifyLinkText(view, text) { + let link = getComputedViewLinkByIndex(view, 0); - expando.click(); - - inspector.once("computed-view-property-expanded", aCallback); -} - -function getLinkByIndex(aIndex) -{ - let contentDoc = computedView.styleDocument; - let links = contentDoc.querySelectorAll(".rule-link .link"); - return links[aIndex]; -} - -function verifyLinkText(text, callback) { - let link = getLinkByIndex(0); - - waitForSuccess({ - name: "link text changed to display correct location: " + text, - validatorFn: function() - { - return link.textContent == text; - }, - successFn: callback, - failureFn: callback, - }); -} - -function finishUp() -{ - gBrowser.removeCurrentTab(); - doc = inspector = computedView = toolbox = win = null; - Services.prefs.clearUserPref(PREF); - finish(); + return waitForSuccess( + () => link.textContent == text, + "link text changed to display correct location: " + text + ); } diff --git a/browser/devtools/styleinspector/test/browser_csslogic_inherited.js b/browser/devtools/styleinspector/test/browser_csslogic_inherited.js index e56c869d0f4b..63fd28bb0eff 100644 --- a/browser/devtools/styleinspector/test/browser_csslogic_inherited.js +++ b/browser/devtools/styleinspector/test/browser_csslogic_inherited.js @@ -1,44 +1,23 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Test that inherited properties are treated correctly. -let doc; +let test = asyncTest(function*() { + yield addTab("data:text/html,selector text test, bug 692400"); -function createDocument() -{ - doc.body.innerHTML = '
Inner div
'; - doc.title = "Style Inspector Inheritance Test"; + content.document.body.innerHTML = '
Inner div
'; + content.document.title = "Style Inspector Inheritance Test"; let cssLogic = new CssLogic(); - cssLogic.highlight(doc.getElementById("innerdiv")); + cssLogic.highlight(content.document.getElementById("innerdiv")); let marginProp = cssLogic.getPropertyInfo("margin-left"); is(marginProp.matchedRuleCount, 0, "margin-left should not be included in matched selectors."); let fontSizeProp = cssLogic.getPropertyInfo("font-size"); is(fontSizeProp.matchedRuleCount, 1, "font-size should be included in matched selectors."); - - finishUp(); -} - -function finishUp() -{ - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,selector text test, bug 692400"; -} +}); diff --git a/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js b/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js index df7d14920c1c..5e80f3c33997 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_734259_style_editor_link.js @@ -2,15 +2,9 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let win; -let doc; -let contentWindow; -let inspector; -let toolbox; +"use strict"; -let tempScope = {}; -Cu.import("resource://gre/modules/Services.jsm", tempScope); -let Services = tempScope.Services; +// Test the links from the rule-view to the styleeditor const STYLESHEET_URL = "data:text/css,"+encodeURIComponent( ["#first {", @@ -18,7 +12,7 @@ const STYLESHEET_URL = "data:text/css,"+encodeURIComponent( "}"].join("\n")); const EXTERNAL_STYLESHEET_FILE_NAME = "browser_ruleview_734259_style_editor_link.css" -const EXTERNAL_STYLESHEET_URL = TEST_BASE_HTTP + EXTERNAL_STYLESHEET_FILE_NAME; +const EXTERNAL_STYLESHEET_URL = TEST_URL_ROOT + EXTERNAL_STYLESHEET_FILE_NAME; const DOCUMENT_URL = "data:text/html,"+encodeURIComponent( ['' + @@ -50,97 +44,81 @@ const DOCUMENT_URL = "data:text/html,"+encodeURIComponent( '', ''].join("\n")); -function openToolbox() { - let target = TargetFactory.forTab(gBrowser.selectedTab); +let test = asyncTest(function*() { + yield addTab(DOCUMENT_URL); + let {toolbox, inspector, view} = yield openRuleView(); - gDevTools.showToolbox(target, "inspector").then(function(aToolbox) { - toolbox = aToolbox; - inspector = toolbox.getCurrentPanel(); - inspector.sidebar.select("ruleview"); - highlightNode(); - }); -} + info("Select the test node"); + yield selectNode("div", inspector); -function highlightNode() -{ - // Highlight a node. - let div = content.document.getElementsByTagName("div")[0]; + yield testInlineStyle(view, inspector); + yield testInlineStyleSheet(view, toolbox); + yield testExternalStyleSheet(view, toolbox); +}); - inspector.selection.setNode(div); - inspector.once("inspector-updated", () => { - is(inspector.selection.node, div, "selection matches the div element"); - testInlineStyle(); - }); -} +function* testInlineStyle(view, inspector) { + info("Testing inline style"); -function testInlineStyle() -{ - info("clicking an inline style"); - - Services.ww.registerNotification(function onWindow(aSubject, aTopic) { - if (aTopic != "domwindowopened") { - return; - } - - win = aSubject.QueryInterface(Ci.nsIDOMWindow); - win.addEventListener("load", function windowLoad() { - win.removeEventListener("load", windowLoad); - let windowType = win.document.documentElement.getAttribute("windowtype"); - is(windowType, "navigator:view-source", "view source window is open"); - win.close(); - Services.ww.unregisterNotification(onWindow); - executeSoon(() => { - testInlineStyleSheet(); - }); - }); - }); - - let link = getLinkByIndex(0); + let onWindow = waitForWindow(); + info("Clicking on the first link in the rule-view"); + let link = getRuleViewLinkByIndex(view, 0); link.scrollIntoView(); link.click(); + + let win = yield onWindow; + + let windowType = win.document.documentElement.getAttribute("windowtype"); + is(windowType, "navigator:view-source", "View source window is open"); + info("Closing window"); + win.close(); } -function testInlineStyleSheet() -{ - info("clicking an inline stylesheet"); +function* testInlineStyleSheet(view, toolbox) { + info("Testing inline stylesheet"); - toolbox.once("styleeditor-ready", function(id, aToolbox) { - let panel = toolbox.getCurrentPanel(); + info("Listening for toolbox switch to the styleeditor"); + let onSwitch = waitForStyleEditor(toolbox); - panel.UI.once("editor-selected", (event, editor) => { - validateStyleEditorSheet(editor, 0); - executeSoon(() => { - testExternalStyleSheet(toolbox); - }); - }); - }); - - let link = getLinkByIndex(4); + info("Clicking an inline stylesheet"); + let link = getRuleViewLinkByIndex(view, 4); link.scrollIntoView(); link.click(); + let editor = yield onSwitch; + + ok(true, "Switched to the style-editor panel in the toolbox"); + + validateStyleEditorSheet(editor, 0); } -function testExternalStyleSheet(toolbox) { - info ("clicking an external stylesheet"); +function* testExternalStyleSheet(view, toolbox) { + info("Testing external stylesheet"); + info("Waiting for the stylesheet editor to be selected"); let panel = toolbox.getCurrentPanel(); - panel.UI.once("editor-selected", (event, editor) => { - is(toolbox.currentToolId, "styleeditor", "style editor tool selected"); - validateStyleEditorSheet(editor, 1); - finishUp(); - }); + let onSelected = panel.UI.once("editor-selected"); - toolbox.selectTool("inspector").then(function () { - testRuleViewLinkLabel(); - let link = getLinkByIndex(1); - link.scrollIntoView(); - link.click(); - }); + info("Switching back to the inspector panel in the toolbox"); + yield toolbox.selectTool("inspector"); + + info("Clicking on an external stylesheet link"); + testRuleViewLinkLabel(view); + let link = getRuleViewLinkByIndex(view, 1); + link.scrollIntoView(); + link.click(); + let editor = yield onSelected; + + is(toolbox.currentToolId, "styleeditor", "The style editor is selected again"); + validateStyleEditorSheet(editor, 1); } -function testRuleViewLinkLabel() -{ - let link = getLinkByIndex(2); +function validateStyleEditorSheet(editor, expectedSheetIndex) { + info("validating style editor stylesheet"); + let sheet = content.document.styleSheets[expectedSheetIndex]; + is(editor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet"); +} + +function testRuleViewLinkLabel(view) { + let link = getRuleViewLinkByIndex(view, 2); let labelElem = link.querySelector(".source-link-label"); let value = labelElem.getAttribute("value"); let tooltipText = labelElem.getAttribute("tooltiptext"); @@ -150,40 +128,3 @@ function testRuleViewLinkLabel() is(tooltipText, EXTERNAL_STYLESHEET_URL, "rule view stylesheet tooltip text matches the full URI path"); } - -function validateStyleEditorSheet(aEditor, aExpectedSheetIndex) -{ - info("validating style editor stylesheet"); - let sheet = doc.styleSheets[aExpectedSheetIndex]; - is(aEditor.styleSheet.href, sheet.href, "loaded stylesheet matches document stylesheet"); -} - -function getLinkByIndex(aIndex) -{ - let contentDoc = ruleView().doc; - contentWindow = contentDoc.defaultView; - let links = contentDoc.querySelectorAll(".ruleview-rule-source"); - return links[aIndex]; -} - -function finishUp() -{ - gBrowser.removeCurrentTab(); - contentWindow = doc = inspector = toolbox = win = null; - finish(); -} - -function test() -{ - waitForExplicitFinish(); - - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(openToolbox, content); - }, true); - - content.location = DOCUMENT_URL; -} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_add_property_01.js b/browser/devtools/styleinspector/test/browser_ruleview_add_property_01.js new file mode 100644 index 000000000000..7fcb75560828 --- /dev/null +++ b/browser/devtools/styleinspector/test/browser_ruleview_add_property_01.js @@ -0,0 +1,48 @@ +/* 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 adding properties to rules work and reselecting the element still +// show them + +const TEST_URI = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.html"; + +let test = asyncTest(function*() { + yield addTab(TEST_URI); + + let target = getNode("#target"); + + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode(target, inspector); + + info("Setting a font-weight property on all rules"); + setPropertyOnAllRules(view); + + info("Reselecting the element"); + yield reselectElement(target, inspector); + + checkPropertyOnAllRules(view); +}); + +function reselectElement(node, inspector) { + return selectNode(node.parentNode, inspector).then(() => { + return selectNode(node, inspector); + }); +} + +function setPropertyOnAllRules(view) { + for (let rule of view._elementStyle.rules) { + rule.editor.addProperty("font-weight", "bold", ""); + } +} + +function checkPropertyOnAllRules(view) { + for (let rule of view._elementStyle.rules) { + let lastRule = rule.textProps[rule.textProps.length - 1]; + + is(lastRule.name, "font-weight", "Last rule name is font-weight"); + is(lastRule.value, "bold", "Last rule value is bold"); + } +} diff --git a/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js b/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js index 2f5c1c6c6b9b..4b9bfb2c5770 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_bug_902966_revert_value_on_ESC.js @@ -1,15 +1,13 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Test original value is correctly displayed when ESCaping out of the // inplace editor in the style inspector. -let doc; -let ruleWindow; -let ruleView; -let inspector; -let originalValue = "#00F"; +const originalValue = "#00F"; // Test data format // { @@ -18,86 +16,69 @@ let originalValue = "#00F"; // modifiers: commitKey modifiers, // expected: what value is expected as a result // } -let testData = [ +const testData = [ {value: "red", commitKey: "VK_ESCAPE", modifiers: {}, expected: originalValue}, {value: "red", commitKey: "VK_RETURN", modifiers: {}, expected: "#F00"}, {value: "invalid", commitKey: "VK_RETURN", modifiers: {}, expected: "invalid"}, {value: "blue", commitKey: "VK_TAB", modifiers: {shiftKey: true}, expected: "blue"} ]; -function startTests() -{ +let test = asyncTest(function*() { + yield addTab("data:text/html,test escaping property change reverts back to original value"); + + info("Creating the test document"); + createDocument(); + + info("Opening the rule view"); + let {toolbox, inspector, view} = yield openRuleView(); + + info("Selecting the test node"); + yield selectNode("#testid", inspector); + + info("Iterating over the test data"); + for (let data of testData) { + yield runTestData(view, data); + } +}); + +function createDocument() { let style = '' + '#testid {' + ' color: ' + originalValue + ';' + '}'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - let testElement = doc.getElementById("testid"); + let node = content.document.createElement('style'); + node.setAttribute("type", "text/css"); + node.textContent = style; + content.document.getElementsByTagName("head")[0].appendChild(node); - openRuleView((aInspector, aRuleView) => { - inspector = aInspector; - ruleView = aRuleView; - ruleWindow = aRuleView.doc.defaultView; - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => runTestData(0)); - }); + content.document.body.innerHTML = '
Styled Node
'; } -function runTestData(index) -{ - if (index === testData.length) { - finishTest(); - return; +function* runTestData(view, {value, commitKey, modifiers, expected}) { + let idRuleEditor = view.element.children[1]._ruleEditor; + let propEditor = idRuleEditor.rule.textProps[0].editor; + + info("Focusing the inplace editor field"); + let editor = yield focusEditableField(propEditor.valueSpan); + is(inplaceEditor(propEditor.valueSpan), editor, "Focused editor should be the value span."); + + info("Entering test data " + value) + for (let ch of value) { + EventUtils.sendChar(ch, view.doc.defaultView); } - let idRuleEditor = ruleView.element.children[1]._ruleEditor; - let propEditor = idRuleEditor.rule.textProps[0].editor; - waitForEditorFocus(propEditor.element, function(aEditor) { - is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value span."); + info("Waiting for focus on the field"); + let onBlur = once(editor.input, "blur"); - for (let ch of testData[index].value) { - EventUtils.sendChar(ch, ruleWindow); - } + info("Entering the commit key " + commitKey + " " + modifiers); + EventUtils.synthesizeKey(commitKey, modifiers); + yield onBlur; - // Need to wait for the change to be finished before the next test starts - // if not cancelling the change (the previous modification can change which - // color format is shown). - if (testData[index].commitKey === "VK_ESCAPE") { - EventUtils.synthesizeKey(testData[index].commitKey, testData[index].modifiers); - is(propEditor.valueSpan.textContent, testData[index].expected, "Value is same as expected: " + testData[index].expected); - runTestData(index + 1); - } else { - ruleView.element.addEventListener("CssRuleViewChanged", function nextTest() { - ruleView.element.removeEventListener("CssRuleViewChanged", nextTest); - is(propEditor.valueSpan.textContent, testData[index].expected, "Value is same as expected: " + testData[index].expected); - runTestData(index + 1); - }); - EventUtils.synthesizeKey(testData[index].commitKey, testData[index].modifiers); - } - }); - - EventUtils.synthesizeMouse(propEditor.valueSpan, 1, 1, {}, ruleWindow); -} - -function finishTest() -{ - inspector = ruleWindow = ruleView = null; - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function escapePropertyChange_load(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, escapePropertyChange_load, true); - doc = content.document; - waitForFocus(startTests, content); - }, true); - - content.location = "data:text/html,test escaping property change reverts back to original value"; + if (commitKey === "VK_ESCAPE") { + is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected); + } else { + yield once(view.element, "CssRuleViewChanged"); + is(propEditor.valueSpan.textContent, expected, "Value is as expected: " + expected); + } } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js index 842fd3562fc1..14b2a12f3765 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_01.js @@ -17,58 +17,44 @@ const PAGE_CONTENT = [ 'Testing the color picker tooltip!' ].join("\n"); -function test() { - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function load(evt) { - gBrowser.selectedBrowser.removeEventListener("load", load, true); - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,rule view color picker tooltip test"; -} - -function createDocument() { +let test = asyncTest(function*() { + yield addTab("data:text/html,rule view color picker tooltip test"); content.document.body.innerHTML = PAGE_CONTENT; + let {toolbox, inspector, view} = yield openRuleView(); - openRuleView((inspector, ruleView) => { - inspector.once("inspector-updated", () => { - let value = getRuleViewProperty("background", ruleView).valueSpan; - let swatch = value.querySelector(".ruleview-colorswatch"); - let url = value.querySelector(".theme-link"); - testImageTooltipAfterColorChange(swatch, url, ruleView); - }); + let value = getRuleViewProperty(view, "body", "background").valueSpan; + let swatch = value.querySelector(".ruleview-colorswatch"); + let url = value.querySelector(".theme-link"); + yield testImageTooltipAfterColorChange(swatch, url, view); +}); + +function* testImageTooltipAfterColorChange(swatch, url, ruleView) { + info("First, verify that the image preview tooltip works"); + let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); + ok(anchor, "The image preview tooltip is shown on the url span"); + is(anchor, url, "The anchor returned by the showOnHover callback is correct"); + + info("Open the color picker tooltip and change the color"); + let picker = ruleView.colorPicker; + let onShown = picker.tooltip.once("shown"); + swatch.click(); + yield onShown; + yield simulateColorPickerChange(picker, [0, 0, 0, 1], { + element: content.document.body, + name: "backgroundImage", + value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)' }); -} - -function testImageTooltipAfterColorChange(swatch, url, ruleView) { - Task.spawn(function*() { - info("First, verify that the image preview tooltip works"); - let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); - ok(anchor, "The image preview tooltip is shown on the url span"); - is(anchor, url, "The anchor returned by the showOnHover callback is correct"); - - info("Open the color picker tooltip and change the color"); - let picker = ruleView.colorPicker; - let onShown = picker.tooltip.once("shown"); - swatch.click(); - yield onShown; - yield simulateColorChange(picker, [0, 0, 0, 1], { - element: content.document.body, - name: "backgroundImage", - value: 'url("chrome://global/skin/icons/warning-64.png"), linear-gradient(rgb(0, 0, 0), rgb(255, 0, 102) 400px)' - }); - - let spectrum = yield picker.spectrum; - let onHidden = picker.tooltip.once("hidden"); - EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView); - yield onHidden; - - info("Verify again that the image preview tooltip works"); - // After a color change, the property is re-populated, we need to get the new - // dom node - url = getRuleViewProperty("background", ruleView).valueSpan.querySelector(".theme-link"); - let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); - ok(anchor, "The image preview tooltip is shown on the url span"); - is(anchor, url, "The anchor returned by the showOnHover callback is correct"); - }).then(finish); + + let spectrum = yield picker.spectrum; + let onHidden = picker.tooltip.once("hidden"); + EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView); + yield onHidden; + + info("Verify again that the image preview tooltip works"); + // After a color change, the property is re-populated, we need to get the new + // dom node + url = getRuleViewProperty(ruleView, "body", "background").valueSpan.querySelector(".theme-link"); + let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); + ok(anchor, "The image preview tooltip is shown on the url span"); + is(anchor, url, "The anchor returned by the showOnHover callback is correct"); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js index 3905ce1c7e5d..20003ceb7052 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-and-image-tooltip_02.js @@ -19,58 +19,43 @@ const PAGE_CONTENT = [ 'Testing the color picker tooltip!' ].join("\n"); -function test() { - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function load(evt) { - gBrowser.selectedBrowser.removeEventListener("load", load, true); - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,rule view color picker tooltip test"; -} - -function createDocument() { +let test = asyncTest(function*() { + yield addTab("data:text/html,rule view color picker tooltip test"); content.document.body.innerHTML = PAGE_CONTENT; + let {toolbox, inspector, view} = yield openRuleView(); + yield testColorChangeIsntRevertedWhenOtherTooltipIsShown(view); +}); - openRuleView((inspector, ruleView) => { - inspector.once("inspector-updated", () => { - testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView); - }); +function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) { + let swatch = getRuleViewProperty(ruleView, "body", "background").valueSpan + .querySelector(".ruleview-colorswatch"); + + info("Open the color picker tooltip and change the color"); + let picker = ruleView.colorPicker; + let onShown = picker.tooltip.once("shown"); + swatch.click(); + yield onShown; + + yield simulateColorPickerChange(picker, [0, 0, 0, 1], { + element: content.document.body, + name: "backgroundColor", + value: "rgb(0, 0, 0)" }); -} - -function testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) { - Task.spawn(function*() { - let swatch = getRuleViewProperty("background", ruleView).valueSpan - .querySelector(".ruleview-colorswatch"); - - info("Open the color picker tooltip and change the color"); - let picker = ruleView.colorPicker; - let onShown = picker.tooltip.once("shown"); - swatch.click(); - yield onShown; - - yield simulateColorChange(picker, [0, 0, 0, 1], { - element: content.document.body, - name: "backgroundColor", - value: "rgb(0, 0, 0)" - }); - let spectrum = yield picker.spectrum; - let onHidden = picker.tooltip.once("hidden"); - EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView); - yield onHidden; - - info("Open the image preview tooltip"); - let value = getRuleViewProperty("background", ruleView).valueSpan; - let url = value.querySelector(".theme-link"); - let onShown = ruleView.previewTooltip.once("shown"); - let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); - ruleView.previewTooltip.show(anchor); - yield onShown; - - info("Image tooltip is shown, verify that the swatch is still correct"); - let swatch = value.querySelector(".ruleview-colorswatch"); - is(swatch.style.backgroundColor, "rgb(0, 0, 0)", "The swatch's color is correct"); - is(swatch.nextSibling.textContent, "#000", "The color name is correct"); - }).then(finish); + let spectrum = yield picker.spectrum; + let onHidden = picker.tooltip.once("hidden"); + EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView); + yield onHidden; + + info("Open the image preview tooltip"); + let value = getRuleViewProperty(ruleView, "body", "background").valueSpan; + let url = value.querySelector(".theme-link"); + let onShown = ruleView.previewTooltip.once("shown"); + let anchor = yield isHoverTooltipTarget(ruleView.previewTooltip, url); + ruleView.previewTooltip.show(anchor); + yield onShown; + + info("Image tooltip is shown, verify that the swatch is still correct"); + let swatch = value.querySelector(".ruleview-colorswatch"); + is(swatch.style.backgroundColor, "rgb(0, 0, 0)", "The swatch's color is correct"); + is(swatch.nextSibling.textContent, "#000", "The color name is correct"); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js index 80853757618e..5a5a2274e90c 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_colorpicker-appears-on-swatch-click.js @@ -6,8 +6,6 @@ // Test that color pickers appear when clicking on color swatches -let ruleView, swatches; - const PAGE_CONTENT = [ '', 'Testing the color picker tooltip!' ].join("\n"); -function test() { - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function load(evt) { - gBrowser.selectedBrowser.removeEventListener("load", load, true); - waitForFocus(createDocument, content); - }, true); +// Tests that properties in the rule-view contain color swatches +// Each entry in the test array should contain: +// { +// selector: the rule-view selector to look for the property in +// propertyName: the property to test +// nb: the number of color swatches this property should have +// } +const TESTS = [ + {selector: "body", propertyName: "color", nb: 1}, + {selector: "body", propertyName: "background-color", nb: 1}, + {selector: "body", propertyName: "border", nb: 1}, + {selector: "*", propertyName: "color", nb: 1}, + {selector: "*", propertyName: "box-shadow", nb: 2}, +]; - content.location = "data:text/html,rule view color picker tooltip test"; -} - -function createDocument() { +let test = asyncTest(function*() { + yield addTab("data:text/html,rule view color picker tooltip test"); content.document.body.innerHTML = PAGE_CONTENT; + let {toolbox, inspector, view} = yield openRuleView(); - openRuleView((inspector, view) => { - ruleView = view; - inspector.once("inspector-updated", testColorSwatchesAreDisplayed); - }); -} + for (let {selector, propertyName, nb} of TESTS) { + info("Looking for color swatches in property " + propertyName + + " in selector " + selector); -function testColorSwatchesAreDisplayed() { - let cSwatch = getRuleViewProperty("color", ruleView).valueSpan - .querySelector(".ruleview-colorswatch"); - ok(cSwatch, "Color swatch is displayed for the color property"); + let prop = getRuleViewProperty(view, selector, propertyName).valueSpan; + let swatches = prop.querySelectorAll(".ruleview-colorswatch"); - let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan - .querySelector(".ruleview-colorswatch"); - ok(bgSwatch, "Color swatch is displayed for the bg-color property"); - - let bSwatch = getRuleViewProperty("border", ruleView).valueSpan - .querySelector(".ruleview-colorswatch"); - ok(bSwatch, "Color swatch is displayed for the border property"); - - ruleView = null; - finish(); -} + ok(swatches.length, "Swatches found in the property"); + is(swatches.length, nb, "Correct number of swatches found in the property"); + } +}); diff --git a/browser/devtools/styleinspector/test/browser_ruleview_copy.js b/browser/devtools/styleinspector/test/browser_ruleview_copy.js index f4872aaaaf25..72cda396e15b 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_copy.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_copy.js @@ -2,17 +2,19 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let inspector; -let win; +"use strict"; + +// Tests that properties can be selected and copied from the rule view XPCOMUtils.defineLazyGetter(this, "osString", function() { return Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS; }); -function createDocument() -{ - doc.body.innerHTML = '
more text

\n' + '

even more text

' + '
'; - doc.title = "Rule view context menu test"; + content.document.title = "Rule view context menu test"; - let target = TargetFactory.forTab(gBrowser.selectedTab); - gDevTools.showToolbox(target, "inspector").then(function(toolbox) { - inspector = toolbox.getCurrentPanel(); - inspector.sidebar.select("ruleview"); - win = inspector.sidebar.getWindowForTab("ruleview"); - highlightNode(); - }); -} + info("Opening the computed view"); + let {toolbox, inspector, view} = yield openRuleView(); -function highlightNode() -{ - // Highlight a node. - let div = content.document.getElementsByTagName("div")[0]; + info("Selecting the test node"); + yield selectNode("div", inspector); - inspector.once("inspector-updated", function() { - is(inspector.selection.node, div, "selection matches the div element"); - executeSoon(checkCopySelection); - }); + yield checkCopySelection(view); + yield checkSelectAll(view); +}); - inspector.selection.setNode(div); -} +function checkCopySelection(view) { + info("Testing selection copy"); -function checkCopySelection() -{ - let contentDoc = win.document; + let contentDoc = view.doc; let prop = contentDoc.querySelector(".ruleview-property"); let values = contentDoc.querySelectorAll(".ruleview-propertycontainer"); let range = contentDoc.createRange(); range.setStart(prop, 0); range.setEnd(values[4], 2); - - let selection = win.getSelection(); - selection.addRange(range); + let selection = view.doc.defaultView.getSelection().addRange(range); info("Checking that _Copy() returns the correct clipboard value"); + let expectedPattern = " margin: 10em;[\\r\\n]+" + " font-size: 14pt;[\\r\\n]+" + " font-family: helvetica,sans-serif;[\\r\\n]+" + @@ -75,26 +65,23 @@ function checkCopySelection() "html {[\\r\\n]+" + " color: #000;[\\r\\n]*"; - SimpleTest.waitForClipboard(function() { - return checkClipboardData(expectedPattern); - }, - function() { + return waitForClipboard(() => { fireCopyEvent(prop); - }, - checkSelectAll, - function() { - failedClipboard(expectedPattern, checkSelectAll); + }, () => { + return checkClipboardData(expectedPattern); + }).then(() => {}, () => { + failedClipboard(expectedPattern); }); } -function checkSelectAll() -{ - let contentDoc = win.document; - let _ruleView = ruleView(); +function checkSelectAll(view) { + info("Testing select-all copy"); + + let contentDoc = view.doc; let prop = contentDoc.querySelector(".ruleview-property"); info("Checking that _SelectAll() then copy returns the correct clipboard value"); - _ruleView._onSelectAll(); + view._onSelectAll(); let expectedPattern = "[\\r\\n]+" + "element {[\\r\\n]+" + " margin: 10em;[\\r\\n]+" + @@ -106,65 +93,37 @@ function checkSelectAll() " color: #000;[\\r\\n]+" + "}[\\r\\n]*"; - SimpleTest.waitForClipboard(function() { - return checkClipboardData(expectedPattern); - }, - function() { + return waitForClipboard(() => { fireCopyEvent(prop); - }, - finishup, - function() { - failedClipboard(expectedPattern, finishup); + }, () => { + return checkClipboardData(expectedPattern); + }).then(() => {}, () => { + failedClipboard(expectedPattern); }); } -function checkClipboardData(aExpectedPattern) -{ +function checkClipboardData(expectedPattern) { let actual = SpecialPowers.getClipboardData("text/unicode"); - let expectedRegExp = new RegExp(aExpectedPattern, "g"); + let expectedRegExp = new RegExp(expectedPattern, "g"); return expectedRegExp.test(actual); } -function failedClipboard(aExpectedPattern, aCallback) -{ +function failedClipboard(expectedPattern) { // Format expected text for comparison let terminator = osString == "WINNT" ? "\r\n" : "\n"; - aExpectedPattern = aExpectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); - aExpectedPattern = aExpectedPattern.replace(/\\\(/g, "("); - aExpectedPattern = aExpectedPattern.replace(/\\\)/g, ")"); + expectedPattern = expectedPattern.replace(/\[\\r\\n\][+*]/g, terminator); + expectedPattern = expectedPattern.replace(/\\\(/g, "("); + expectedPattern = expectedPattern.replace(/\\\)/g, ")"); let actual = SpecialPowers.getClipboardData("text/unicode"); // Trim the right hand side of our strings. This is because expectedPattern // accounts for windows sometimes adding a newline to our copied data. - aExpectedPattern = aExpectedPattern.trimRight(); + expectedPattern = expectedPattern.trimRight(); actual = actual.trimRight(); dump("TEST-UNEXPECTED-FAIL | Clipboard text does not match expected ... " + "results (escaped for accurate comparison):\n"); info("Actual: " + escape(actual)); - info("Expected: " + escape(aExpectedPattern)); - aCallback(); -} - -function finishup() -{ - gBrowser.removeCurrentTab(); - doc = inspector = win = null; - finish(); -} - -function test() -{ - waitForExplicitFinish(); - - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,

rule view context menu test

"; + info("Expected: " + escape(expectedPattern)); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_editor.js b/browser/devtools/styleinspector/test/browser_ruleview_editor.js index f4a891dac2b0..3c2519dc1236 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_editor.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_editor.js @@ -1,119 +1,117 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc = content.document; +"use strict"; -function expectDone(aValue, aCommit, aNext) -{ - return function(aDoneValue, aDoneCommit) { - dump("aDoneValue: " + aDoneValue + " commit: " + aDoneCommit + "\n"); +// Test the inplace-editor behavior. +// This test doesn't open the devtools, it just exercises the inplace-editor +// on test elements in the page - is(aDoneValue, aValue, "Should get expected value"); - is(aDoneCommit, aDoneCommit, "Should get expected commit value"); - aNext(); - } -} +let test = asyncTest(function*() { + yield addTab("data:text/html,inline editor tests"); + yield testReturnCommit(); + yield testBlurCommit(); + yield testAdvanceCharCommit(); +}); -function clearBody() -{ - doc.body.innerHTML = ""; -} +function testReturnCommit() { + info("Testing that pressing return commits the new value"); + let def = promise.defer(); -function createSpan() -{ - let span = doc.createElement("span"); - span.setAttribute("tabindex", "0"); - span.textContent = "Edit Me!"; - doc.body.appendChild(span); - return span; -} - -function testReturnCommit() -{ - clearBody(); - let span = createSpan(); - editableField({ - element: span, + createInplaceEditorAndClick({ initial: "explicit initial", - start: function() { - is(inplaceEditor(span).input.value, "explicit initial", "Explicit initial value should be used."); - inplaceEditor(span).input.value = "Test Value"; + start: function(editor) { + is(editor.input.value, "explicit initial", "Explicit initial value should be used."); + editor.input.value = "Test Value"; EventUtils.sendKey("return"); }, - done: expectDone("Test Value", true, testBlurCommit) + done: onDone("Test Value", true, def) }); - span.click(); + + return def.promise; } -function testBlurCommit() -{ - clearBody(); - let span = createSpan(); - editableField({ - element: span, - start: function() { - is(inplaceEditor(span).input.value, "Edit Me!", "textContent of the span used."); - inplaceEditor(span).input.value = "Test Value"; - inplaceEditor(span).input.blur(); +function testBlurCommit() { + info("Testing that bluring the field commits the new value"); + let def = promise.defer(); + + createInplaceEditorAndClick({ + start: function(editor) { + is(editor.input.value, "Edit Me!", "textContent of the span used."); + editor.input.value = "Test Value"; + editor.input.blur(); }, - done: expectDone("Test Value", true, testAdvanceCharCommit) + done: onDone("Test Value", true, def) }); - span.click(); + + return def.promise; } -function testAdvanceCharCommit() -{ - clearBody(); - let span = createSpan(); - editableField({ - element: span, +function testAdvanceCharCommit() { + info("Testing that configured advanceChars commit the new value"); + let def = promise.defer(); + + createInplaceEditorAndClick({ advanceChars: ":", - start: function() { - let input = inplaceEditor(span).input; + start: function(editor) { + let input = editor.input; for each (let ch in "Test:") { EventUtils.sendChar(ch); } }, - done: expectDone("Test", true, testEscapeCancel) + done: onDone("Test", true, def) }); - span.click(); + + return def.promise; } -function testEscapeCancel() -{ - clearBody(); - let span = createSpan(); - editableField({ - element: span, +function testEscapeCancel() { + info("Testing that escape cancels the new value"); + let def = promise.defer(); + + createInplaceEditorAndClick({ initial: "initial text", - start: function() { - inplaceEditor(span).input.value = "Test Value"; + start: function(editor) { + editor.input.value = "Test Value"; EventUtils.sendKey("escape"); }, - done: expectDone("initial text", false, finishTest) + done: onDone("initial text", false, def) }); + + return def.promise; +} + +function onDone(value, isCommit, def) { + return function(actualValue, actualCommit) { + info("Inplace-editor's done callback executed, checking its state"); + is(actualValue, value, "The value is correct"); + is(actualCommit, isCommit, "The commit boolean is correct"); + def.resolve(); + } +} + +function createInplaceEditorAndClick(options) { + clearBody(); + let span = options.element = createSpan(); + + info("Creating an inplace-editor field"); + editableField(options); + + info("Clicking on the inplace-editor field to turn to edit mode"); span.click(); } - -function finishTest() -{ - doc = null; - gBrowser.removeCurrentTab(); - finish(); +function clearBody() { + info("Clearing the page body"); + content.document.body.innerHTML = ""; } - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(testReturnCommit, content); - }, true); - - content.location = "data:text/html,inline editor tests"; +function createSpan() { + info("Creating a new span element"); + let span = content.document.createElement("span"); + span.setAttribute("tabindex", "0"); + span.textContent = "Edit Me!"; + content.document.body.appendChild(span); + return span; } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js index e4c535923a4a..ee7cc83000f9 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js @@ -1,220 +1,187 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let ruleWindow; -let ruleView; -let inspector; -let TEST_URL = 'url("http://example.com/browser/browser/devtools/' + - 'styleinspector/test/test-image.png")'; +"use strict"; -function startTest() -{ - let style = '' + - '#testid {' + - ' background-color: blue;' + - '} ' + - '.testclass {' + - ' background-color: green;' + - '}'; +// Testing various inplace-editor behaviors in the rule-view +// FIXME: To be split in several test files, and some of the inplace-editor +// focus/blur/commit/revert stuff should be factored out in head.js - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - let testElement = doc.getElementById("testid"); +let TEST_URL = 'url("' + TEST_URL_ROOT + 'test-image.png")'; +let PAGE_CONTENT = [ + '', + '
Styled Node
' +].join("\n"); - openRuleView((aInspector, aRuleView) => { - inspector = aInspector; - ruleView = aRuleView; - ruleWindow = aRuleView.doc.defaultView; - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", testCancelNew); - }); +let test = asyncTest(function*() { + yield addTab("data:text/html,test rule view user changes"); + + info("Creating the test document"); + content.document.body.innerHTML = PAGE_CONTENT; + + info("Opening the rule-view"); + let {toolbox, inspector, view} = yield openRuleView(); + + info("Selecting the test element"); + yield selectNode("#testid", inspector); + + yield testCancelNew(view); + yield testCreateNew(view); + yield testCreateNewEscape(view); + yield testEditProperty(view, "border-color", "red"); + yield testEditProperty(view, "background-image", TEST_URL); +}); + +function* testCancelNew(view) { + info("Test adding a new rule to the element's style declaration and leaving it empty."); + + let elementRuleEditor = view.element.children[0]._ruleEditor; + + info("Focusing a new property name in the rule-view"); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused"); + + info("Bluring the editor input"); + let onBlur = once(editor.input, "blur"); + editor.input.blur(); + yield onBlur; + + info("Checking the state of canceling a new property name editor"); + ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding request after a cancel."); + is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); + ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); } -function testCancelNew() -{ - // Start at the beginning: start to add a rule to the element's style - // declaration, but leave it empty. - let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - let input = aEditor.input; - waitForEditorBlur(aEditor, function () { - ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding request after a cancel."); - is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); - ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); - testCreateNew(); - }); - aEditor.input.blur(); - }); - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); +function* testCreateNew(view) { + info("Test creating a new property"); + + let elementRuleEditor = view.element.children[0]._ruleEditor; + + info("Focusing a new property name in the rule-view"); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); + + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused"); + let input = editor.input; + + info("Entering background-color in the property name editor"); + input.value = "background-color"; + + info("Pressing return to commit and focus the new value field"); + let onValueFocus = once(elementRuleEditor.element, "focus", true); + let onModifications = elementRuleEditor.rule._applyingModifications; + EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView); + yield onValueFocus; + yield onModifications; + + // Getting the new value editor after focus + editor = inplaceEditor(view.doc.activeElement); + let textProp = elementRuleEditor.rule.textProps[0]; + + is(elementRuleEditor.rule.textProps.length, 1, "Created a new text property."); + is(elementRuleEditor.propertyList.children.length, 1, "Created a property editor."); + is(editor, inplaceEditor(textProp.editor.valueSpan), "Editing the value span now."); + + info("Entering a value and bluring the field to expect a rule change"); + editor.input.value = "#XYZ"; + let onBlur = once(editor.input, "blur"); + let onModifications = elementRuleEditor.rule._applyingModifications; + editor.input.blur(); + yield onBlur; + yield onModifications; + + is(textProp.value, "#XYZ", "Text prop should have been changed."); + is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry"); } -function testCreateNew() -{ - // Create a new property. - let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - let input = aEditor.input; - input.value = "background-color"; +function* testCreateNewEscape(view) { + info("Test creating a new property and escaping"); - waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) { - promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => { - is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor."); - let textProp = elementRuleEditor.rule.textProps[0]; - is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now."); - aEditor.input.value = "#XYZ"; - waitForEditorBlur(aEditor, function() { - promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => { - is(textProp.value, "#XYZ", "Text prop should have been changed."); - is(textProp.editor.isValid(), false, "#XYZ should not be a valid entry"); - testCreateNewEscape(); - })); - }); - aEditor.input.blur(); - })); - }); - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); - }); + let elementRuleEditor = view.element.children[0]._ruleEditor; - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); + info("Focusing a new property name in the rule-view"); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); + + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "The new property editor got focused."); + let input = editor.input; + + info("Entering a value in the property name editor"); + input.value = "color"; + + info("Pressing return to commit and focus the new value field"); + let onValueFocus = once(elementRuleEditor.element, "focus", true); + let onModifications = elementRuleEditor.rule._applyingModifications; + EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView); + yield onValueFocus; + yield onModifications; + + // Getting the new value editor after focus + editor = inplaceEditor(view.doc.activeElement); + let textProp = elementRuleEditor.rule.textProps[1]; + + is(elementRuleEditor.rule.textProps.length, 2, "Created a new text property."); + is(elementRuleEditor.propertyList.children.length, 2, "Created a property editor."); + is(editor, inplaceEditor(textProp.editor.valueSpan), "Editing the value span now."); + + info("Entering a property value"); + editor.input.value = "red"; + + info("Escaping out of the field"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView); + + info("Checking that the previous field is focused"); + let focusedElement = inplaceEditor(elementRuleEditor.rule.textProps[0].editor.valueSpan).input; + is(focusedElement, focusedElement.ownerDocument.activeElement, "Correct element has focus"); + + EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView); + + is(elementRuleEditor.rule.textProps.length, 1, "Removed the new text property."); + is(elementRuleEditor.propertyList.children.length, 1, "Removed the property editor."); } -function testCreateNewEscape() -{ - // Create a new property. - let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - let input = aEditor.input; - input.value = "color"; +function* testEditProperty(view, name, value) { + info("Test editing existing property name/value fields"); - waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) { - promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => { - is(elementRuleEditor.rule.textProps.length, 2, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 2, "Should have created a property editor."); - let textProp = elementRuleEditor.rule.textProps[1]; - is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now."); - aEditor.input.value = "red"; - EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow); - - // Make sure previous input is focused. - let focusedElement = inplaceEditor(elementRuleEditor.rule.textProps[0].editor.valueSpan).input; - is(focusedElement, focusedElement.ownerDocument.activeElement, "Correct element has focus"); - - EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow); - - is(elementRuleEditor.rule.textProps.length, 1, "Should have removed the new text property."); - is(elementRuleEditor.propertyList.children.length, 1, "Should have removed the property editor."); - - testEditProperty(); - })); - }); - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); - }); - - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); -} - -function testEditProperty() -{ - let idRuleEditor = ruleView.element.children[1]._ruleEditor; + let idRuleEditor = view.element.children[1]._ruleEditor; let propEditor = idRuleEditor.rule.textProps[0].editor; - waitForEditorFocus(propEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor."); - let input = aEditor.input; - waitForEditorFocus(propEditor.element, function onNewName(aEditor) { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - input = aEditor.input; - is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value."); - waitForEditorBlur(aEditor, function() { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - let value = idRuleEditor.rule.domRule._rawStyle().getPropertyValue("border-color"); - is(value, "red", "border-color should have been set."); - is(propEditor.isValid(), true, "red should be a valid entry"); - testEditPropertyWithColon(); - })); - }); + info("Focusing an existing property name in the rule-view"); + let editor = yield focusEditableField(propEditor.nameSpan, 32, 1); - for (let ch of "red;") { - EventUtils.sendChar(ch, ruleWindow); - } - })); - }); - for (let ch of "border-color:") { - EventUtils.sendChar(ch, ruleWindow); - } - }); + is(inplaceEditor(propEditor.nameSpan), editor, "The property name editor got focused"); + let input = editor.input; - EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1, - { }, - ruleWindow); -} - -function testEditPropertyWithColon() -{ - let idRuleEditor = ruleView.element.children[1]._ruleEditor; - let propEditor = idRuleEditor.rule.textProps[0].editor; - waitForEditorFocus(propEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor."); - let input = aEditor.input; - waitForEditorFocus(propEditor.element, function onNewName(aEditor) { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - input = aEditor.input; - is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value."); - - waitForEditorBlur(aEditor, function() { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - let value = idRuleEditor.rule.domRule._rawStyle().getPropertyValue("background-image"); - is(value, TEST_URL, "background-image should have been set."); - is(propEditor.isValid(), true, "the test URL should be a valid entry"); - finishTest(); - })); - }); - - - for (let ch of (TEST_URL + ";")) { - EventUtils.sendChar(ch, ruleWindow); - } - })); - }); - for (let ch of "background-image:") { - EventUtils.sendChar(ch, ruleWindow); - } - }); - - EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1, - { }, - ruleWindow); -} - -function finishTest() -{ - inspector = ruleWindow = ruleView = null; - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true); - doc = content.document; - waitForFocus(startTest, content); - }, true); - - content.location = "data:text/html,test rule view user changes"; + info("Entering a new property name, including : to commit and focus the value"); + let onValueFocus = once(idRuleEditor.element, "focus", true); + let onModifications = idRuleEditor.rule._applyingModifications; + for (let ch of name + ":") { + EventUtils.sendChar(ch, view.doc.defaultView); + } + yield onValueFocus; + yield onModifications; + + // Getting the value editor after focus + editor = inplaceEditor(view.doc.activeElement); + input = editor.input; + is(inplaceEditor(propEditor.valueSpan), editor, "Focus moved to the value."); + + info("Entering a new value, including ; to commit and blur the value"); + let onBlur = once(input, "blur"); + let onModifications = idRuleEditor.rule._applyingModifications; + for (let ch of value + ";") { + EventUtils.sendChar(ch, view.doc.defaultView); + } + yield onBlur; + yield onModifications; + + let propValue = idRuleEditor.rule.domRule._rawStyle().getPropertyValue(name); + is(propValue, value, name + " should have been set."); + is(propEditor.isValid(), true, value + " should be a valid entry"); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_focus.js b/browser/devtools/styleinspector/test/browser_ruleview_focus.js index e5037cef972c..254a7c5fba3b 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_focus.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_focus.js @@ -1,65 +1,49 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Test that focus doesn't leave the style editor when adding a property // (bug 719916) -let doc; -let inspector; -let stylePanel; +let test = asyncTest(function*() { + yield addTab("data:text/html,

Some header text

"); + let {toolbox, inspector, view} = yield openRuleView(); -function selectNode(aInspector, aRuleView) -{ - inspector = aInspector; - let node = content.document.getElementsByTagName("h1")[0]; - inspector.selection.setNode(node); - inspector.once("inspector-updated", testFocus); -} + info("Selecting the test node"); + yield selectNode("h1", inspector); -function testFocus() -{ - let win = inspector.sidebar.getWindowForTab("ruleview"); - let brace = win.document.querySelectorAll(".ruleview-ruleclose")[0]; - - waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) { - aEditor.input.value = "color"; - waitForEditorFocus(brace.parentNode, function onEditingValue(aEditor) { - // If we actually get this focus we're ok. - ok(true, "We got focus."); - aEditor.input.value = "green"; - - // If we've retained focus, pressing return will start a new editor. - // If not, we'll wait here until we time out. - waitForEditorFocus(brace.parentNode, function onNewEditor(aEditor) { - aEditor.input.blur(); - finishUp(); - }); - EventUtils.sendKey("return"); - }); - EventUtils.sendKey("return"); - }); + info("Getting the ruleclose brace element"); + let brace = view.doc.querySelector(".ruleview-ruleclose"); + info("Clicking on the brace element to focus the new property field"); + let onFocus = once(brace.parentNode, "focus", true); brace.click(); -} + yield onFocus; -function finishUp() -{ - doc = inspector = stylePanel = null; - gBrowser.removeCurrentTab(); - finish(); -} + info("Entering a property name"); + let editor = getCurrentInplaceEditor(view); + editor.input.value = "color"; -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - doc.title = "Rule View Test"; - waitForFocus(() => openRuleView(selectNode), content); - }, true); + info("Typing ENTER to focus the next field: property value"); + let onFocus = once(brace.parentNode, "focus", true); + EventUtils.sendKey("return"); + yield onFocus; + ok(true, "The value field was focused"); - content.location = "data:text/html,

Some header text

"; + info("Entering a property value"); + let editor = getCurrentInplaceEditor(view); + editor.input.value = "green"; + + info("Typing ENTER again should focus a new property name"); + let onFocus = once(brace.parentNode, "focus", true); + EventUtils.sendKey("return"); + yield onFocus; + ok(true, "The new property name field was focused"); + getCurrentInplaceEditor(view).input.blur(); +}); + +function getCurrentInplaceEditor(view) { + return inplaceEditor(view.doc.activeElement); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_inherit.js b/browser/devtools/styleinspector/test/browser_ruleview_inherit.js index bea78aace1a6..8e956bcd92c9 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_inherit.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_inherit.js @@ -1,116 +1,86 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; +"use strict"; -let inspector; -let view; +// Check that inherited properties appear as such in the rule-view let {ELEMENT_STYLE} = devtools.require("devtools/server/actors/styles"); -function simpleInherit(aInspector, aRuleView) -{ - inspector = aInspector; - view = aRuleView; +let test = asyncTest(function*() { + yield addTab("data:text/html;charset=utf-8,browser_inspector_changes.js"); + let {toolbox, inspector, view} = yield openRuleView(); + yield simpleInherit(inspector, view); + yield emptyInherit(inspector, view); + yield elementStyleInherit(inspector, view); +}); + +function* simpleInherit(inspector, view) { let style = '' + '#test2 {' + ' background-color: green;' + ' color: purple;' + '}'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = '
Styled Node
'; - inspector.selection.setNode(doc.getElementById("test1")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + yield selectNode("#test1", inspector); - is(elementStyle.rules.length, 2, "Should have 2 rules."); + let elementStyle = view._elementStyle; + is(elementStyle.rules.length, 2, "Should have 2 rules."); - let elementRule = elementStyle.rules[0]; - ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); + let elementRule = elementStyle.rules[0]; + ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); - let inheritRule = elementStyle.rules[1]; - is(inheritRule.selectorText, "#test2", "Inherited rule should be the one that includes inheritable properties."); - ok(!!inheritRule.inherited, "Rule should consider itself inherited."); - is(inheritRule.textProps.length, 1, "Should only display one inherited style"); - let inheritProp = inheritRule.textProps[0]; - is(inheritProp.name, "color", "color should have been inherited."); + let inheritRule = elementStyle.rules[1]; + is(inheritRule.selectorText, "#test2", "Inherited rule should be the one that includes inheritable properties."); + ok(!!inheritRule.inherited, "Rule should consider itself inherited."); + is(inheritRule.textProps.length, 1, "Should only display one inherited style"); + let inheritProp = inheritRule.textProps[0]; + is(inheritProp.name, "color", "color should have been inherited."); - styleNode.parentNode.removeChild(styleNode); - - emptyInherit(); - }); + styleNode.remove(); } -function emptyInherit() -{ +function* emptyInherit(inspector, view) { // No inheritable styles, this rule shouldn't show up. let style = '' + '#test2 {' + ' background-color: green;' + '}'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = '
Styled Node
'; - inspector.selection.setNode(doc.getElementById("test1")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + yield selectNode("#test1", inspector); - is(elementStyle.rules.length, 1, "Should have 1 rule."); + let elementStyle = view._elementStyle; + is(elementStyle.rules.length, 1, "Should have 1 rule."); - let elementRule = elementStyle.rules[0]; - ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); + let elementRule = elementStyle.rules[0]; + ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); - styleNode.parentNode.removeChild(styleNode); - - elementStyleInherit(); - }); + styleNode.parentNode.removeChild(styleNode); } -function elementStyleInherit() -{ - doc.body.innerHTML = '
Styled Node
'; +function* elementStyleInherit(inspector, view) { + content.document.body.innerHTML = '
Styled Node
'; - inspector.selection.setNode(doc.getElementById("test1")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + yield selectNode("#test1", inspector); - is(elementStyle.rules.length, 2, "Should have 2 rules."); + let elementStyle = view._elementStyle; + is(elementStyle.rules.length, 2, "Should have 2 rules."); - let elementRule = elementStyle.rules[0]; - ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); + let elementRule = elementStyle.rules[0]; + ok(!elementRule.inherited, "Element style attribute should not consider itself inherited."); - let inheritRule = elementStyle.rules[1]; - is(inheritRule.domRule.type, ELEMENT_STYLE, "Inherited rule should be an element style, not a rule."); - ok(!!inheritRule.inherited, "Rule should consider itself inherited."); - is(inheritRule.textProps.length, 1, "Should only display one inherited style"); - let inheritProp = inheritRule.textProps[0]; - is(inheritProp.name, "color", "color should have been inherited."); - - finishTest(); - }); -} - -function finishTest() -{ - doc = inspector = view = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(simpleInherit), content); - }, true); - - content.location = "data:text/html;charset=utf-8,browser_inspector_changes.js"; + let inheritRule = elementStyle.rules[1]; + is(inheritRule.domRule.type, ELEMENT_STYLE, "Inherited rule should be an element style, not a rule."); + ok(!!inheritRule.inherited, "Rule should consider itself inherited."); + is(inheritRule.textProps.length, 1, "Should only display one inherited style"); + let inheritProp = inheritRule.textProps[0]; + is(inheritProp.name, "color", "color should have been inherited."); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js b/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js index c0cb69089dce..5e1149703859 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_livepreview.js @@ -1,21 +1,17 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Test that changes are previewed when editing a property value -let doc; -let testElement; -let ruleWindow; -let ruleView; -let inspector; - // Format // { // value : what to type in the field // expected : expected computed style on the targeted element // } -let testData = [ +const TEST_DATA = [ {value: "inline", expected: "inline"}, {value: "inline-block", expected: "inline-block"}, @@ -26,77 +22,45 @@ let testData = [ {escape: true, value: "inline", expected: "block"} ]; -function startTest() -{ +let test = asyncTest(function*() { + yield addTab("data:text/html,test rule view live preview on user changes"); + let style = '#testid {display:block;}'; + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = '
Styled Node
inline element'; + let testElement = getNode("#testid"); - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
inline element'; - testElement = doc.getElementById("testid"); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNode(testElement, inspector); - openRuleView((aInspector, aRuleView) => { - inspector = aInspector; - ruleView = aRuleView; - ruleWindow = aRuleView.doc.defaultView; - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => loopTestData(0)); - }); -} - -function loopTestData(index) -{ - if(index === testData.length) { - finishTest(); - return; + for (let data of TEST_DATA) { + yield testLivePreviewData(data, view, testElement); } +}); + +function* testLivePreviewData(data, ruleView, testElement) { let idRuleEditor = ruleView.element.children[1]._ruleEditor; let propEditor = idRuleEditor.rule.textProps[0].editor; - waitForEditorFocus(propEditor.element, function(aEditor) { - is(inplaceEditor(propEditor.valueSpan), aEditor, "Focused editor should be the value."); - let thisTest = testData[index]; + info("Focusing the property value inplace-editor"); + let editor = yield focusEditableField(propEditor.valueSpan); + is(inplaceEditor(propEditor.valueSpan), editor, "The focused editor is the value"); - // Entering a correct value for the property - for (let ch of thisTest.value) { - EventUtils.sendChar(ch, ruleWindow); - } - if (thisTest.escape) { - EventUtils.synthesizeKey("VK_ESCAPE", {}); - } else { - EventUtils.synthesizeKey("VK_RETURN", {}); - } + info("Enter a value in the editor") + for (let ch of data.value) { + EventUtils.sendChar(ch, ruleView.doc.defaultView); + } + if (data.escape) { + EventUtils.synthesizeKey("VK_ESCAPE", {}); + } else { + EventUtils.synthesizeKey("VK_RETURN", {}); + } - // While the editor is still focused in, the display should have changed already - executeSoon(() => { - is(content.getComputedStyle(testElement).display, - testData[index].expected, - "Element should be previewed as " + testData[index].expected); + yield wait(1); - loopTestData(index + 1); - }); - }); - - EventUtils.synthesizeMouse(propEditor.valueSpan, 1, 1, {}, ruleWindow); -} - -function finishTest() -{ - inspector = ruleWindow = ruleView = null; - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true); - doc = content.document; - waitForFocus(startTest, content); - }, true); - - content.location = "data:text/html,test rule view live preview on user changes"; + // While the editor is still focused in, the display should have changed already + is(content.getComputedStyle(testElement).display, + data.expected, + "Element should be previewed as " + data.expected); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js b/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js index f2c5f5bd2e35..78a9b96dab58 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_manipulation.js @@ -1,87 +1,68 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; +"use strict"; -function simpleOverride(aInspector, aRuleView) -{ - doc.body.innerHTML = '
Styled Node
'; - let element = doc.getElementById("testid"); +// Checking properties orders and overrides in the rule-view - aInspector.selection.setNode(element); - aInspector.once("inspector-updated", () => { - let elementStyle = aRuleView._elementStyle; +let test = asyncTest(function*() { + yield addTab("data:text/html;charset=utf-8,browser_ruleview_manipulation.js"); + let {toolbox, inspector, view} = yield openRuleView(); - let elementRule = elementStyle.rules[0]; - 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."); - is(elementRule.textProps[1], secondProp, "Rules should be in addition order."); + info("Creating the test document and getting the test node"); + content.document.body.innerHTML = '
Styled Node
'; + let element = getNode("#testid"); - promiseDone(elementRule._applyingModifications.then(() => { - is(element.style.getPropertyValue("background-color"), "blue", "Second property should have been used."); + yield selectNode(element, inspector); - secondProp.remove(); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "green", "After deleting second property, first should be used."); + let elementStyle = view._elementStyle; + let elementRule = elementStyle.rules[0]; - secondProp = elementRule.createProperty("background-color", "blue", ""); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "blue", "New property should be used."); + 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."); + 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."); - is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places."); - is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places."); + 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."); - secondProp.setEnabled(false); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "green", "After disabling second property, first value 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(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places."); + is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places."); - firstProp.setEnabled(false); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "", "After disabling both properties, value should be empty."); + 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"); - secondProp.setEnabled(true); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "blue", "Value should be set correctly after re-enabling"); + 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."); - firstProp.setEnabled(true); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "blue", "Re-enabling an earlier property shouldn't make it override a later property."); - is(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places."); - is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places."); + 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"); - firstProp.setValue("purple", ""); - return elementRule._applyingModifications; - }).then(() => { - is(element.style.getPropertyValue("background-color"), "blue", "Modifying an earlier property shouldn't override a later property."); - finishTest(); - })); - }); -} + 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(elementRule.textProps[0], firstProp, "Rules shouldn't have switched places."); + is(elementRule.textProps[1], secondProp, "Rules shouldn't have switched places."); -function finishTest() -{ - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(simpleOverride), content); - }, true); - - content.location = "data:text/html;charset=utf-8,browser_ruleview_manipulation.js"; -} + 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."); +}); diff --git a/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js b/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js index 65e12c728fa0..25f87851deab 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_multiple_properties.js @@ -1,276 +1,233 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let ruleWindow; -let ruleView; -let inspector; -let elementRuleEditor; +"use strict"; -function startTest() -{ - doc.body.innerHTML = '

Testing Multiple Properties

'; +// Test that the rule-view behaves correctly when entering mutliple and/or +// unfinished properties/values in inplace-editors - openRuleView((aInspector, aRuleView) => { - inspector = aInspector; - ruleView = aRuleView; - ruleWindow = aRuleView.doc.defaultView; - selectNewElement().then(testCreateNewMulti); - }); -} +let test = asyncTest(function*() { + yield addTab("data:text/html,test rule view user changes"); + content.document.body.innerHTML = "

Testing Multiple Properties

"; -/* - * Add a new node to the DOM and resolve the promise once it is ready to use + let {toolbox, inspector, view} = yield openRuleView(); + + yield testCreateNewMulti(inspector, view); + yield testCreateNewMultiDuplicates(inspector, view); + yield testCreateNewMultiPriority(inspector, view); + yield testCreateNewMultiUnfinished(inspector, view); + yield testCreateNewMultiPartialUnfinished(inspector, view); + yield testMultiValues(inspector, view); +}); + +/** + * Create a new test element, select it, and return the rule-view ruleEditor */ -function selectNewElement() -{ - let newElement = doc.createElement("div"); +function* createAndSelectNewElement(inspector, view) { + info("Creating a new test element"); + let newElement = content.document.createElement("div"); newElement.textContent = "Test Element"; - doc.body.appendChild(newElement); + content.document.body.appendChild(newElement); - inspector.selection.setNode(newElement, "test"); - let def = promise.defer(); - ruleView.element.addEventListener("CssRuleViewRefreshed", function changed() { - ruleView.element.removeEventListener("CssRuleViewRefreshed", changed); - elementRuleEditor = ruleView.element.children[0]._ruleEditor; - def.resolve(); - }); + info("Selecting the new element and waiting for the inspector to update"); + yield selectNode(newElement, inspector); - return def.promise; + info("Getting the rule-view rule editor for that new element"); + return view.element.children[0]._ruleEditor; } -/* +/** * Begin the creation of a new property, resolving after the editor * has been created. */ -function beginNewProp() -{ - let def = promise.defer(); - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { +function* focusNewProperty(ruleEditor) { + info("Clicking on the close ruleEditor brace to start edition"); + ruleEditor.closeBrace.scrollIntoView(); + let editor = yield focusEditableField(ruleEditor.closeBrace); - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - is(elementRuleEditor.rule.textProps.length, 0, "Should be starting with one new text property."); - is(elementRuleEditor.propertyList.children.length, 1, "Should be starting with two property editors."); + is(inplaceEditor(ruleEditor.newPropSpan), editor, "Focused editor is the new property editor."); + is(ruleEditor.rule.textProps.length, 0, "Starting with one new text property."); + is(ruleEditor.propertyList.children.length, 1, "Starting with two property editors."); - def.resolve(aEditor); - }); - elementRuleEditor.closeBrace.scrollIntoView(); - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); - return def.promise; + return editor; } -/* +/** * Fully create a new property, given some text input */ -function createNewProp(inputValue) -{ - let def = promise.defer(); - beginNewProp().then((aEditor)=>{ - aEditor.input.value = inputValue; +function* createNewProperty(ruleEditor, inputValue) { + info("Creating a new property editor"); + let editor = yield focusNewProperty(ruleEditor); - waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) { - promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => { - def.resolve(); - })); - }); + info("Entering the value " + inputValue); + editor.input.value = inputValue; - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); - }); - - return def.promise; + info("Submitting the new value and waiting for value field focus"); + let onFocus = once(ruleEditor.element, "focus", true); + EventUtils.synthesizeKey("VK_RETURN", {}, ruleEditor.element.ownerDocument.defaultView); + yield onFocus; } -function testCreateNewMulti() -{ - createNewProp( - "color:blue;background : orange ; text-align:center; border-color: green;" - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 4, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 5, "Should have created a new property editor."); +function* testCreateNewMulti(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, + "color:blue;background : orange ; text-align:center; border-color: green;"); - is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "blue", "Should have correct property value"); + is(ruleEditor.rule.textProps.length, 4, "Should have created a new text property."); + is(ruleEditor.propertyList.children.length, 5, "Should have created a new property editor."); - is(elementRuleEditor.rule.textProps[1].name, "background", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "blue", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[2].name, "text-align", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[2].value, "center", "Should have correct property value"); + is(ruleEditor.rule.textProps[1].name, "background", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[3].name, "border-color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[3].value, "green", "Should have correct property value"); + is(ruleEditor.rule.textProps[2].name, "text-align", "Should have correct property name"); + is(ruleEditor.rule.textProps[2].value, "center", "Should have correct property value"); - selectNewElement().then(testCreateNewMultiDuplicates); - }); + is(ruleEditor.rule.textProps[3].name, "border-color", "Should have correct property name"); + is(ruleEditor.rule.textProps[3].value, "green", "Should have correct property value"); + + yield inspector.once("inspector-updated"); } -function testCreateNewMultiDuplicates() -{ - createNewProp( - "color:red;color:orange;color:yellow;color:green;color:blue;color:indigo;color:violet;" - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 7, "Should have created new text properties."); - is(elementRuleEditor.propertyList.children.length, 8, "Should have created new property editors."); +function* testCreateNewMultiDuplicates(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, + "color:red;color:orange;color:yellow;color:green;color:blue;color:indigo;color:violet;"); - is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "red", "Should have correct property value"); + is(ruleEditor.rule.textProps.length, 7, "Should have created new text properties."); + is(ruleEditor.propertyList.children.length, 8, "Should have created new property editors."); - is(elementRuleEditor.rule.textProps[1].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "red", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[2].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[2].value, "yellow", "Should have correct property value"); + is(ruleEditor.rule.textProps[1].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[3].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[3].value, "green", "Should have correct property value"); + is(ruleEditor.rule.textProps[2].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[2].value, "yellow", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[4].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[4].value, "blue", "Should have correct property value"); + is(ruleEditor.rule.textProps[3].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[3].value, "green", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[5].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[5].value, "indigo", "Should have correct property value"); + is(ruleEditor.rule.textProps[4].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[4].value, "blue", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[6].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[6].value, "violet", "Should have correct property value"); + is(ruleEditor.rule.textProps[5].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[5].value, "indigo", "Should have correct property value"); - selectNewElement().then(testCreateNewMultiPriority); - }); + is(ruleEditor.rule.textProps[6].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[6].value, "violet", "Should have correct property value"); + + yield inspector.once("inspector-updated"); } -function testCreateNewMultiPriority() -{ - createNewProp( - "color:red;width:100px;height: 100px;" - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 3, "Should have created new text properties."); - is(elementRuleEditor.propertyList.children.length, 4, "Should have created new property editors."); +function* testCreateNewMultiPriority(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, + "color:red;width:100px;height: 100px;"); - is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "red", "Should have correct property value"); + is(ruleEditor.rule.textProps.length, 3, "Should have created new text properties."); + is(ruleEditor.propertyList.children.length, 4, "Should have created new property editors."); - is(elementRuleEditor.rule.textProps[1].name, "width", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "100px", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "red", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[2].name, "height", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[2].value, "100px", "Should have correct property value"); + is(ruleEditor.rule.textProps[1].name, "width", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "100px", "Should have correct property value"); - selectNewElement().then(testCreateNewMultiUnfinished); - }); + is(ruleEditor.rule.textProps[2].name, "height", "Should have correct property name"); + is(ruleEditor.rule.textProps[2].value, "100px", "Should have correct property value"); + + yield inspector.once("inspector-updated"); } -function testCreateNewMultiUnfinished() -{ - createNewProp( - "color:blue;background : orange ; text-align:center; border-color: " - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 4, "Should have created new text properties."); - is(elementRuleEditor.propertyList.children.length, 4, "Should have created property editors."); +function* testCreateNewMultiUnfinished(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, + "color:blue;background : orange ; text-align:center; border-color: "); - for (let ch of "red") { - EventUtils.sendChar(ch, ruleWindow); - } - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); + is(ruleEditor.rule.textProps.length, 4, "Should have created new text properties."); + is(ruleEditor.propertyList.children.length, 4, "Should have created property editors."); - is(elementRuleEditor.rule.textProps.length, 4, "Should have the same number of text properties."); - is(elementRuleEditor.propertyList.children.length, 5, "Should have added the changed value editor."); + for (let ch of "red") { + EventUtils.sendChar(ch, view.doc.defaultView); + } + EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView); - is(elementRuleEditor.rule.textProps[0].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "blue", "Should have correct property value"); + is(ruleEditor.rule.textProps.length, 4, "Should have the same number of text properties."); + is(ruleEditor.propertyList.children.length, 5, "Should have added the changed value editor."); - is(elementRuleEditor.rule.textProps[1].name, "background", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "blue", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[2].name, "text-align", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[2].value, "center", "Should have correct property value"); + is(ruleEditor.rule.textProps[1].name, "background", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "orange", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[3].name, "border-color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[3].value, "red", "Should have correct property value"); + is(ruleEditor.rule.textProps[2].name, "text-align", "Should have correct property name"); + is(ruleEditor.rule.textProps[2].value, "center", "Should have correct property value"); - selectNewElement().then(testCreateNewMultiPartialUnfinished); - }); + is(ruleEditor.rule.textProps[3].name, "border-color", "Should have correct property name"); + is(ruleEditor.rule.textProps[3].value, "red", "Should have correct property value"); + + yield inspector.once("inspector-updated"); } +function* testCreateNewMultiPartialUnfinished(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, "width: 100px; heig"); -function testCreateNewMultiPartialUnfinished() -{ - createNewProp( - "width: 100px; heig" - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 2, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 2, "Should have created a property editor."); + is(ruleEditor.rule.textProps.length, 2, "Should have created a new text property."); + is(ruleEditor.propertyList.children.length, 2, "Should have created a property editor."); - // Value is focused, lets add multiple rules here and make sure they get added - let valueEditor = elementRuleEditor.propertyList.children[1].querySelector("input"); - valueEditor.value = "10px;background:orangered;color: black;"; - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); + // Value is focused, lets add multiple rules here and make sure they get added + let valueEditor = ruleEditor.propertyList.children[1].querySelector("input"); + valueEditor.value = "10px;background:orangered;color: black;"; + EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView); - is(elementRuleEditor.rule.textProps.length, 4, "Should have added the changed value."); - is(elementRuleEditor.propertyList.children.length, 5, "Should have added the changed value editor."); + is(ruleEditor.rule.textProps.length, 4, "Should have added the changed value."); + is(ruleEditor.propertyList.children.length, 5, "Should have added the changed value editor."); - is(elementRuleEditor.rule.textProps[0].name, "width", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "100px", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "width", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "100px", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[1].name, "heig", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "10px", "Should have correct property value"); + is(ruleEditor.rule.textProps[1].name, "heig", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "10px", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[2].name, "background", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[2].value, "orangered", "Should have correct property value"); + is(ruleEditor.rule.textProps[2].name, "background", "Should have correct property name"); + is(ruleEditor.rule.textProps[2].value, "orangered", "Should have correct property value"); - is(elementRuleEditor.rule.textProps[3].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[3].value, "black", "Should have correct property value"); + is(ruleEditor.rule.textProps[3].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[3].value, "black", "Should have correct property value"); - selectNewElement().then(testMultiValues); - }); + yield inspector.once("inspector-updated"); } -function testMultiValues() -{ - createNewProp( - "width:" - ).then(()=>{ - is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor."); +function* testMultiValues(inspector, view) { + let ruleEditor = yield createAndSelectNewElement(inspector, view); + yield createNewProperty(ruleEditor, "width:"); - // Value is focused, lets add multiple rules here and make sure they get added - let valueEditor = elementRuleEditor.propertyList.children[0].querySelector("input"); - valueEditor.value = "height: 10px;color:blue" - EventUtils.synthesizeKey("VK_RETURN", {}, ruleWindow); + is(ruleEditor.rule.textProps.length, 1, "Should have created a new text property."); + is(ruleEditor.propertyList.children.length, 1, "Should have created a property editor."); - is(elementRuleEditor.rule.textProps.length, 2, "Should have added the changed value."); - is(elementRuleEditor.propertyList.children.length, 3, "Should have added the changed value editor."); + // Value is focused, lets add multiple rules here and make sure they get added + let valueEditor = ruleEditor.propertyList.children[0].querySelector("input"); + valueEditor.value = "height: 10px;color:blue" + EventUtils.synthesizeKey("VK_RETURN", {}, view.doc.defaultView); - EventUtils.synthesizeKey("VK_ESCAPE", {}, ruleWindow); - is(elementRuleEditor.propertyList.children.length, 2, "Should have removed the value editor."); + is(ruleEditor.rule.textProps.length, 2, "Should have added the changed value."); + is(ruleEditor.propertyList.children.length, 3, "Should have added the changed value editor."); - is(elementRuleEditor.rule.textProps[0].name, "width", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[0].value, "height: 10px", "Should have correct property value"); + EventUtils.synthesizeKey("VK_ESCAPE", {}, view.doc.defaultView); + is(ruleEditor.propertyList.children.length, 2, "Should have removed the value editor."); - is(elementRuleEditor.rule.textProps[1].name, "color", "Should have correct property name"); - is(elementRuleEditor.rule.textProps[1].value, "blue", "Should have correct property value"); + is(ruleEditor.rule.textProps[0].name, "width", "Should have correct property name"); + is(ruleEditor.rule.textProps[0].value, "height: 10px", "Should have correct property value"); - finishTest(); - }); -} - -function finishTest() -{ - inspector = ruleWindow = ruleView = doc = elementRuleEditor = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function changedValues_load(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, changedValues_load, true); - doc = content.document; - waitForFocus(startTest, content); - }, true); - - content.location = "data:text/html,test rule view user changes"; + is(ruleEditor.rule.textProps[1].name, "color", "Should have correct property name"); + is(ruleEditor.rule.textProps[1].value, "blue", "Should have correct property value"); + + yield inspector.once("inspector-updated"); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js b/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js index 278a0a780f20..d45e13996370 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_original_source_link.js @@ -2,90 +2,68 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let win; -let doc; -let contentWindow; -let inspector; -let toolbox; +"use strict"; -const TESTCASE_URI = TEST_BASE_HTTPS + "sourcemaps.html"; +// Test that the stylesheet links in the rule view are correct when source maps +// are involved + +const TESTCASE_URI = TEST_URL_ROOT + "sourcemaps.html"; const PREF = "devtools.styleeditor.source-maps-enabled"; - const SCSS_LOC = "sourcemaps.scss:4"; const CSS_LOC = "sourcemaps.css:1"; -function test() -{ - waitForExplicitFinish(); - +let test = asyncTest(function*() { + info("Setting the " + PREF + " pref to true"); Services.prefs.setBoolPref(PREF, true); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, - true); - doc = content.document; - waitForFocus(openToolbox, content); - }, true); + info("Opening the test page and opening the inspector"); + yield addTab(TESTCASE_URI); + let {toolbox, inspector, view} = yield openRuleView(); - content.location = TESTCASE_URI; -} + info("Selecting the test node"); + yield selectNode("div", inspector); -function openToolbox() { - let target = TargetFactory.forTab(gBrowser.selectedTab); + yield verifyLinkText(SCSS_LOC, view); - gDevTools.showToolbox(target, "inspector").then(function(aToolbox) { - toolbox = aToolbox; - inspector = toolbox.getCurrentPanel(); - inspector.sidebar.select("ruleview"); - highlightNode(); - }); -} - -function highlightNode() -{ - // Highlight a node. - let div = content.document.getElementsByTagName("div")[0]; - - inspector.selection.setNode(div, "test"); - inspector.once("inspector-updated", () => { - is(inspector.selection.node, div, "selection matches the div element"); - testRuleViewLink(); - }); -} - -function testRuleViewLink() { - verifyLinkText(SCSS_LOC, testTogglePref); -} - -function testTogglePref() { + info("Setting the " + PREF + " pref to false"); Services.prefs.setBoolPref(PREF, false); + yield verifyLinkText(CSS_LOC, view); - verifyLinkText(CSS_LOC, () => { - Services.prefs.setBoolPref(PREF, true); + info("Setting the " + PREF + " pref to true again"); + Services.prefs.setBoolPref(PREF, true); - testClickingLink(); - }) -} + yield testClickingLink(toolbox, view); + yield checkDisplayedStylesheet(toolbox); -function testClickingLink() { - toolbox.once("styleeditor-ready", function(id, aToolbox) { - let panel = toolbox.getCurrentPanel(); - panel.UI.on("editor-selected", (event, editor) => { - // The style editor selects the first sheet at first load before - // selecting the desired sheet. - if (editor.styleSheet.href.endsWith("scss")) { - info("original source editor selected"); - editor.getSourceEditor().then(editorSelected); - } - }); - }); + info("Clearing the " + PREF + " pref"); + Services.prefs.clearUserPref(PREF); +}); - let link = getLinkByIndex(1); +function* testClickingLink(toolbox, view) { + info("Listening for switch to the style editor"); + let onStyleEditorReady = toolbox.once("styleeditor-ready"); - info("clicking rule view link"); + info("Finding the stylesheet link and clicking it"); + let link = getRuleViewLinkByIndex(view, 1); link.scrollIntoView(); link.click(); + yield onStyleEditorReady; +} + +function checkDisplayedStylesheet(toolbox) { + let def = promise.defer(); + + let panel = toolbox.getCurrentPanel(); + panel.UI.on("editor-selected", (event, editor) => { + // The style editor selects the first sheet at first load before + // selecting the desired sheet. + if (editor.styleSheet.href.endsWith("scss")) { + info("Original source editor selected"); + editor.getSourceEditor().then(editorSelected).then(def.resolve, def.reject); + } + }); + + return def.promise; } function editorSelected(editor) { @@ -94,38 +72,13 @@ function editorSelected(editor) { let {line, col} = editor.sourceEditor.getCursor(); is(line, 3, "cursor is at correct line number in original source"); - - finishUp(); } -/* Helpers */ - -function verifyLinkText(text, callback) { - let label = getLinkByIndex(1).querySelector("label"); - - waitForSuccess({ - name: "link text changed to display correct location: " + text, - validatorFn: function() - { - return label.getAttribute("value") == text; - }, - successFn: callback, - failureFn: callback, - }); -} - -function getLinkByIndex(aIndex) -{ - let contentDoc = ruleView().doc; - contentWindow = contentDoc.defaultView; - let links = contentDoc.querySelectorAll(".ruleview-rule-source"); - return links[aIndex]; -} - -function finishUp() -{ - gBrowser.removeCurrentTab(); - contentWindow = doc = inspector = toolbox = win = null; - Services.prefs.clearUserPref(PREF); - finish(); +function verifyLinkText(text, view) { + info("Verifying that the rule-view stylesheet link is " + text); + let label = getRuleViewLinkByIndex(view, 1).querySelector("label"); + return waitForSuccess( + () => label.getAttribute("value") == text, + "Link text changed to display correct location: " + text + ); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_override.js b/browser/devtools/styleinspector/test/browser_ruleview_override.js index 89607e1969c3..152e1a0d288c 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_override.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_override.js @@ -1,60 +1,67 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let inspector; -let view; +"use strict"; -function simpleOverride(aInspector, aRuleView) -{ - inspector = aInspector; - view = aRuleView; - let style = '' + +// Test the display of overridden declarations in the rule-view + +let test = asyncTest(function*() { + yield addTab("data:text/html;charset=utf-8,browser_ruleview_override.js"); + let {toolbox, inspector, view} = yield openRuleView(); + + yield simpleOverride(inspector, view); + yield partialOverride(inspector, view); + yield importantOverride(inspector, view); + yield disableOverride(inspector, view); +}); + +function* createTestContent(inspector, style) { + let onMutated = inspector.once("markupmutation"); + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = '
Styled Node
'; + yield onMutated; + yield selectNode("#testid", inspector); + return styleNode; +} + +function* simpleOverride(inspector, view) { + let styleNode = yield createTestContent(inspector, '' + '#testid {' + ' background-color: blue;' + '} ' + '.testclass {' + ' background-color: green;' + - '}'; + '}'); - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - inspector.once("markupmutation", () => { - inspector.selection.setNode(doc.getElementById("testid")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + let elementStyle = view._elementStyle; - let idRule = elementStyle.rules[1]; - let idProp = idRule.textProps[0]; - is(idProp.name, "background-color", "First ID prop should be background-color"); - ok(!idProp.overridden, "ID prop should not be overridden."); + let idRule = elementStyle.rules[1]; + let idProp = idRule.textProps[0]; + is(idProp.name, "background-color", "First ID prop should be background-color"); + ok(!idProp.overridden, "ID prop should not be overridden."); - let classRule = elementStyle.rules[2]; - let classProp = classRule.textProps[0]; - is(classProp.name, "background-color", "First class prop should be background-color"); - ok(classProp.overridden, "Class property should be overridden."); + let classRule = elementStyle.rules[2]; + let classProp = classRule.textProps[0]; + is(classProp.name, "background-color", "First class prop should be background-color"); + ok(classProp.overridden, "Class property should be overridden."); - // Override background-color by changing the element style. - let elementRule = elementStyle.rules[0]; - elementRule.createProperty("background-color", "purple", ""); - promiseDone(elementRule._applyingModifications.then(() => { - let elementProp = elementRule.textProps[0]; - is(classProp.name, "background-color", "First element prop should now be background-color"); - ok(!elementProp.overridden, "Element style property should not be overridden"); - ok(idProp.overridden, "ID property should be overridden"); - ok(classProp.overridden, "Class property should be overridden"); + // Override background-color by changing the element style. + let elementRule = elementStyle.rules[0]; + elementRule.createProperty("background-color", "purple", ""); + yield elementRule._applyingModifications; - styleNode.parentNode.removeChild(styleNode); - partialOverride(); - })); - }); - }); + let elementProp = elementRule.textProps[0]; + is(classProp.name, "background-color", "First element prop should now be background-color"); + ok(!elementProp.overridden, "Element style property should not be overridden"); + ok(idProp.overridden, "ID property should be overridden"); + ok(classProp.overridden, "Class property should be overridden"); + + styleNode.remove(); } -function partialOverride() -{ - let style = '' + +function* partialOverride(inspector, view) { + let styleNode = yield createTestContent(inspector, '' + // Margin shorthand property... '.testclass {' + ' margin: 2px;' + @@ -62,36 +69,28 @@ function partialOverride() // ... will be partially overridden. '#testid {' + ' margin-left: 1px;' + - '}'; + '}'); - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - inspector.once("markupmutation", () => { - inspector.selection.setNode(doc.getElementById("testid")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + let elementStyle = view._elementStyle; - let classRule = elementStyle.rules[2]; - let classProp = classRule.textProps[0]; - ok(!classProp.overridden, "Class prop shouldn't be overridden, some props are still being used."); - for (let computed of classProp.computed) { - if (computed.name.indexOf("margin-left") == 0) { - ok(computed.overridden, "margin-left props should be overridden."); - } else { - ok(!computed.overridden, "Non-margin-left props should not be overridden."); - } - } + let classRule = elementStyle.rules[2]; + let classProp = classRule.textProps[0]; + ok(!classProp.overridden, + "Class prop shouldn't be overridden, some props are still being used."); - styleNode.parentNode.removeChild(styleNode); + for (let computed of classProp.computed) { + if (computed.name.indexOf("margin-left") == 0) { + ok(computed.overridden, "margin-left props should be overridden."); + } else { + ok(!computed.overridden, "Non-margin-left props should not be overridden."); + } + } - importantOverride(); - }); - }); + styleNode.remove(); } -function importantOverride() -{ - let style = '' + +function* importantOverride(inspector, view) { + let styleNode = yield createTestContent(inspector, '' + // Margin shorthand property... '.testclass {' + ' background-color: green !important;' + @@ -99,84 +98,49 @@ function importantOverride() // ... will be partially overridden. '#testid {' + ' background-color: blue;' + - '}'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - inspector.once("markupmutation", () => { - inspector.selection.setNode(doc.getElementById("testid")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + '}'); - let idRule = elementStyle.rules[1]; - let idProp = idRule.textProps[0]; - ok(idProp.overridden, "Not-important rule should be overridden."); + let elementStyle = view._elementStyle; - let classRule = elementStyle.rules[2]; - let classProp = classRule.textProps[0]; - ok(!classProp.overridden, "Important rule should not be overridden."); + let idRule = elementStyle.rules[1]; + let idProp = idRule.textProps[0]; + ok(idProp.overridden, "Not-important rule should be overridden."); - styleNode.parentNode.removeChild(styleNode); + let classRule = elementStyle.rules[2]; + let classProp = classRule.textProps[0]; + ok(!classProp.overridden, "Important rule should not be overridden."); - let elementRule = elementStyle.rules[0]; - let elementProp = elementRule.createProperty("background-color", "purple", "important"); - promiseDone(elementRule._applyingModifications.then(() => { - ok(classProp.overridden, "New important prop should override class property."); - ok(!elementProp.overridden, "New important prop should not be overriden."); + styleNode.remove(); - disableOverride(); - })); - }); - }); + let elementRule = elementStyle.rules[0]; + let elementProp = elementRule.createProperty("background-color", "purple", "important"); + yield elementRule._applyingModifications; + + ok(classProp.overridden, "New important prop should override class property."); + ok(!elementProp.overridden, "New important prop should not be overriden."); } -function disableOverride() -{ - let style = '' + +function* disableOverride(inspector, view) { + let styleNode = yield createTestContent(inspector, '' + '#testid {' + ' background-color: blue;' + '}' + '.testclass {' + ' background-color: green;' + - '}'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - inspector.once("markupmutation", () => { - inspector.selection.setNode(doc.getElementById("testid")); - inspector.once("inspector-updated", () => { - let elementStyle = view._elementStyle; + '}'); - let idRule = elementStyle.rules[1]; - let idProp = idRule.textProps[0]; - idProp.setEnabled(false); - promiseDone(idRule._applyingModifications.then(() => { - let classRule = elementStyle.rules[2]; - let classProp = classRule.textProps[0]; - ok(!classProp.overridden, "Class prop should not be overridden after id prop was disabled."); + let elementStyle = view._elementStyle; - styleNode.parentNode.removeChild(styleNode); + let idRule = elementStyle.rules[1]; + let idProp = idRule.textProps[0]; - finishTest(); - })); - }); - }); -} - -function finishTest() -{ - doc = inspector = view = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(simpleOverride), content); - }, true); - - content.location = "data:text/html;charset=utf-8,browser_ruleview_override.js"; + idProp.setEnabled(false); + yield idRule._applyingModifications; + + let classRule = elementStyle.rules[2]; + let classProp = classRule.textProps[0]; + ok(!classProp.overridden, "Class prop should not be overridden after id prop was disabled."); + + styleNode.remove(); + yield inspector.once("inspector-updated"); } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js b/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js index ca93550015e4..507840b38f12 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_pseudoelement.js @@ -1,320 +1,273 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let inspector; -let view; +"use strict"; -const TEST_URI = "http://example.com/browser/browser/" + - "devtools/styleinspector/test/" + - "browser_ruleview_pseudoelement.html"; +const TEST_URI = TEST_URL_ROOT + "browser_ruleview_pseudoelement.html"; -function testPseudoElements(aInspector, aRuleView) -{ - inspector = aInspector; - view = aRuleView; +let test = asyncTest(function*() { + yield addTab(TEST_URI); + let {toolbox, inspector, view} = yield openRuleView(); - testTopLeft(); + yield testTopLeft(inspector, view); + yield testTopRight(inspector, view); + yield testBottomRight(inspector, view); + yield testBottomLeft(inspector, view); + yield testParagraph(inspector, view); + yield testBody(inspector, view); +}); + +function* testTopLeft(inspector, view) { + let { + rules, + element, + elementStyle + } = yield assertPseudoElementRulesNumbers("#topleft", inspector, view, { + elementRulesNb: 4, + afterRulesNb: 1, + beforeRulesNb: 2, + firstLineRulesNb: 0, + firstLetterRulesNb: 0, + selectionRulesNb: 0 + }); + + let gutters = assertGutters(view); + + // Make sure that clicking on the twisty hides pseudo elements + let expander = gutters[0].querySelector(".ruleview-expander"); + ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded"); + expander.click(); + ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty"); + expander.click(); + ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again"); + + // Make sure that dblclicking on the header container also toggles the pseudo elements + EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview")); + ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking"); + + let defaultView = element.ownerDocument.defaultView; + let elementRule = rules.elementRules[0]; + let elementRuleView = [].filter.call(view.element.children, e => { + return e._ruleEditor && e._ruleEditor.rule === elementRule; + })[0]._ruleEditor; + + let elementAfterRule = rules.afterRules[0]; + let elementAfterRuleView = [].filter.call(view.element.children, (e) => { + return e._ruleEditor && e._ruleEditor.rule === elementAfterRule; + })[0]._ruleEditor; + + is + ( + convertTextPropsToString(elementAfterRule.textProps), + "background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " + + "border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px", + "TopLeft after properties are correct" + ); + + let elementBeforeRule = rules.beforeRules[0]; + let elementBeforeRuleView = [].filter.call(view.element.children, (e) => { + return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule; + })[0]._ruleEditor; + + is + ( + convertTextPropsToString(elementBeforeRule.textProps), + "top: 0px; left: 0px", + "TopLeft before properties are correct" + ); + + let firstProp = elementAfterRuleView.addProperty("background-color", "rgb(0, 255, 0)", ""); + let secondProp = elementAfterRuleView.addProperty("padding", "100px", ""); + + is (firstProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 2], + "First added property is on back of array"); + is (secondProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 1], + "Second added property is on back of array"); + + yield elementAfterRule._applyingModifications; + + is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), + "rgb(0, 255, 0)", "Added property should have been used."); + is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), + "100px", "Added property should have been used."); + is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), + "32px", "Added property should not apply to element"); + + secondProp.setEnabled(false); + yield elementAfterRule._applyingModifications; + + is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "0px", + "Disabled property should have been used."); + is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px", + "Added property should not apply to element"); + + secondProp.setEnabled(true); + yield elementAfterRule._applyingModifications; + + is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "100px", + "Enabled property should have been used."); + is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px", + "Added property should not apply to element"); + + let firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", ""); + yield elementRule._applyingModifications; + + is(defaultView.getComputedStyle(element).getPropertyValue("background-color"), "rgb(0, 0, 255)", + "Added property should have been used."); + is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), "rgb(0, 255, 0)", + "Added prop does not apply to pseudo"); } -function testTopLeft() -{ - testNode(doc.querySelector("#topleft"), (element, elementStyle) => { - let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; }); - let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; }); - let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; }); - let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; }); - let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; }); - let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; }); +function* testTopRight(inspector, view) { + let { + rules, + element, + elementStyle + } = yield assertPseudoElementRulesNumbers("#topright", inspector, view, { + elementRulesNb: 4, + afterRulesNb: 1, + beforeRulesNb: 2, + firstLineRulesNb: 0, + firstLetterRulesNb: 0, + selectionRulesNb: 0 + }); - is(elementRules.length, 4, "TopLeft has the correct number of non psuedo element rules"); - is(afterRules.length, 1, "TopLeft has the correct number of :after rules"); - is(beforeRules.length, 2, "TopLeft has the correct number of :before rules"); - is(firstLineRules.length, 0, "TopLeft has the correct number of :first-line rules"); - is(firstLetterRules.length, 0, "TopLeft has the correct number of :first-letter rules"); - is(selectionRules.length, 0, "TopLeft has the correct number of :selection rules"); + let gutters = assertGutters(view); - let gutters = view.element.querySelectorAll(".theme-gutter"); - is (gutters.length, 3, "There are three gutter headings"); - is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct"); - is (gutters[1].textContent, "This Element", "Gutter heading is correct"); - is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct"); + let expander = gutters[0].querySelector(".ruleview-expander"); + ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements remain collapsed after switching element"); + expander.scrollIntoView(); + expander.click(); + ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are shown again after clicking twisty"); +} - // Make sure that clicking on the twisty hides pseudo elements - let expander = gutters[0].querySelector(".ruleview-expander"); - ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded"); - expander.click(); - ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by twisty"); - expander.click(); - ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are expanded again"); - - // Make sure that dblclicking on the header container also toggles the pseudo elements - EventUtils.synthesizeMouseAtCenter(gutters[0], {clickCount: 2}, inspector.sidebar.getWindowForTab("ruleview")); - ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are collapsed by dblclicking"); - - let defaultView = element.ownerDocument.defaultView; - let elementRule = elementRules[0]; - let elementRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementRule; - })[0]._ruleEditor; - - let elementAfterRule = afterRules[0]; - let elementAfterRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementAfterRule; - })[0]._ruleEditor; - - is - ( - convertTextPropsToString(elementAfterRule.textProps), - "background: none repeat scroll 0% 0% red; content: \" \"; position: absolute; " + - "border-radius: 50%; height: 32px; width: 32px; top: 50%; left: 50%; margin-top: -16px; margin-left: -16px", - "TopLeft after properties are correct" - ); - - let elementBeforeRule = beforeRules[0]; - let elementBeforeRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementBeforeRule; - })[0]._ruleEditor; - - is - ( - convertTextPropsToString(elementBeforeRule.textProps), - "top: 0px; left: 0px", - "TopLeft before properties are correct" - ); - - let firstProp = elementAfterRuleView.addProperty("background-color", "rgb(0, 255, 0)", ""); - let secondProp = elementAfterRuleView.addProperty("padding", "100px", ""); - - is (firstProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 2], - "First added property is on back of array"); - is (secondProp, elementAfterRule.textProps[elementAfterRule.textProps.length - 1], - "Second added property is on back of array"); - - promiseDone(elementAfterRule._applyingModifications.then(() => { - is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), - "rgb(0, 255, 0)", "Added property should have been used."); - is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), - "100px", "Added property should have been used."); - is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), - "32px", "Added property should not apply to element"); - - secondProp.setEnabled(false); - - return elementAfterRule._applyingModifications; - }).then(() => { - is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "0px", - "Disabled property should have been used."); - is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px", - "Added property should not apply to element"); - - secondProp.setEnabled(true); - - return elementAfterRule._applyingModifications; - }).then(() => { - is(defaultView.getComputedStyle(element, ":after").getPropertyValue("padding-top"), "100px", - "Enabled property should have been used."); - is(defaultView.getComputedStyle(element).getPropertyValue("padding-top"), "32px", - "Added property should not apply to element"); - - let firstProp = elementRuleView.addProperty("background-color", "rgb(0, 0, 255)", ""); - - return elementRule._applyingModifications; - }).then(() => { - is(defaultView.getComputedStyle(element).getPropertyValue("background-color"), "rgb(0, 0, 255)", - "Added property should have been used."); - is(defaultView.getComputedStyle(element, ":after").getPropertyValue("background-color"), "rgb(0, 255, 0)", - "Added prop does not apply to pseudo"); - - testTopRight(); - })); +function* testBottomRight(inspector, view) { + yield assertPseudoElementRulesNumbers("#bottomright", inspector, view, { + elementRulesNb: 4, + afterRulesNb: 1, + beforeRulesNb: 3, + firstLineRulesNb: 0, + firstLetterRulesNb: 0, + selectionRulesNb: 0 }); } -function testTopRight() -{ - testNode(doc.querySelector("#topright"), (element, elementStyle) => { - - let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; }); - let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; }); - let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; }); - let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; }); - let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; }); - let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; }); - - is(elementRules.length, 4, "TopRight has the correct number of non psuedo element rules"); - is(afterRules.length, 1, "TopRight has the correct number of :after rules"); - is(beforeRules.length, 2, "TopRight has the correct number of :before rules"); - is(firstLineRules.length, 0, "TopRight has the correct number of :first-line rules"); - is(firstLetterRules.length, 0, "TopRight has the correct number of :first-letter rules"); - is(selectionRules.length, 0, "TopRight has the correct number of :selection rules"); - - let gutters = view.element.querySelectorAll(".theme-gutter"); - is (gutters.length, 3, "There are three gutter headings"); - is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct"); - is (gutters[1].textContent, "This Element", "Gutter heading is correct"); - is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct"); - - let expander = gutters[0].querySelector(".ruleview-expander"); - ok (!view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements remain collapsed after switching element"); - expander.scrollIntoView(); - expander.click(); - ok (view.element.classList.contains("show-pseudo-elements"), "Pseudo Elements are shown again after clicking twisty"); - - testBottomRight(); +function* testBottomLeft(inspector, view) { + yield assertPseudoElementRulesNumbers("#bottomleft", inspector, view, { + elementRulesNb: 4, + afterRulesNb: 1, + beforeRulesNb: 2, + firstLineRulesNb: 0, + firstLetterRulesNb: 0, + selectionRulesNb: 0 }); } -function testBottomRight() -{ - testNode(doc.querySelector("#bottomright"), (element, elementStyle) => { - - let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; }); - let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; }); - let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; }); - let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; }); - let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; }); - let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; }); - - is(elementRules.length, 4, "BottomRight has the correct number of non psuedo element rules"); - is(afterRules.length, 1, "BottomRight has the correct number of :after rules"); - is(beforeRules.length, 3, "BottomRight has the correct number of :before rules"); - is(firstLineRules.length, 0, "BottomRight has the correct number of :first-line rules"); - is(firstLetterRules.length, 0, "BottomRight has the correct number of :first-letter rules"); - is(selectionRules.length, 0, "BottomRight has the correct number of :selection rules"); - - testBottomLeft(); - }); -} - -function testBottomLeft() -{ - testNode(doc.querySelector("#bottomleft"), (element, elementStyle) => { - - let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; }); - let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; }); - let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; }); - let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; }); - let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; }); - let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; }); - - is(elementRules.length, 4, "BottomLeft has the correct number of non psuedo element rules"); - is(afterRules.length, 1, "BottomLeft has the correct number of :after rules"); - is(beforeRules.length, 2, "BottomLeft has the correct number of :before rules"); - is(firstLineRules.length, 0, "BottomLeft has the correct number of :first-line rules"); - is(firstLetterRules.length, 0, "BottomLeft has the correct number of :first-letter rules"); - is(selectionRules.length, 0, "BottomLeft has the correct number of :selection rules"); - - testParagraph(); - }); -} - -function testParagraph() -{ - testNode(doc.querySelector("#bottomleft p"), (element, elementStyle) => { - - let elementRules = elementStyle.rules.filter((rule) => { return !rule.pseudoElement; }); - let afterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":after"; }); - let beforeRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":before"; }); - let firstLineRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-line"; }); - let firstLetterRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":first-letter"; }); - let selectionRules = elementStyle.rules.filter((rule) => { return rule.pseudoElement === ":-moz-selection"; }); - - is(elementRules.length, 3, "Paragraph has the correct number of non psuedo element rules"); - is(afterRules.length, 0, "Paragraph has the correct number of :after rules"); - is(beforeRules.length, 0, "Paragraph has the correct number of :before rules"); - is(firstLineRules.length, 1, "Paragraph has the correct number of :first-line rules"); - is(firstLetterRules.length, 1, "Paragraph has the correct number of :first-letter rules"); - is(selectionRules.length, 1, "Paragraph has the correct number of :selection rules"); - - let gutters = view.element.querySelectorAll(".theme-gutter"); - is (gutters.length, 3, "There are three gutter headings"); - is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct"); - is (gutters[1].textContent, "This Element", "Gutter heading is correct"); - is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct"); - - let elementFirstLineRule = firstLineRules[0]; - let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule; - })[0]._ruleEditor; - - is - ( - convertTextPropsToString(elementFirstLineRule.textProps), - "background: none repeat scroll 0% 0% blue", - "Paragraph first-line properties are correct" - ); - - let elementFirstLetterRule = firstLetterRules[0]; - let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule; - })[0]._ruleEditor; - - is - ( - convertTextPropsToString(elementFirstLetterRule.textProps), - "color: red; font-size: 130%", - "Paragraph first-letter properties are correct" - ); - - let elementSelectionRule = selectionRules[0]; - let elementSelectionRuleView = [].filter.call(view.element.children, (e) => { - return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule; - })[0]._ruleEditor; - - is - ( - convertTextPropsToString(elementSelectionRule.textProps), - "color: white; background: none repeat scroll 0% 0% black", - "Paragraph first-letter properties are correct" - ); - - testBody(); - }); -} - -function testBody() { - - testNode(doc.querySelector("body"), (element, elementStyle) => { - - let gutters = view.element.querySelectorAll(".theme-gutter"); - is (gutters.length, 0, "There are no gutter headings"); - - finishTest(); +function* testParagraph(inspector, view) { + let { + rules, + element, + elementStyle + } = yield assertPseudoElementRulesNumbers("#bottomleft p", inspector, view, { + elementRulesNb: 3, + afterRulesNb: 0, + beforeRulesNb: 0, + firstLineRulesNb: 1, + firstLetterRulesNb: 1, + selectionRulesNb: 1 }); + let gutters = assertGutters(view); + + let elementFirstLineRule = rules.firstLineRules[0]; + let elementFirstLineRuleView = [].filter.call(view.element.children, (e) => { + return e._ruleEditor && e._ruleEditor.rule === elementFirstLineRule; + })[0]._ruleEditor; + + is + ( + convertTextPropsToString(elementFirstLineRule.textProps), + "background: none repeat scroll 0% 0% blue", + "Paragraph first-line properties are correct" + ); + + let elementFirstLetterRule = rules.firstLetterRules[0]; + let elementFirstLetterRuleView = [].filter.call(view.element.children, (e) => { + return e._ruleEditor && e._ruleEditor.rule === elementFirstLetterRule; + })[0]._ruleEditor; + + is + ( + convertTextPropsToString(elementFirstLetterRule.textProps), + "color: red; font-size: 130%", + "Paragraph first-letter properties are correct" + ); + + let elementSelectionRule = rules.selectionRules[0]; + let elementSelectionRuleView = [].filter.call(view.element.children, (e) => { + return e._ruleEditor && e._ruleEditor.rule === elementSelectionRule; + })[0]._ruleEditor; + + is + ( + convertTextPropsToString(elementSelectionRule.textProps), + "color: white; background: none repeat scroll 0% 0% black", + "Paragraph first-letter properties are correct" + ); } + +function* testBody(inspector, view) { + let {element, elementStyle} = yield testNode("body", inspector, view); + + let gutters = view.element.querySelectorAll(".theme-gutter"); + is (gutters.length, 0, "There are no gutter headings"); +} + function convertTextPropsToString(textProps) { - return textProps.map((t) => { - return t.name + ": " + t.value; - }).join("; "); + return textProps.map(t => t.name + ": " + t.value).join("; "); } -function testNode(node, cb) -{ - inspector.once("inspector-updated", () => { - cb(node, view._elementStyle) - }); - inspector.selection.setNode(node); +function* testNode(selector, inspector, view) { + let element = getNode(selector); + yield selectNode(element, inspector); + let elementStyle = view._elementStyle; + return {element: element, elementStyle: elementStyle}; } -function finishTest() -{ - doc = inspector = view = null; - gBrowser.removeCurrentTab(); - finish(); +function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) { + let {element, elementStyle} = yield testNode(selector, inspector, view); + + let rules = { + elementRules: elementStyle.rules.filter(rule => !rule.pseudoElement), + afterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":after"), + beforeRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":before"), + firstLineRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-line"), + firstLetterRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":first-letter"), + selectionRules: elementStyle.rules.filter(rule => rule.pseudoElement === ":-moz-selection") + }; + + is(rules.elementRules.length, ruleNbs.elementRulesNb, selector + + " has the correct number of non pseudo element rules"); + is(rules.afterRules.length, ruleNbs.afterRulesNb, selector + + " has the correct number of :after rules"); + is(rules.beforeRules.length, ruleNbs.beforeRulesNb, selector + + " has the correct number of :before 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: rules, element: element, elementStyle: elementStyle}; } -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(testPseudoElements), content); - }, true); - - content.location = TEST_URI; +function assertGutters(view) { + let gutters = view.element.querySelectorAll(".theme-gutter"); + is (gutters.length, 3, "There are 3 gutter headings"); + is (gutters[0].textContent, "Pseudo-elements", "Gutter heading is correct"); + is (gutters[1].textContent, "This Element", "Gutter heading is correct"); + is (gutters[2].textContent, "Inherited from body", "Gutter heading is correct"); + return gutters; } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_ui.js b/browser/devtools/styleinspector/test/browser_ruleview_ui.js index c13f2dcc74ea..2e58c3f3ed0f 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_ui.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_ui.js @@ -1,17 +1,26 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; -let inspector; -let ruleWindow; -let ruleView; +"use strict"; -function startTest(aInspector, aRuleView) -{ - inspector = aInspector; - ruleWindow = aRuleView.doc.defaultView; - ruleView = aRuleView; +// Test all sorts of additions and updates of properties in the rule-view +// FIXME: TO BE SPLIT IN *MANY* SMALLER TESTS + +let test = asyncTest(function*() { + yield addTab("data:text/html;charset=utf-8,browser_ruleview_ui.js"); + let {toolbox, inspector, view} = yield openRuleView(); + + yield testContentAfterNodeSelection(inspector, view); + yield testCancelNew(inspector, view); + yield testCancelNewOnEscape(inspector, view); + yield testCreateNew(inspector, view); + yield testEditProperty(inspector, view); + yield testDisableProperty(inspector, view); + yield testPropertyStillMarkedDirty(inspector, view); +}); + +function* testContentAfterNodeSelection(inspector, ruleView) { let style = "" + "#testid {" + " background-color: blue;" + @@ -20,233 +29,183 @@ function startTest(aInspector, aRuleView) " background-color: green;" + "}"; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = "
Styled Node
" + - "
Styled Node
"; + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = "
Styled Node
" + + "
Styled Node
"; - let testElement = doc.getElementById("testid"); - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => { - is(ruleView.element.querySelectorAll("#noResults").length, 0, "After a highlight, no longer has a no-results element."); - inspector.selection.setNode(null); - inspector.once("inspector-updated", () => { - is(ruleView.element.querySelectorAll("#noResults").length, 1, "After highlighting null, has a no-results element again."); - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => { - let classEditor = ruleView.element.children[2]._ruleEditor; - is(classEditor.selectorText.querySelector(".ruleview-selector-matched").textContent, ".testclass", ".textclass should be matched."); - is(classEditor.selectorText.querySelector(".ruleview-selector-unmatched").textContent, ".unmatched", ".unmatched should not be matched."); + yield selectNode("#testid", inspector); + is(ruleView.element.querySelectorAll("#noResults").length, 0, + "After a highlight, no longer has a no-results element."); - testCancelNew(); - }); - }); - }); + yield clearCurrentNodeSelection(inspector) + is(ruleView.element.querySelectorAll("#noResults").length, 1, + "After highlighting null, has a no-results element again."); + + yield selectNode("#testid", inspector); + let classEditor = ruleView.element.children[2]._ruleEditor; + is(classEditor.selectorText.querySelector(".ruleview-selector-matched").textContent, + ".testclass", ".textclass should be matched."); + is(classEditor.selectorText.querySelector(".ruleview-selector-unmatched").textContent, + ".unmatched", ".unmatched should not be matched."); } -function testCancelNew() -{ +function* testCancelNew(inspector, ruleView) { // Start at the beginning: start to add a rule to the element's style // declaration, but leave it empty. let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - waitForEditorBlur(aEditor, function () { - ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel."); - is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); - ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); - testCancelNewOnEscape(); - }); - aEditor.input.blur(); - }); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, + "Property editor is focused"); + + let onBlur = once(editor.input, "blur"); + editor.input.blur(); + yield onBlur; + + ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel."); + is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); + ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); } -function testCancelNewOnEscape() -{ +function* testCancelNewOnEscape(inspector, ruleView) { // Start at the beginning: start to add a rule to the element's style // declaration, add some text, then press escape. let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); - for (let ch of "background") { - EventUtils.sendChar(ch, ruleWindow); - } - waitForEditorBlur(aEditor, function () { - ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel."); - is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); - ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); - testCreateNew(); - }); - EventUtils.synthesizeKey("VK_ESCAPE", { }); - }); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, "Next focused editor should be the new property editor."); + for (let ch of "background") { + EventUtils.sendChar(ch, ruleView.doc.defaultView); + } + + let onBlur = once(editor.input, "blur"); + EventUtils.synthesizeKey("VK_ESCAPE", {}); + yield onBlur; + + ok(!elementRuleEditor.rule._applyingModifications, "Shouldn't have an outstanding modification request after a cancel."); + is(elementRuleEditor.rule.textProps.length, 0, "Should have canceled creating a new text property."); + ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties."); } -function testCreateNew() -{ +function* testCreateNew(inspector, ruleView) { // Create a new property. let elementRuleEditor = ruleView.element.children[0]._ruleEditor; - waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor."); + let editor = yield focusEditableField(elementRuleEditor.closeBrace); - let input = aEditor.input; + is(inplaceEditor(elementRuleEditor.newPropSpan), editor, + "Next focused editor should be the new property editor."); - ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected."); + let input = editor.input; - // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665). - EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow); - input.select(); + ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, + "Editor contents are selected."); - input.value = "background-color"; + // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665). + EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.doc.defaultView); + input.select(); - waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) { - promiseDone(expectRuleChange(elementRuleEditor.rule).then(() => { - is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property."); - is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor."); - let textProp = elementRuleEditor.rule.textProps[0]; - is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now."); + info("Entering the property name"); + input.value = "background-color"; - aEditor.input.value = "purple"; - waitForEditorBlur(aEditor, function() { - expectRuleChange(elementRuleEditor.rule).then(() => { - is(textProp.value, "purple", "Text prop should have been changed."); - testEditProperty(); - }); - }); + info("Pressing RETURN and waiting for the value field focus"); + let onFocus = once(elementRuleEditor.element, "focus", true); + EventUtils.sendKey("return", ruleView.doc.defaultView); + yield onFocus; + yield elementRuleEditor.rule._applyingModifications; - aEditor.input.blur(); - })); - }); - EventUtils.sendKey("return", ruleWindow); - }); + editor = inplaceEditor(ruleView.doc.activeElement); - EventUtils.synthesizeMouse(elementRuleEditor.closeBrace, 1, 1, - { }, - ruleWindow); + is(elementRuleEditor.rule.textProps.length, 1, "Should have created a new text property."); + is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor."); + let textProp = elementRuleEditor.rule.textProps[0]; + is(editor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now."); + + editor.input.value = "purple"; + let onBlur = once(editor.input, "blur"); + editor.input.blur(); + yield onBlur; + yield elementRuleEditor.rule._applyingModifications; + + is(textProp.value, "purple", "Text prop should have been changed."); } -function testEditProperty() -{ - let idRuleEditor = ruleView.element.children[1]._ruleEditor; - let propEditor = idRuleEditor.rule.textProps[0].editor; - waitForEditorFocus(propEditor.element, function onNewElement(aEditor) { - is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor."); - - let input = aEditor.input; - - dump("SELECTION END IS: " + input.selectionEnd + "\n"); - ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected."); - - // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665). - EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow); - input.select(); - - waitForEditorFocus(propEditor.element, function onNewName(aEditor) { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value."); - - input = aEditor.input; - - ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected."); - - // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665). - EventUtils.synthesizeMouse(input, 1, 1, { }, ruleWindow); - input.select(); - - waitForEditorBlur(aEditor, function() { - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "red", - "border-color should have been set."); - - let props = ruleView.element.querySelectorAll(".ruleview-property"); - for (let i = 0; i < props.length; i++) { - is(props[i].hasAttribute("dirty"), i <= 1, - "props[" + i + "] marked dirty as appropriate"); - } - testDisableProperty(); - })); - }); - - for (let ch of "red;") { - EventUtils.sendChar(ch, ruleWindow); - is(propEditor.warning.hidden, true, - "warning triangle is hidden or shown as appropriate"); - } - })); - }); - for (let ch of "border-color:") { - EventUtils.sendChar(ch, ruleWindow); - } - }); - - EventUtils.synthesizeMouse(propEditor.nameSpan, 32, 1, - { }, - ruleWindow); -} - -function testDisableProperty() -{ +function* testEditProperty(inspector, ruleView) { let idRuleEditor = ruleView.element.children[1]._ruleEditor; let propEditor = idRuleEditor.rule.textProps[0].editor; + let editor = yield focusEditableField(propEditor.nameSpan); + let input = editor.input; + is(inplaceEditor(propEditor.nameSpan), editor, "Next focused editor should be the name editor."); + + ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected."); + + // Try clicking on the editor's input again, shouldn't cause trouble (see bug 761665). + EventUtils.synthesizeMouse(input, 1, 1, {}, ruleView.doc.defaultView); + input.select(); + + info("Entering property name followed by a colon to focus the value"); + let onFocus = once(idRuleEditor.element, "focus", true); + for (let ch of "border-color:") { + EventUtils.sendChar(ch, ruleView.doc.defaultView); + } + yield onFocus; + yield idRuleEditor.rule._applyingModifications; + + info("Verifying that the focused field is the valueSpan"); + editor = inplaceEditor(ruleView.doc.activeElement); + input = editor.input; + is(inplaceEditor(propEditor.valueSpan), editor, "Focus should have moved to the value."); + ok(input.selectionStart === 0 && input.selectionEnd === input.value.length, "Editor contents are selected."); + + info("Entering a value following by a semi-colon to commit it"); + let onBlur = once(editor.input, "blur"); + for (let ch of "red;") { + EventUtils.sendChar(ch, ruleView.doc.defaultView); + is(propEditor.warning.hidden, true, + "warning triangle is hidden or shown as appropriate"); + } + yield onBlur; + yield idRuleEditor.rule._applyingModifications; + + is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "red", + "border-color should have been set."); + + let props = ruleView.element.querySelectorAll(".ruleview-property"); + for (let i = 0; i < props.length; i++) { + is(props[i].hasAttribute("dirty"), i <= 1, + "props[" + i + "] marked dirty as appropriate"); + } +} + +function* testDisableProperty(inspector, ruleView) { + let idRuleEditor = ruleView.element.children[1]._ruleEditor; + let propEditor = idRuleEditor.rule.textProps[0].editor; + + info("Disabling a property"); propEditor.enable.click(); - promiseDone(expectRuleChange(idRuleEditor.rule).then(() => { - is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "", "Border-color should have been unset."); + yield idRuleEditor.rule._applyingModifications; + is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "", + "Border-color should have been unset."); - propEditor.enable.click(); - return expectRuleChange(idRuleEditor.rule); - }).then(() => { - is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "red", - "Border-color should have been reset."); - - testPropertyStillMarkedDirty(); - })); + info("Enabling the property again"); + propEditor.enable.click(); + yield idRuleEditor.rule._applyingModifications; + is(idRuleEditor.rule.style._rawStyle().getPropertyValue("border-color"), "red", + "Border-color should have been reset."); } -function testPropertyStillMarkedDirty() { +function* testPropertyStillMarkedDirty(inspector, ruleView) { // Select an unstyled node. - let testElement = doc.getElementById("testid2"); - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => { - // Select the original node again. - testElement = doc.getElementById("testid"); - inspector.selection.setNode(testElement); - inspector.once("inspector-updated", () => { - let props = ruleView.element.querySelectorAll(".ruleview-property"); - for (let i = 0; i < props.length; i++) { - is(props[i].hasAttribute("dirty"), i <= 1, - "props[" + i + "] marked dirty as appropriate"); - } - finishTest(); - }); - }); -} + yield selectNode("#testid2", inspector); -function finishTest() -{ - inspector = ruleWindow = ruleView = null; - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} + // Select the original node again. + yield selectNode("#testid", inspector); -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(startTest), content); - }, true); - - content.location = "data:text/html;charset=utf-8,browser_ruleview_ui.js"; + let props = ruleView.element.querySelectorAll(".ruleview-property"); + for (let i = 0; i < props.length; i++) { + is(props[i].hasAttribute("dirty"), i <= 1, + "props[" + i + "] marked dirty as appropriate"); + } } diff --git a/browser/devtools/styleinspector/test/browser_ruleview_update.js b/browser/devtools/styleinspector/test/browser_ruleview_update.js index 59d5fc460e38..ab32da97f3ec 100644 --- a/browser/devtools/styleinspector/test/browser_ruleview_update.js +++ b/browser/devtools/styleinspector/test/browser_ruleview_update.js @@ -1,18 +1,17 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ -let doc; +"use strict"; -let inspector; -let ruleView; -let testElement; -let rule; +// Test that changing the current element's attributes and style refreshes the +// rule-view -function startTest(aInspector, aRuleView) -{ - inspector = aInspector; - ruleView = aRuleView; +let test = asyncTest(function*() { + yield addTab("data:text/html;charset=utf-8,browser_ruleview_update.js"); + let {toolbox, inspector, view} = yield openRuleView(); + + info("Creating the test document"); let style = '' + '#testid {' + ' background-color: blue;' + @@ -20,21 +19,36 @@ function startTest(aInspector, aRuleView) '.testclass {' + ' background-color: green;' + '}'; + let styleNode = addStyle(content.document, style); + content.document.body.innerHTML = '
Styled Node
'; - let styleNode = addStyle(doc, style); - doc.body.innerHTML = '
Styled Node
'; - - testElement = doc.getElementById("testid"); + info("Getting the test node"); + let testElement = getNode("#testid"); + info("Adding inline style"); let elementStyle = 'margin-top: 1px; padding-top: 5px;' testElement.setAttribute("style", elementStyle); - inspector.selection.setNode(testElement); - inspector.once("rule-view-refreshed", testRuleChanges); -} + info("Selecting the test node") + yield selectNode(testElement, inspector); -function testRuleChanges() -{ + info("Test that changing the element's attributes refreshes the rule-view"); + yield testRuleChanges(inspector, view, testElement); + yield testRuleChange1(inspector, view, testElement); + yield testRuleChange2(inspector, view, testElement); + + yield testPropertyChanges(inspector, view, testElement); + 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 testPropertyChange7(inspector, view, testElement); +}); + +function* testRuleChanges(inspector, ruleView, testElement) { let selectors = ruleView.doc.querySelectorAll(".ruleview-selector"); is(selectors.length, 3, "Three rules visible."); is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style."); @@ -42,33 +56,129 @@ function testRuleChanges() is(selectors[2].textContent.indexOf(".testclass"), 0, "Third item is class rule."); // Change the id and refresh. - inspector.once("rule-view-refreshed", testRuleChange1); + let ruleViewRefreshed = inspector.once("rule-view-refreshed"); testElement.setAttribute("id", "differentid"); + yield ruleViewRefreshed; } -function testRuleChange1() -{ +function* testRuleChange1(inspector, ruleView, testElement) { let selectors = ruleView.doc.querySelectorAll(".ruleview-selector"); is(selectors.length, 2, "Two rules visible."); is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style."); is(selectors[1].textContent.indexOf(".testclass"), 0, "Second item is class rule."); - inspector.once("rule-view-refreshed", testRuleChange2); + let ruleViewRefreshed = inspector.once("rule-view-refreshed"); testElement.setAttribute("id", "testid"); + yield ruleViewRefreshed; } -function testRuleChange2() -{ + +function* testRuleChange2(inspector, ruleView, testElement) { let selectors = ruleView.doc.querySelectorAll(".ruleview-selector"); is(selectors.length, 3, "Three rules visible."); is(selectors[0].textContent.indexOf("element"), 0, "First item is inline style."); is(selectors[1].textContent.indexOf("#testid"), 0, "Second item is id rule."); is(selectors[2].textContent.indexOf(".testclass"), 0, "Third item is class rule."); - - testPropertyChanges(); } -function validateTextProp(aProp, aEnabled, aName, aValue, aDesc, valueSpanText) -{ +function* testPropertyChanges(inspector, ruleView, testElement) { + let rule = ruleView._elementStyle.rules[0]; + let ruleEditor = ruleView._elementStyle.rules[0].editor; + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Add a second margin-top value, just to make things interesting. + ruleEditor.addProperty("margin-top", "5px", ""); + yield onRefreshed; +} + +function* testPropertyChange0(inspector, ruleView, testElement) { + let rule = ruleView._elementStyle.rules[0]; + validateTextProp(rule.textProps[0], false, "margin-top", "1px", "Original margin property active"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + testElement.setAttribute("style", "margin-top: 1px; padding-top: 5px"); + yield onRefreshed; +} + +function* testPropertyChange1(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Now set it back to 5px, the 5px value should be re-enabled. + testElement.setAttribute("style", "margin-top: 5px; padding-top: 5px;"); + yield onRefreshed; +} + +function* testPropertyChange2(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Set the margin property to a value that doesn't exist in the editor. + // Should reuse the currently-enabled element (the second one.) + testElement.setAttribute("style", "margin-top: 15px; padding-top: 5px;"); + yield onRefreshed; +} + +function* testPropertyChange3(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Remove the padding-top attribute. Should disable the padding property but not remove it. + testElement.setAttribute("style", "margin-top: 5px;"); + yield onRefreshed; +} + +function* testPropertyChange4(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Put the padding-top attribute back in, should re-enable the padding property. + testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px"); + yield onRefreshed; +} + +function* testPropertyChange5(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Add an entirely new property + testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px; padding-left: 20px;"); + yield onRefreshed; +} + +function* testPropertyChange6(inspector, ruleView, testElement) { + 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"); + + let onRefreshed = inspector.once("rule-view-refreshed"); + // Add an entirely new property + testElement.setAttribute("style", "background: url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red"); + yield onRefreshed; +} + +function* testPropertyChange7(inspector, ruleView, testElement) { + let rule = ruleView._elementStyle.rules[0]; + is(rule.editor.element.querySelectorAll(".ruleview-property").length, 5, "Added a property"); + validateTextProp(rule.textProps[4], true, "background", + "url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red", + "shortcut property correctly set", + "url('chrome://branding/content/about-logo.png') repeat scroll 0% 0% #F00"); +} + +function validateTextProp(aProp, aEnabled, aName, aValue, aDesc, valueSpanText) { is(aProp.enabled, aEnabled, aDesc + ": enabled."); is(aProp.name, aName, aDesc + ": name."); is(aProp.value, aValue, aDesc + ": value."); @@ -77,117 +187,3 @@ function validateTextProp(aProp, aEnabled, aName, aValue, aDesc, valueSpanText) is(aProp.editor.nameSpan.textContent, aName, aDesc + ": name span."); is(aProp.editor.valueSpan.textContent, valueSpanText || aValue, aDesc + ": value span."); } - -function testPropertyChanges() -{ - rule = ruleView._elementStyle.rules[0]; - let ruleEditor = ruleView._elementStyle.rules[0].editor; - inspector.once("rule-view-refreshed", testPropertyChange0); - - // Add a second margin-top value, just to make things interesting. - ruleEditor.addProperty("margin-top", "5px", ""); -} - -function testPropertyChange0() -{ - validateTextProp(rule.textProps[0], false, "margin-top", "1px", "Original margin property active"); - - inspector.once("rule-view-refreshed", testPropertyChange1); - testElement.setAttribute("style", "margin-top: 1px; padding-top: 5px"); -} -function testPropertyChange1() -{ - 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"); - - inspector.once("rule-view-refreshed", testPropertyChange2); - - // Now set it back to 5px, the 5px value should be re-enabled. - testElement.setAttribute("style", "margin-top: 5px; padding-top: 5px;"); -} -function testPropertyChange2() -{ - 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"); - - inspector.once("rule-view-refreshed", testPropertyChange3); - - // Set the margin property to a value that doesn't exist in the editor. - // Should reuse the currently-enabled element (the second one.) - testElement.setAttribute("style", "margin-top: 15px; padding-top: 5px;"); -} -function testPropertyChange3() -{ - 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"); - - inspector.once("rule-view-refreshed", testPropertyChange4); - - // Remove the padding-top attribute. Should disable the padding property but not remove it. - testElement.setAttribute("style", "margin-top: 5px;"); -} -function testPropertyChange4() -{ - is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties"); - validateTextProp(rule.textProps[1], false, "padding-top", "5px", "Padding property disabled"); - - inspector.once("rule-view-refreshed", testPropertyChange5); - - // Put the padding-top attribute back in, should re-enable the padding property. - testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px"); -} -function testPropertyChange5() -{ - is(rule.editor.element.querySelectorAll(".ruleview-property").length, 3, "Correct number of properties"); - validateTextProp(rule.textProps[1], true, "padding-top", "25px", "Padding property enabled"); - - inspector.once("rule-view-refreshed", testPropertyChange6); - - // Add an entirely new property - testElement.setAttribute("style", "margin-top: 5px; padding-top: 25px; padding-left: 20px;"); -} -function testPropertyChange6() -{ - is(rule.editor.element.querySelectorAll(".ruleview-property").length, 4, "Added a property"); - validateTextProp(rule.textProps[3], true, "padding-left", "20px", "Padding property enabled"); - - inspector.once("rule-view-refreshed", testPropertyChange7); - - // Add an entirely new property - testElement.setAttribute("style", "background: url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red"); -} - -function testPropertyChange7() -{ - is(rule.editor.element.querySelectorAll(".ruleview-property").length, 5, "Added a property"); - validateTextProp(rule.textProps[4], true, "background", - "url(\"chrome://branding/content/about-logo.png\") repeat scroll 0% 0% red", - "shortcut property correctly set", - "url('chrome://branding/content/about-logo.png') repeat scroll 0% 0% #F00"); - - finishTest(); -} - -function finishTest() -{ - inspector = ruleView = rule = null; - doc = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true); - doc = content.document; - waitForFocus(() => openRuleView(startTest), content); - }, true); - - content.location = "data:text/html;charset=utf-8,browser_ruleview_update.js"; -} diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js b/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js index b74b2c47203c..998a2e16c28e 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_bug_672744_search_filter.js @@ -1,101 +1,65 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Tests that the search filter works properly. -let doc; -let inspector; -let computedView; +let test = asyncTest(function*() { + yield addTab("data:text/html,default styles test"); -function createDocument() -{ - doc.body.innerHTML = '' + 'Some styled text' + ''; - doc.title = "Style Inspector Search Filter Test"; + content.document.title = "Style Inspector Search Filter Test"; - openComputedView(runStyleInspectorTests); -} + info("Opening the computed-view"); + let {toolbox, inspector, view} = yield openComputedView(); -function runStyleInspectorTests(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; + info("Selecting the test node"); + yield selectNode("#matches", inspector); - SI_inspectNode(); -} + yield testToggleDefaultStyles(inspector, view); + yield testAddTextInFilter(inspector, view); +}); -function SI_inspectNode() -{ - var span = doc.querySelector("#matches"); - ok(span, "captain, we have the matches span"); - inspector.selection.setNode(span); - inspector.once("inspector-updated", () => { - is(span, computedView.viewedElement.rawNode(), - "style inspector node matches the selected node"); - SI_toggleDefaultStyles(); - }); -} - -function SI_toggleDefaultStyles() -{ +function* testToggleDefaultStyles(inspector, computedView) { info("checking \"Browser styles\" checkbox"); let doc = computedView.styleDocument; let checkbox = doc.querySelector(".includebrowserstyles"); - inspector.once("computed-view-refreshed", SI_AddFilterText); + let onRefreshed = inspector.once("computed-view-refreshed"); checkbox.click(); + yield onRefreshed; } -function SI_AddFilterText() -{ +function* testAddTextInFilter(inspector, computedView) { + info("setting filter text to \"color\""); + let doc = computedView.styleDocument; let searchbar = doc.querySelector(".devtools-searchinput"); - inspector.once("computed-view-refreshed", SI_checkFilter); - info("setting filter text to \"color\""); + let onRefreshed = inspector.once("computed-view-refreshed"); searchbar.focus(); - let win =computedView.styleWindow; + let win = computedView.styleWindow; EventUtils.synthesizeKey("c", {}, win); EventUtils.synthesizeKey("o", {}, win); EventUtils.synthesizeKey("l", {}, win); EventUtils.synthesizeKey("o", {}, win); EventUtils.synthesizeKey("r", {}, win); -} -function SI_checkFilter() -{ - let propertyViews = computedView.propertyViews; + yield onRefreshed; info("check that the correct properties are visible"); + + let propertyViews = computedView.propertyViews; propertyViews.forEach(function(propView) { let name = propView.name; is(propView.visible, name.indexOf("color") > -1, "span " + name + " property visibility check"); }); - - finishUp(); -} - -function finishUp() -{ - doc = inspector = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,default styles test"; } diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_bug_672746_default_styles.js b/browser/devtools/styleinspector/test/browser_styleinspector_bug_672746_default_styles.js index 869ca9303979..6f80b7cbf73e 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_bug_672746_default_styles.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_bug_672746_default_styles.js @@ -1,99 +1,54 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Tests that the checkbox to include browser styles works properly. -let doc; -let inspector; -let computedView; +let test = asyncTest(function*() { + yield addTab("data:text/html,default styles test"); -function createDocument() -{ - doc.body.innerHTML = '' + 'Some styled text' + ''; - doc.title = "Style Inspector Default Styles Test"; + content.document.title = "Style Inspector Default Styles Test"; - openComputedView(SI_inspectNode); -} + info("Opening the computed view"); + let {toolbox, inspector, view} = yield openComputedView(); -function SI_inspectNode(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; + info("Selecting the test node"); + yield selectNode("#matches", inspector); - let span = doc.querySelector("#matches"); - ok(span, "captain, we have the matches span"); - - inspector.selection.setNode(span); - inspector.once("inspector-updated", () => { - is(span, computedView.viewedElement.rawNode(), - "style inspector node matches the selected node"); - SI_check(); - }); -} - -function SI_check() -{ - is(propertyVisible("color"), true, + info("Checking the default styles"); + is(isPropertyVisible("color", view), true, "span #matches color property is visible"); - is(propertyVisible("background-color"), false, + is(isPropertyVisible("background-color", view), false, "span #matches background-color property is hidden"); - SI_toggleDefaultStyles(); -} - -function SI_toggleDefaultStyles() -{ - // Click on the checkbox. - let doc = computedView.styleDocument; + info("Toggling the browser styles"); + let doc = view.styleDocument; let checkbox = doc.querySelector(".includebrowserstyles"); - inspector.once("computed-view-refreshed", SI_checkDefaultStyles); - + let onRefreshed = inspector.once("computed-view-refreshed"); checkbox.click(); -} + yield onRefreshed; -function SI_checkDefaultStyles() -{ - // Check that the default styles are now applied. - is(propertyVisible("color"), true, - "span color property is visible"); - is(propertyVisible("background-color"), true, - "span background-color property is visible"); + info("Checking the browser styles"); + is(isPropertyVisible("color", view), true, + "span color property is visible"); + is(isPropertyVisible("background-color", view), true, + "span background-color property is visible"); +}); - finishUp(); -} - -function propertyVisible(aName) -{ - info("Checking property visibility for " + aName); - let propertyViews = computedView.propertyViews; +function isPropertyVisible(name, view) { + info("Checking property visibility for " + name); + let propertyViews = view.propertyViews; for each (let propView in propertyViews) { - if (propView.name == aName) { + if (propView.name == name) { return propView.visible; } } return false; } - -function finishUp() -{ - doc = inspector = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,default styles test"; -} diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_bug_677930_urls_clickable.js b/browser/devtools/styleinspector/test/browser_styleinspector_bug_677930_urls_clickable.js index 99054740a46b..87555790baf9 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_bug_677930_urls_clickable.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_bug_677930_urls_clickable.js @@ -1,113 +1,62 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Tests to make sure that URLs are clickable in the rule view -let doc; -let computedView; -let inspector; - -const BASE_URL = "http://example.com/browser/browser/" + - "devtools/styleinspector/test/"; -const TEST_URI = BASE_URL + +const TEST_URI = TEST_URL_ROOT + "browser_styleinspector_bug_677930_urls_clickable.html"; -const TEST_IMAGE = BASE_URL + "test-image.png"; +const TEST_IMAGE = TEST_URL_ROOT + "test-image.png"; const BASE_64_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="; -function setNode(node, inspector) -{ - let updated = inspector.once("inspector-updated"); - inspector.selection.setNode(node); - return updated; -} - -function selectNodes(aInspector, aRuleView) -{ - inspector = aInspector; - let sidebar = inspector.sidebar; - let contentDoc = aRuleView.doc; - - let relative1 = doc.querySelector(".relative1"); - let relative2 = doc.querySelector(".relative2"); - let absolute = doc.querySelector(".absolute"); - let inline = doc.querySelector(".inline"); - let base64 = doc.querySelector(".base64"); - let noimage = doc.querySelector(".noimage"); - let inlineresolved = doc.querySelector(".inline-resolved"); - - ok(relative1, "captain, we have the relative1 div"); - ok(relative2, "captain, we have the relative2 div"); - ok(absolute, "captain, we have the absolute div"); - ok(inline, "captain, we have the inline div"); - ok(base64, "captain, we have the base64 div"); - ok(noimage, "captain, we have the noimage div"); - ok(inlineresolved, "captain, we have the inlineresolved div"); - - - Task.spawn(function*() { - - yield setNode(relative1, inspector); - is(inspector.selection.node, relative1, "selection matches the relative1 element"); - let relativeLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (relativeLink, "Link exists for relative1 node"); - is (relativeLink.getAttribute("href"), TEST_IMAGE, "href matches"); - - yield setNode(relative2, inspector); - is(inspector.selection.node, relative2, "selection matches the relative2 element"); - let relativeLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (relativeLink, "Link exists for relative2 node"); - is (relativeLink.getAttribute("href"), TEST_IMAGE, "href matches"); - - yield setNode(absolute, inspector); - is(inspector.selection.node, absolute, "selection matches the absolute element"); - let absoluteLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (absoluteLink, "Link exists for absolute node"); - is (absoluteLink.getAttribute("href"), TEST_IMAGE, "href matches"); - - yield setNode(inline, inspector); - is(inspector.selection.node, inline, "selection matches the inline element"); - let inlineLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (inlineLink, "Link exists for inline node"); - is (inlineLink.getAttribute("href"), TEST_IMAGE, "href matches"); - - yield setNode(base64, inspector); - is(inspector.selection.node, base64, "selection matches the base64 element"); - let base64Link = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (base64Link, "Link exists for base64 node"); - is (base64Link.getAttribute("href"), BASE_64_URL, "href matches"); - - yield setNode(inlineresolved, inspector); - is(inspector.selection.node, inlineresolved, "selection matches the style tag element"); - let inlineResolvedLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (inlineResolvedLink, "Link exists for style tag node"); - is (inlineResolvedLink.getAttribute("href"), TEST_IMAGE, "href matches"); - - yield setNode(noimage, inspector); - is(inspector.selection.node, noimage, "selection matches the inline element"); - let noimageLink = contentDoc.querySelector(".ruleview-propertycontainer a"); - ok (!noimageLink, "There is no link for the node with no background image"); - - finishUp(); - }); -} - -function finishUp() -{ - doc = computedView = inspector = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(() => openRuleView(selectNodes), content); - }, true); - - content.location = TEST_URI; +let test = asyncTest(function*() { + yield addTab(TEST_URI); + let {toolbox, inspector, view} = yield openRuleView(); + yield selectNodes(inspector, view); +}); + +function* selectNodes(inspector, ruleView) { + let relative1 = ".relative1"; + let relative2 = ".relative2"; + let absolute = ".absolute"; + let inline = ".inline"; + let base64 = ".base64"; + let noimage = ".noimage"; + let inlineresolved = ".inline-resolved"; + + yield selectNode(relative1, inspector); + let relativeLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(relativeLink, "Link exists for relative1 node"); + is(relativeLink.getAttribute("href"), TEST_IMAGE, "href matches"); + + yield selectNode(relative2, inspector); + let relativeLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(relativeLink, "Link exists for relative2 node"); + is(relativeLink.getAttribute("href"), TEST_IMAGE, "href matches"); + + yield selectNode(absolute, inspector); + let absoluteLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(absoluteLink, "Link exists for absolute node"); + is(absoluteLink.getAttribute("href"), TEST_IMAGE, "href matches"); + + yield selectNode(inline, inspector); + let inlineLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(inlineLink, "Link exists for inline node"); + is(inlineLink.getAttribute("href"), TEST_IMAGE, "href matches"); + + yield selectNode(base64, inspector); + let base64Link = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(base64Link, "Link exists for base64 node"); + is(base64Link.getAttribute("href"), BASE_64_URL, "href matches"); + + yield selectNode(inlineresolved, inspector); + let inlineResolvedLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(inlineResolvedLink, "Link exists for style tag node"); + is(inlineResolvedLink.getAttribute("href"), TEST_IMAGE, "href matches"); + + yield selectNode(noimage, inspector); + let noimageLink = ruleView.doc.querySelector(".ruleview-propertycontainer a"); + ok(!noimageLink, "There is no link for the node with no background image"); } diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_bug_689759_no_results_placeholder.js b/browser/devtools/styleinspector/test/browser_styleinspector_bug_689759_no_results_placeholder.js index 83f6e2d62052..421bbde0ce1f 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_bug_689759_no_results_placeholder.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_bug_689759_no_results_placeholder.js @@ -1,104 +1,73 @@ /* 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/ */ + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; // Tests that the no results placeholder works properly. -let doc; -let inspector; -let computedView; +let test = asyncTest(function*() { + yield addTab("data:text/html,no results placeholder test"); -function createDocument() -{ - doc.body.innerHTML = '' + 'Some styled text'; - doc.title = "Tests that the no results placeholder works properly"; + content.document.title = "Tests that the no results placeholder works properly"; - openComputedView(runStyleInspectorTests); -} + info("Opening the computed view"); + let {toolbox, inspector, view} = yield openComputedView(); -function runStyleInspectorTests(aInspector, aComputedView) -{ - inspector = aInspector; - computedView = aComputedView; + info("Selecting the test node"); + yield selectNode("#matches", inspector); - let span = doc.querySelector("#matches"); - ok(span, "captain, we have the matches span"); + yield enterInvalidFilter(inspector, view); + checkNoResultsPlaceholderShown(view); - inspector.selection.setNode(span); - inspector.once("inspector-updated", () => { - is(span, computedView.viewedElement.rawNode(), - "style inspector node matches the selected node"); - SI_AddFilterText(); - }); + yield clearFilterText(inspector, view); + checkNoResultsPlaceholderHidden(view); +}); -} - -function SI_AddFilterText() -{ +function* enterInvalidFilter(inspector, computedView) { let searchbar = computedView.searchField; let searchTerm = "xxxxx"; - inspector.once("computed-view-refreshed", SI_checkPlaceholderVisible); - info("setting filter text to \"" + searchTerm + "\""); + + let onRefreshed = inspector.once("computed-view-refreshed"); searchbar.focus(); for each (let c in searchTerm) { EventUtils.synthesizeKey(c, {}, computedView.styleWindow); } + yield onRefreshed; } -function SI_checkPlaceholderVisible() -{ - info("SI_checkPlaceholderVisible called"); +function checkNoResultsPlaceholderShown(computedView) { + info("Checking that the no results placeholder is shown"); + let placeholder = computedView.noResults; let win = computedView.styleWindow; let display = win.getComputedStyle(placeholder).display; - is(display, "block", "placeholder is visible"); - - SI_ClearFilterText(); } -function SI_ClearFilterText() -{ +function* clearFilterText(inspector, computedView) { + info("Clearing the filter text"); + let searchbar = computedView.searchField; - inspector.once("computed-view-refreshed", SI_checkPlaceholderHidden); - info("clearing filter text"); + let onRefreshed = inspector.once("computed-view-refreshed"); searchbar.focus(); searchbar.value = ""; EventUtils.synthesizeKey("c", {}, computedView.styleWindow); + yield onRefreshed; } -function SI_checkPlaceholderHidden() -{ +function checkNoResultsPlaceholderHidden(computedView) { + info("Checking that the no results placeholder is hidden"); + let placeholder = computedView.noResults; let win = computedView.styleWindow; let display = win.getComputedStyle(placeholder).display; - is(display, "none", "placeholder is hidden"); - - finishUp(); -} - -function finishUp() -{ - doc = inspector = computedView = null; - gBrowser.removeCurrentTab(); - finish(); -} - -function test() -{ - waitForExplicitFinish(); - gBrowser.selectedTab = gBrowser.addTab(); - gBrowser.selectedBrowser.addEventListener("load", function onLoad(evt) { - gBrowser.selectedBrowser.removeEventListener(evt.type, onLoad, true); - doc = content.document; - waitForFocus(createDocument, content); - }, true); - - content.location = "data:text/html,no results placeholder test"; } diff --git a/browser/devtools/styleinspector/test/browser_styleinspector_outputparser.js b/browser/devtools/styleinspector/test/browser_styleinspector_outputparser.js index 7c5f6f7fe8c1..abaab6c99507 100644 --- a/browser/devtools/styleinspector/test/browser_styleinspector_outputparser.js +++ b/browser/devtools/styleinspector/test/browser_styleinspector_outputparser.js @@ -1,7 +1,9 @@ -/* vim: set ts=2 et sw=2 tw=80: */ +/* 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 expected outputs of the output-parser's parseCssProperty function. // This is more of a unit test than a mochitest-browser test, but can't be @@ -14,8 +16,6 @@ const COLOR_CLASS = "color-class"; const URL_CLASS = "url-class"; function test() { - waitForExplicitFinish(); - function countAll(fragment) { return fragment.querySelectorAll("*").length; } diff --git a/browser/devtools/styleinspector/test/head.js b/browser/devtools/styleinspector/test/head.js index 0f786f7a53b9..5d19321e0a7d 100644 --- a/browser/devtools/styleinspector/test/head.js +++ b/browser/devtools/styleinspector/test/head.js @@ -1,95 +1,110 @@ -/* vim:set ts=2 sw=2 sts=2 et: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* 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/ */ -const TEST_BASE_HTTP = "http://example.com/browser/browser/devtools/styleinspector/test/"; -const TEST_BASE_HTTPS = "https://example.com/browser/browser/devtools/styleinspector/test/"; - -// Services.prefs.setBoolPref("devtools.dump.emit", true); -// Services.prefs.setBoolPref("devtools.debugger.log", true); - -let tempScope = {}; - -Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope); -let ConsoleUtils = tempScope.ConsoleUtils; -let gDevTools = tempScope.gDevTools; - -Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope); -let devtools = tempScope.devtools; +"use strict"; +const Cu = Components.utils; +let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); +let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); let TargetFactory = devtools.TargetFactory; let {CssHtmlTree} = devtools.require("devtools/styleinspector/computed-view"); let {CssRuleView, _ElementStyle} = devtools.require("devtools/styleinspector/rule-view"); let {CssLogic, CssSelector} = devtools.require("devtools/styleinspector/css-logic"); - let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {}); +let {editableField, getInplaceEditorForSpan: inplaceEditor} = devtools.require("devtools/shared/inplace-editor"); +let {console} = Components.utils.import("resource://gre/modules/devtools/Console.jsm", {}); -gDevTools.testing = true; -SimpleTest.registerCleanupFunction(() => { - gDevTools.testing = false; +// All test are asynchronous +waitForExplicitFinish(); + +const TEST_URL_ROOT = "http://example.com/browser/browser/devtools/styleinspector/test/"; +const TEST_URL_ROOT_SSL = "https://example.com/browser/browser/devtools/styleinspector/test/"; + +// Auto clean-up when a test ends +registerCleanupFunction(() => { + try { + let target = TargetFactory.forTab(gBrowser.selectedTab); + gDevTools.closeToolbox(target); + } catch (ex) { + dump(ex); + } + while (gBrowser.tabs.length > 1) { + gBrowser.removeCurrentTab(); + } }); -SimpleTest.registerCleanupFunction(() => { - // Services.prefs.clearUserPref("devtools.debugger.log"); +// Services.prefs.setBoolPref("devtools.dump.emit", true); +registerCleanupFunction(() => { Services.prefs.clearUserPref("devtools.dump.emit"); }); -let { - editableField, - getInplaceEditorForSpan: inplaceEditor -} = devtools.require("devtools/shared/inplace-editor"); -Components.utils.import("resource://gre/modules/devtools/Console.jsm", tempScope); -let console = tempScope.console; +/** + * The functions found below are here to ease test development and maintenance. + * Most of these functions are stateless and will require some form of context + * (the instance of the current toolbox, or inspector panel for instance). + * + * Most of these functions are async too and return promises. + * + * All tests should follow the following pattern: + * + * let test = asyncTest(function*() { + * yield addTab(TEST_URI); + * let {toolbox, inspector, view} = yield openComputedView(); + * + * yield selectNode("#test", inspector); + * yield someAsyncTestFunction(view); + * }); + * + * asyncTest is the way to define the testcase in the test file. It accepts + * a single generator-function argument. + * The generator function should yield any async call. + * + * There is no need to clean tabs up at the end of a test as this is done + * automatically. + * + * It is advised not to store any references on the global scope. There shouldn't + * be a need to anyway. Thanks to asyncTest, test steps, even though asynchronous, + * can be described in a nice flat way, and if/for/while/... control flow can be + * used as in sync code, making it possible to write the outline of the test case + * all in asyncTest, and delegate actual processing and assertions to other + * functions. + */ -let browser, hudId, hud, hudBox, filterBox, outputNode, cs; +/* ********************************************* + * UTILS + * ********************************************* + * General test utilities. + * Define the test case, add new tabs, open the toolbox and switch to the + * various panels, select nodes, get node references, ... + */ -function addTab(aURL) -{ - gBrowser.selectedTab = gBrowser.addTab(); - content.location = aURL; - browser = gBrowser.getBrowserForTab(gBrowser.selectedTab); +/** + * Define an async test based on a generator function + */ +function asyncTest(generator) { + return () => Task.spawn(generator).then(null, ok.bind(null, false)).then(finish); } -function openInspector(callback) -{ - let target = TargetFactory.forTab(gBrowser.selectedTab); - gDevTools.showToolbox(target, "inspector").then(function(toolbox) { - callback(toolbox.getCurrentPanel()); - }); -} +/** + * Add a new test tab in the browser and load the given url. + * @param {String} url The url to be loaded in the new tab + * @return a promise that resolves to the tab object when the url is loaded + */ +function addTab(url) { + let def = promise.defer(); -function getActiveInspector() -{ - let target = TargetFactory.forTab(gBrowser.selectedTab); - return gDevTools.getToolbox(target).getPanel("inspector"); -} + let tab = gBrowser.selectedTab = gBrowser.addTab(); + gBrowser.selectedBrowser.addEventListener("load", function onload() { + gBrowser.selectedBrowser.removeEventListener("load", onload, true); + info("URL " + url + " loading complete into new test tab"); + waitForFocus(() => { + def.resolve(tab); + }, content); + }, true); + content.location = url; -function openView(name, callback) -{ - openInspector(inspector => { - function onReady() { - inspector.sidebar.select(name); - let { view } = inspector.sidebar.getWindowForTab(name)[name]; - callback(inspector, view); - } - - if (inspector.sidebar.getWindowForTab(name)) { - onReady(); - } else { - inspector.sidebar.once(name + "-ready", onReady); - } - }); -} - -function openRuleView(callback) -{ - openView("ruleview", callback); -} - -function openComputedView(callback) -{ - openView("computedview", callback); + return def.promise; } /** @@ -98,29 +113,24 @@ function openComputedView(callback) * @param {String|DOMNode} nodeOrSelector * @return {DOMNode} */ -function getNode(nodeOrSelector) -{ - let node = nodeOrSelector; - - if (typeof nodeOrSelector === "string") { - node = content.document.querySelector(nodeOrSelector); - ok(node, "A node was found for selector " + nodeOrSelector); - } - - return node; +function getNode(nodeOrSelector) { + return typeof nodeOrSelector === "string" ? + content.document.querySelector(nodeOrSelector) : + nodeOrSelector; } /** * Set the inspector's current selection to a node or to the first match of the * given css selector - * @param {String|DOMNode} nodeOrSelector - * @param {InspectorPanel} inspector The instance of InspectorPanel currently loaded in the toolbox + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @param {String} reason Defaults to "test" which instructs the inspector not + * to highlight the node upon selection * @param {String} reason Defaults to "test" which instructs the inspector not to highlight the node upon selection * @return a promise that resolves when the inspector is updated with the new * node */ -function selectNode(nodeOrSelector, inspector, reason="test") -{ +function selectNode(nodeOrSelector, inspector, reason="test") { info("Selecting the node " + nodeOrSelector); let node = getNode(nodeOrSelector); let updated = inspector.once("inspector-updated"); @@ -128,227 +138,345 @@ function selectNode(nodeOrSelector, inspector, reason="test") return updated; } -function addStyle(aDocument, aString) -{ - let node = aDocument.createElement('style'); - node.setAttribute("type", "text/css"); - node.textContent = aString; - aDocument.getElementsByTagName("head")[0].appendChild(node); - return node; -} - -function finishTest() -{ - finish(); -} - -function tearDown() -{ - try { - let target = TargetFactory.forTab(gBrowser.selectedTab); - gDevTools.closeToolbox(target); - } - catch (ex) { - dump(ex); - } - while (gBrowser.tabs.length > 1) { - gBrowser.removeCurrentTab(); - } - browser = hudId = hud = filterBox = outputNode = cs = null; -} - -function getComputedView() { - let inspector = getActiveInspector(); - return inspector.sidebar.getWindowForTab("computedview").computedview.view; -} - -function ruleView() -{ - let inspector = getActiveInspector(); - return inspector.sidebar.getWindowForTab("ruleview").ruleview.view; -} - -function waitForEditorFocus(aParent, aCallback) -{ - aParent.addEventListener("focus", function onFocus(evt) { - if (inplaceEditor(evt.target) && evt.target.tagName == "input") { - aParent.removeEventListener("focus", onFocus, true); - let editor = inplaceEditor(evt.target); - executeSoon(function() { - aCallback(editor); - }); - } - }, true); -} - -function waitForEditorBlur(aEditor, aCallback) -{ - let input = aEditor.input; - input.addEventListener("blur", function onBlur() { - input.removeEventListener("blur", onBlur, false); - executeSoon(function() { - aCallback(); - }); - }, false); -} - -function fireCopyEvent(element) { - let evt = element.ownerDocument.createEvent("Event"); - evt.initEvent("copy", true, true); - element.dispatchEvent(evt); -} - -function contextMenuClick(element) { - var evt = element.ownerDocument.createEvent('MouseEvents'); - - var button = 2; // right click - - evt.initMouseEvent('contextmenu', true, true, - element.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, - false, false, false, button, null); - - element.dispatchEvent(evt); -} - -function expectRuleChange(rule) { - return rule._applyingModifications; -} - -function promiseDone(promise) { - promise.then(null, err => { - ok(false, "Promise failed: " + err); - if (err.stack) { - dump(err.stack); - } - SimpleTest.finish(); - }); -} - -function getComputedPropertyValue(aName) -{ - let computedview = getComputedView(); - let props = computedview.styleDocument.querySelectorAll(".property-view"); - - for (let prop of props) { - let name = prop.querySelector(".property-name"); - - if (name.textContent === aName) { - let value = prop.querySelector(".property-value"); - return value.textContent; - } - } +/** + * 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"); + let updated = inspector.once("inspector-updated"); + inspector.selection.setNode(null); + return updated; } /** - * Polls a given function waiting for it to become true. - * - * @param object aOptions - * Options object with the following properties: - * - validatorFn - * A validator function that returns a boolean. This is called every few - * milliseconds to check if the result is true. When it is true, succesFn - * is called and polling stops. If validatorFn never returns true, then - * polling timeouts after several tries and a failure is recorded. - * - successFn Optional - * A function called when the validator function returns true. - * - failureFn Optional - * A function called if the validator function timeouts - fails to return - * true in the given time. - * - name - * Name of test. This is used to generate the success and failure - * messages. - * - timeout - * Timeout for validator function, in milliseconds. Default is 5000. - * @return a promise that resolves when the condition is met, or rejects if the - * timeout is reached + * Open the toolbox, with the inspector tool visible. + * @return a promise that resolves when the inspector is ready */ -function waitForSuccess(aOptions) -{ - let def = promise.defer(); - let start = Date.now(); - let timeout = aOptions.timeout || 5000; +let openInspector = Task.async(function*() { + info("Opening the inspector"); + let target = TargetFactory.forTab(gBrowser.selectedTab); - function wait(validatorFn, successFn, failureFn) - { - if ((Date.now() - start) > timeout) { - // Log the failure. - ok(false, "Timed out while waiting for: " + aOptions.name); - if (failureFn) { - failureFn(aOptions); - } - def.reject(aOptions); - return; - } + let inspector, toolbox; - if (validatorFn(aOptions)) { - ok(true, aOptions.name); - if (successFn) { - successFn(); - } - def.resolve(); - } else { - setTimeout(function() wait(validatorFn, successFn, failureFn), 100); + // Checking if the toolbox and the inspector are already loaded + // The inspector-updated event should only be waited for if the inspector + // isn't loaded yet + toolbox = gDevTools.getToolbox(target); + if (toolbox) { + inspector = toolbox.getPanel("inspector"); + if (inspector) { + info("Toolbox and inspector already open"); + return { + toolbox: toolbox, + inspector: inspector + }; } } - wait(aOptions.validatorFn, aOptions.successFn, aOptions.failureFn); + info("Opening the toolbox"); + toolbox = yield gDevTools.showToolbox(target, "inspector"); + yield waitForToolboxFrameFocus(toolbox); + inspector = toolbox.getPanel("inspector"); + + info("Waiting for the inspector to update"); + yield inspector.once("inspector-updated"); + + return { + toolbox: toolbox, + inspector: inspector + }; +}); + +/** + * Wait for the toolbox frame to receive focus after it loads + * @param {Toolbox} toolbox + * @return a promise that resolves when focus has been received + */ +function waitForToolboxFrameFocus(toolbox) { + info("Making sure that the toolbox's frame is focused"); + let def = promise.defer(); + let win = toolbox.frame.contentWindow; + waitForFocus(def.resolve, win); return def.promise; } -registerCleanupFunction(tearDown); +/** + * Open the toolbox, with the inspector tool visible, and the sidebar that + * corresponds to the given id selected + * @return a promise that resolves when the inspector is ready and the sidebar + * view is visible and ready + */ +let openInspectorSideBar = Task.async(function*(id) { + let {toolbox, inspector} = yield openInspector(); -waitForExplicitFinish(); + if (!hasSideBarTab(inspector, id)) { + info("Waiting for the " + id + " sidebar to be ready"); + yield inspector.sidebar.once(id + "-ready"); + } + + info("Selecting the " + id + " sidebar"); + inspector.sidebar.select(id); + + return { + toolbox: toolbox, + inspector: inspector, + view: inspector.sidebar.getWindowForTab(id)[id].view + }; +}); /** - * @return a promise that resolves when the tooltip is shown + * Open the toolbox, with the inspector tool visible, and the computed-view + * sidebar tab selected. + * @return a promise that resolves when the inspector is ready and the computed + * view is visible and ready */ -function assertTooltipShownOn(tooltip, element) { - return Task.spawn(function*() { - let isTarget = yield isHoverTooltipTarget(tooltip, element); - ok(isTarget, "The element is a tooltip target"); - }); +function openComputedView() { + return openInspectorSideBar("computedview"); } +/** + * 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 openInspectorSideBar("ruleview"); +} + +/** + * Wait for eventName on target. + * @param {Object} target An observable object that either supports on/off or + * addEventListener/removeEventListener + * @param {String} eventName + * @param {Boolean} useCapture Optional, for addEventListener/removeEventListener + * @return A promise that resolves when the event has been handled + */ +function once(target, eventName, useCapture=false) { + info("Waiting for event: '" + eventName + "' on " + target + "."); + + let deferred = promise.defer(); + + for (let [add, remove] of [ + ["addEventListener", "removeEventListener"], + ["addListener", "removeListener"], + ["on", "off"] + ]) { + if ((add in target) && (remove in target)) { + target[add](eventName, function onEvent(...aArgs) { + target[remove](eventName, onEvent, useCapture); + deferred.resolve.apply(deferred, aArgs); + }, useCapture); + break; + } + } + + return deferred.promise; +} + +/** + * This shouldn't be used in the tests, but is useful when writing new tests or + * debugging existing tests in order to introduce delays in the test steps + * @param {Number} ms The time to wait + * @return A promise that resolves when the time is passed + */ +function wait(ms) { + let def = promise.defer(); + content.setTimeout(def.resolve, ms); + return def.promise; +} + +/** + * Given an inplace editable element, click to switch it to edit mode, wait for + * focus + * @return a promise that resolves to the inplace-editor element when ready + */ +let focusEditableField = Task.async(function*(editable, xOffset=1, yOffset=1, options={}) { + let onFocus = once(editable.parentNode, "focus", true); + + info("Clicking on editable field to turn to edit mode"); + EventUtils.synthesizeMouse(editable, xOffset, yOffset, options, + editable.ownerDocument.defaultView); + let event = yield onFocus; + + info("Editable field gained focus, returning the input field now"); + return inplaceEditor(editable.ownerDocument.activeElement); +}); + /** * Given a tooltip object instance (see Tooltip.js), checks if it is set to * toggle and hover and if so, checks if the given target is a valid hover target. * This won't actually show the tooltip (the less we interact with XUL panels * during test runs, the better). - * @return a promise that resolves when the answer is known. Also, this will - * delegate to a function in the rule-view which will insert content into the - * tooltip + * @return a promise that resolves when the answer is known */ function isHoverTooltipTarget(tooltip, target) { if (!tooltip._basedNode || !tooltip.panel) { - return promise.reject(new Error("The tooltip passed isn't set to toggle on hover or is not a tooltip")); + return promise.reject(new Error( + "The tooltip passed isn't set to toggle on hover or is not a tooltip")); } - // The tooltip delegates to a user defined cb that inserts content in the tooltip - // when calling isValidHoverTarget return tooltip.isValidHoverTarget(target); } -function getRuleViewProperty(name, ruleView) { - let prop = null; - [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => { - let nameSpan = property.querySelector(".ruleview-propertyname"); - let valueSpan = property.querySelector(".ruleview-propertyvalue"); - - if (nameSpan.textContent === name) { - prop = {nameSpan: nameSpan, valueSpan: valueSpan}; - } +/** + * Same as isHoverTooltipTarget except that it will fail the test if there is no + * tooltip defined on hover of the given element + * @return a promise + */ +function assertHoverTooltipOn(tooltip, element) { + return isHoverTooltipTarget(tooltip, element).then(() => { + ok(true, "A tooltip is defined on hover of the given element"); + }, () => { + ok(false, "No tooltip is defined on hover of the given element"); }); - return prop; } /** - * Get references to the name and value span nodes corresponding to a given - * selector and property name in the rule-view - * @return an object {nameSpan, valueSpan} + * Same as assertHoverTooltipOn but fails the test if there is a tooltip defined + * on hover of the given element + * @return a promise */ -function getRuleViewSelectorProperty(selectorText, propertyName, ruleView) { - let rule, property; +function assertNoHoverTooltipOn(tooltip, element) { + return isHoverTooltipTarget(tooltip, element).then(() => { + ok(false, "A tooltip is defined on hover of the given element"); + }, () => { + ok(true, "No tooltip is defined on hover of the given element"); + }); +} - for (let r of ruleView.doc.querySelectorAll(".ruleview-rule")) { +/** + * Listen for a new window to open and return a promise that resolves when one + * does and completes its load. + * Only resolves when the new window topic isn't domwindowopened. + * @return a promise that resolves to the window object + */ +function waitForWindow() { + let def = promise.defer(); + + info("Waiting for a window to open"); + Services.ww.registerNotification(function onWindow(subject, topic) { + if (topic != "domwindowopened") { + return; + } + info("A window has been opened"); + let win = subject.QueryInterface(Ci.nsIDOMWindow); + once(win, "load").then(() => { + info("The window load completed"); + Services.ww.unregisterNotification(onWindow); + def.resolve(win); + }); + }); + + return def.promise; +} + +/** + * @see SimpleTest.waitForClipboard + * @param {Function} setup Function to execute before checking for the + * clipboard content + * @param {String|Boolean} expected An expected string or validator function + * @return a promise that resolves when the expected string has been found or + * the validator function has returned true, rejects otherwise. + */ +function waitForClipboard(setup, expected) { + let def = promise.defer(); + SimpleTest.waitForClipboard(expected, setup, def.resolve, def.reject); + return def.promise; +} + +/** + * Dispatch the copy event on the given element + */ +function fireCopyEvent(element) { + let evt = element.ownerDocument.createEvent("Event"); + evt.initEvent("copy", true, true); + element.dispatchEvent(evt); +} + +/** + * Polls a given function waiting for it to return true. + * + * @param {Function} validatorFn A validator function that returns a boolean. + * This is called every few milliseconds to check if the result is true. When + * it is true, the promise resolves. If validatorFn never returns true, then + * polling timeouts after several tries and the promise rejects. + * @param {String} name Optional name of the test. This is used to generate + * the success and failure messages. + * @param {Number} timeout Optional timeout for the validator function, in + * milliseconds. Default is 5000. + * @return a promise that resolves when the function returned true or rejects + * if the timeout is reached + */ +function waitForSuccess(validatorFn, name="untitled", timeout=5000) { + let def = promise.defer(); + let start = Date.now(); + + function wait(validatorFn) { + if ((Date.now() - start) > timeout) { + ok(false, "Validator function " + name + " timed out"); + return def.reject(); + } + if (validatorFn()) { + ok(true, "Validator function " + name + " returned true"); + def.resolve(); + } else { + setTimeout(() => wait(validatorFn), 100); + } + } + wait(validatorFn); + + return def.promise; +} + +/** + * Create a new style tag containing the given style text and append it to the + * document's head node + * @param {Document} doc + * @param {String} style + * @return {DOMNode} The newly created style node + */ +function addStyle(doc, style) { + info("Adding a new style tag to the document with style content: " + + style.substring(0, 50)); + let node = doc.createElement('style'); + node.setAttribute("type", "text/css"); + node.textContent = style; + doc.getElementsByTagName("head")[0].appendChild(node); + return node; +} + +/** + * Checks whether the inspector's sidebar corresponding to the given id already + * exists + * @param {InspectorPanel} + * @param {String} + * @return {Boolean} + */ +function hasSideBarTab(inspector, id) { + return !!inspector.sidebar.getWindowForTab(id); +} + +/* ********************************************* + * RULE-VIEW + * ********************************************* + * Rule-view related test utility functions + * This object contains functions to get rules, get properties, ... + */ + +/** + * Get the DOMNode for a css rule in the rule-view that corresponds to the given + * selector + * @param {CssRuleView} view The instance of the rule-view panel + * @param {String} selectorText The selector in the rule-view for which the rule + * object is wanted + * @return {DOMNode} + */ +function getRuleViewRule(view, selectorText) { + let rule; + for (let r of view.doc.querySelectorAll(".ruleview-rule")) { let selector = r.querySelector(".ruleview-selector-matched"); if (selector && selector.textContent === selectorText) { rule = r; @@ -356,19 +484,35 @@ function getRuleViewSelectorProperty(selectorText, propertyName, ruleView) { } } + return rule; +} + +/** + * Get references to the name and value span nodes corresponding to a given + * selector and property name in the rule-view + * @param {CssRuleView} view The instance of the rule-view panel + * @param {String} selectorText The selector in the rule-view to look for the + * property in + * @param {String} propertyName The name of the property + * @return {Object} An object like {nameSpan: DOMNode, valueSpan: DOMNode} + */ +function getRuleViewProperty(view, selectorText, propertyName) { + let prop; + + let rule = getRuleViewRule(view, selectorText); if (rule) { // Look for the propertyName in that rule element for (let p of rule.querySelectorAll(".ruleview-property")) { let nameSpan = p.querySelector(".ruleview-propertyname"); let valueSpan = p.querySelector(".ruleview-propertyvalue"); + if (nameSpan.textContent === propertyName) { - property = {nameSpan: nameSpan, valueSpan: valueSpan}; + prop = {nameSpan: nameSpan, valueSpan: valueSpan}; break; } } } - - return property; + return prop; } /** @@ -383,29 +527,157 @@ function getRuleViewSelectorProperty(selectorText, propertyName, ruleView) { * - {String} value The expected style value * The style will be checked like so: getComputedStyle(element)[name] === value */ -function simulateColorChange(colorPicker, newRgba, expectedChange) { - // Note that this test isn't concerned with simulating events to test how the - // spectrum color picker reacts, see browser_spectrum.js for this. - // This test only cares about the color swatch <-> color picker <-> rule view - // interactions. That's why there's no event simulations here - return Task.spawn(function*() { - info("Getting the spectrum colorpicker object"); - let spectrum = yield colorPicker.spectrum; - info("Setting the new color"); - spectrum.rgb = newRgba; - info("Applying the change"); - spectrum.updateUI(); - spectrum.onChange(); +let simulateColorPickerChange = Task.async(function*(colorPicker, newRgba, expectedChange) { + info("Getting the spectrum colorpicker object"); + let spectrum = yield colorPicker.spectrum; + info("Setting the new color"); + spectrum.rgb = newRgba; + info("Applying the change"); + spectrum.updateUI(); + spectrum.onChange(); - if (expectedChange) { - info("Waiting for the style to be applied on the page"); - yield waitForSuccess({ - validatorFn: () => { - let {element, name, value} = expectedChange; - return content.getComputedStyle(element)[name] === value; - }, - name: "Color picker change applied on the page" - }); - } - }); + if (expectedChange) { + info("Waiting for the style to be applied on the page"); + yield waitForSuccess(() => { + let {element, name, value} = expectedChange; + return content.getComputedStyle(element)[name] === value; + }, "Color picker change applied on the page"); + } +}); + +/** + * Get a rule-link from the rule-view given its index + * @param {CssRuleView} view The instance of the rule-view panel + * @param {Number} index The index of the link to get + * @return {DOMNode} The link if any at this index + */ +function getRuleViewLinkByIndex(view, index) { + let links = view.doc.querySelectorAll(".ruleview-rule-source"); + return links[index]; +} + +// TO BE UNCOMMENTED WHEN THE EYEDROPPER FINALLY LANDS +// /** +// * Given a color swatch in the ruleview, click on it to open the color picker +// * and then click on the eyedropper button to start the eyedropper tool +// * @param {CssRuleView} view The instance of the rule-view panel +// * @param {DOMNode} swatch The color swatch to be clicked on +// * @return A promise that resolves when the dropper is opened +// */ +// let openRuleViewEyeDropper = Task.async(function*(view, swatch) { +// info("Opening the colorpicker tooltip on a colorswatch"); +// let tooltip = view.colorPicker.tooltip; +// let onTooltipShown = tooltip.once("shown"); +// swatch.click(); +// yield onTooltipShown; + +// info("Finding the eyedropper icon in the colorpicker document"); +// let tooltipDoc = tooltip.content.contentDocument; +// let dropperButton = tooltipDoc.querySelector("#eyedropper-button"); +// ok(dropperButton, "Found the eyedropper icon"); + +// info("Opening the eyedropper"); +// let onOpen = tooltip.once("eyedropper-opened"); +// dropperButton.click(); +// return yield onOpen; +// }); + +/* ********************************************* + * COMPUTED-VIEW + * ********************************************* + * Computed-view related utility functions. + * Allows to get properties, links, expand properties, ... + */ + +/** + * Get references to the name and value span nodes corresponding to a given + * property name in the computed-view + * @param {CssHtmlTree} view The instance of the computed view panel + * @param {String} name The name of the property to retrieve + * @return an object {nameSpan, valueSpan} + */ +function getComputedViewProperty(view, name) { + let prop; + for (let property of view.styleDocument.querySelectorAll(".property-view")) { + let nameSpan = property.querySelector(".property-name"); + let valueSpan = property.querySelector(".property-value"); + + if (nameSpan.textContent === name) { + prop = {nameSpan: nameSpan, valueSpan: valueSpan}; + break; + } + } + return prop; +} + +/** + * Expand a given property, given its index in the current property list of + * the computed view + * @param {CssHtmlTree} view The instance of the computed view panel + * @param {InspectorPanel} inspector The instance of the inspector panel + * @param {Number} index The index of the property to be expanded + * @return a promise that resolves when the property has been expanded, or + * rejects if the property was not found + */ +function expandComputedViewPropertyByIndex(view, inspector, index) { + info("Expanding property " + index + " in the computed view"); + let expandos = view.styleDocument.querySelectorAll(".expandable"); + if (!expandos.length || !expandos[index]) { + return promise.reject(); + } + + let onExpand = inspector.once("computed-view-property-expanded"); + expandos[index].click(); + return onExpand; +} + +/** + * Get a rule-link from the computed-view given its index + * @param {CssHtmlTree} view The instance of the computed view panel + * @param {Number} index The index of the link to be retrieved + * @return {DOMNode} The link at the given index, if one exists, null otherwise + */ +function getComputedViewLinkByIndex(view, index) { + let links = view.styleDocument.querySelectorAll(".rule-link .link"); + return links[index]; +} + +/* ********************************************* + * STYLE-EDITOR + * ********************************************* + * Style-editor related utility functions. + */ + +/** + * Wait for the toolbox to emit the styleeditor-selected event and when done + * wait for the stylesheet identified by href to be loaded in the stylesheet + * editor + * @param {Toolbox} toolbox + * @param {String} href Optional, if not provided, wait for the first editor + * to be ready + * @return a promise that resolves to the editor when the stylesheet editor is + * ready + */ +function waitForStyleEditor(toolbox, href) { + let def = promise.defer(); + + info("Waiting for the toolbox to switch to the styleeditor"); + toolbox.once("styleeditor-ready").then(() => { + let panel = toolbox.getCurrentPanel(); + ok(panel && panel.UI, "Styleeditor panel switched to front"); + + panel.UI.on("editor-selected", function onEditorSelected(event, editor) { + let currentHref = editor.styleSheet.href; + if (!href || (href && currentHref.endsWith(href))) { + info("Stylesheet editor selected"); + panel.UI.off("editor-selected", onEditorSelected); + editor.getSourceEditor().then(editor => { + info("Stylesheet editor fully loaded"); + def.resolve(editor); + }); + } + }); + }); + + return def.promise; }