Bug 988313 - Rewriting all devtools/styleinspector tests to be shorter, less prone to failures and more consistent; r=miker

This commit is contained in:
Patrick Brosset 2014-04-07 21:27:24 +02:00
Родитель 2b4d57d50a
Коммит caf3bb957f
57 изменённых файлов: 3707 добавлений и 5289 удалений

Просмотреть файл

@ -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]

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
let test = asyncTest(function*() {
yield addTab("data:text/html,default styles test");
info("Adding content to the test page");
content.document.body.innerHTML = '<style type="text/css"> ' +
'.matches {color: #F00;}</style>' +
'<span class="matches">Some styled text</span>' +
'</div>';
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;
}

Просмотреть файл

@ -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");
}

Просмотреть файл

@ -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 = [
'<style type="text/css">',
@ -18,101 +17,53 @@ const PAGE_CONTENT = [
'<div id="testElement">test element</div>'
].join("\n");
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html;charset=utf-8,font family longhand tooltip test");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
info("Creating the test document");
content.document.body.innerHTML = PAGE_CONTENT;
content.location = "data:text/html;charset=utf-8,font family longhand tooltip test";
info("Opening the rule view");
let {toolbox, inspector, view} = yield openRuleView();
info("Selecting the test node");
yield selectNode("#testElement", inspector);
yield testRuleView(view);
info("Opening the computed view");
let {toolbox, inspector, view} = yield openComputedView();
yield testComputedView(view);
});
function* testRuleView(ruleView) {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the font family property inside the rule view
let {valueSpan} = getRuleViewProperty(ruleView, "#testElement", "font-family");
// And verify that the tooltip gets shown on this property
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
function* testComputedView(computedView) {
info("Testing font-family tooltips in the computed view");
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector("#testElement"));
inspector.once("inspector-updated", testRuleView);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testRuleView() {
Task.spawn(function*() {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the font family property inside the rule view
let {valueSpan} = getRuleViewProperty("font-family");
// And verify that the tooltip gets shown on this property
assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
}).then(testComputedView);
}
function testComputedView() {
Task.spawn(function*() {
info("Testing font-family tooltips in the computed view");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
assertTooltipShownOn(computedView.tooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
}).then(endTests);
}
function getRuleViewProperty(name) {
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};
}
});
return prop;
}
function getComputedViewProperty(name) {
let prop = null;
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty(computedView, "font-family");
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "cursive", "Tooltips contains correct font-family style");
}

Просмотреть файл

@ -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 shorthand properties
const PAGE_CONTENT = [
'<style type="text/css">',
@ -16,106 +15,58 @@ const PAGE_CONTENT = [
'<div id="testElement">test element</div>'
].join("\n");
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html;charset=utf-8,font family shorthand tooltip test");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
info("Creating the test document");
content.document.body.innerHTML = PAGE_CONTENT;
content.location = "data:text/html;charset=utf-8,font family shorthand tooltip test";
info("Opening the rule view");
let {toolbox, inspector, view} = yield openRuleView();
info("Selecting the test node");
yield selectNode("#testElement", inspector);
yield testRuleView(view);
info("Opening the computed view");
let {toolbox, inspector, view} = yield openComputedView();
yield testComputedView(view);
});
function* testRuleView(ruleView) {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the computed font family property inside the font rule view
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
fontExpander.click();
let rule = getRuleViewRule(ruleView, "#testElement");
let valueSpan = rule.querySelector(".ruleview-computed .ruleview-propertyvalue");
// And verify that the tooltip gets shown on this property
yield assertHoverTooltipOn(ruleView.previewTooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
function* testComputedView(computedView) {
info("Testing font-family tooltips in the computed view");
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector("#testElement"));
inspector.once("inspector-updated", testRuleView);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testRuleView() {
Task.spawn(function*() {
info("Testing font-family tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the computed font family property inside the font rule view
let propertyList = ruleView.element.querySelectorAll(".ruleview-propertylist");
let fontExpander = propertyList[1].querySelectorAll(".ruleview-expander")[0];
fontExpander.click();
let {valueSpan} = getRuleViewProperty("font-family");
// And verify that the tooltip gets shown on this property
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// And that it has the right content
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
}).then(testComputedView);
}
function testComputedView() {
Task.spawn(function*() {
info("Testing font-family tooltips in the computed view");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("font-family");
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
}).then(endTests);
}
function getRuleViewProperty(name) {
let prop = null;
[].forEach.call(ruleView.doc.querySelectorAll(".ruleview-computedlist"), property => {
let nameSpan = property.querySelector(".ruleview-propertyname");
let valueSpan = property.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
}
function getComputedViewProperty(name) {
let prop = null;
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty(computedView, "font-family");
yield assertHoverTooltipOn(computedView.tooltip, valueSpan);
let description = panel.getElementsByTagName("description")[0];
is(description.style.fontFamily, "Arial", "Tooltips contains correct font-family style");
}

Просмотреть файл

@ -1,118 +1,61 @@
/* 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 correct stylesheets origins are identified in HTML & XUL
// stylesheets
"use strict";
let doc;
// Check stylesheets on HMTL and XUL document
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
"test/browser_bug705707_is_content_stylesheet.html";
const TEST_URI2 = "http://example.com/browser/browser/devtools/styleinspector/" +
"test/browser_bug705707_is_content_stylesheet.xul";
const TEST_URI_HTML = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.html";
const TEST_URI_XUL = TEST_URL_ROOT + "browser_bug705707_is_content_stylesheet.xul";
const XUL_URI = Cc["@mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService)
.newURI(TEST_URI2, null, null);
const XUL_PRINCIPAL = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(XUL_URI);
.newURI(TEST_URI_XUL, null, null);
const XUL_PRINCIPAL = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(XUL_URI);
let inspector, ruleView;
let {CssLogic} = devtools.require("devtools/styleinspector/css-logic");
function test()
{
waitForExplicitFinish();
addTab(TEST_URI);
browser.addEventListener("load", htmlLoaded, true);
}
let test = asyncTest(function*() {
info("Checking stylesheets on HTML document");
yield addTab(TEST_URI_HTML);
let target = getNode("#target");
function htmlLoaded()
{
browser.removeEventListener("load", htmlLoaded, true);
doc = content.document;
testFromHTML()
}
let {toolbox, inspector, view} = yield openRuleView();
yield selectNode(target, inspector);
function testFromHTML()
{
let target = doc.querySelector("#target");
info("Checking stylesheets");
checkSheets(target);
executeSoon(function() {
checkSheets(target);
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
inspector.selection.setNode(target);
inspector.once("inspector-updated", testModifyRules);
});
});
}
info("Checking stylesheets on XUL document");
info("Allowing XUL content");
allowXUL();
yield addTab(TEST_URI_XUL);
function reselectElement(target, cb)
{
inspector.selection.setNode(target.parentNode);
inspector.once("inspector-updated", ()=> {
inspector.selection.setNode(target);
inspector.once("inspector-updated", cb);
});
}
let {toolbox, inspector, view} = yield openRuleView();
let target = getNode("#target");
yield selectNode(target, inspector);
function testModifyRules()
{
// Set a property on all rules, then refresh and make sure they are still
// there (and there wasn't an error on the server side)
for (let rule of ruleView._elementStyle.rules) {
rule.editor.addProperty("font-weight", "bold", "");
}
checkSheets(target);
info("Disallowing XUL content");
disallowXUL();
});
executeSoon(() => {
reselectElement(doc.querySelector("#target"), () => {
for (let rule of ruleView._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");
}
gBrowser.removeCurrentTab();
openXUL();
});
});
}
function openXUL()
{
function allowXUL() {
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
.addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.ALLOW_ACTION);
addTab(TEST_URI2);
browser.addEventListener("load", xulLoaded, true);
}
function xulLoaded()
{
browser.removeEventListener("load", xulLoaded, true);
doc = content.document;
testFromXUL()
function disallowXUL() {
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
.addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
}
function testFromXUL()
{
let target = doc.querySelector("#target");
executeSoon(function() {
checkSheets(target);
finishUp();
});
}
function checkSheets(aTarget)
{
function checkSheets(target) {
let domUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
.getService(Ci.inIDOMUtils);
let domRules = domUtils.getCSSStyleRules(aTarget);
let domRules = domUtils.getCSSStyleRules(target);
for (let i = 0, n = domRules.Count(); i < n; i++) {
let domRule = domRules.GetElementAt(i);
@ -127,13 +70,3 @@ function checkSheets(aTarget)
}
}
}
function finishUp()
{
info("finishing up");
Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager)
.addFromPrincipal(XUL_PRINCIPAL, 'allowXULXBL', Ci.nsIPermissionManager.DENY_ACTION);
doc = inspector = ruleView = null;
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -1,49 +1,34 @@
/* 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";
// Tests that we correctly display appropriate media query titles in the
// property view.
let doc;
let computedView;
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
"test/browser_bug722196_identify_media_queries.html";
const TEST_URI = TEST_URL_ROOT + "browser_bug722196_identify_media_queries.html";
let {PropertyView} = devtools.require("devtools/styleinspector/computed-view");
let {CssLogic} = devtools.require("devtools/styleinspector/css-logic");
function test()
{
waitForExplicitFinish();
addTab(TEST_URI);
browser.addEventListener("load", docLoaded, true);
}
let test = asyncTest(function*() {
yield addTab(TEST_URI);
let {toolbox, inspector, view} = yield openComputedView();
function docLoaded()
{
browser.removeEventListener("load", docLoaded, true);
doc = content.document;
info("Selecting the test element");
yield selectNode("div", inspector);
openComputedView(selectNode);
}
info("Checking CSSLogic");
checkCssLogic();
function selectNode(aInspector, aComputedView)
{
computedView = aComputedView;
info("Checking property view");
yield checkPropertyView(view);
});
var div = doc.querySelector("div");
ok(div, "captain, we have the div");
aInspector.selection.setNode(div);
aInspector.once("inspector-updated", checkCssLogic);
}
function checkCssLogic()
{
function checkCssLogic() {
let cssLogic = new CssLogic();
cssLogic.highlight(doc.querySelector("div"));
cssLogic.highlight(getNode("div"));
cssLogic.processMatchedSelectors();
let _strings = Services.strings
@ -57,16 +42,14 @@ function checkCssLogic()
"rule.source gives correct output for rule 1");
is(cssLogic._matchedRules[1][0].source, source2,
"rule.source gives correct output for rule 2");
checkPropertyView();
}
function checkPropertyView()
{
let propertyView = new PropertyView(computedView, "width");
function checkPropertyView(view) {
let propertyView = new PropertyView(view, "width");
propertyView.buildMain();
propertyView.buildSelectorContainer();
propertyView.matchedExpanded = true;
return propertyView.refreshMatchedSelectors().then(() => {
let numMatchedSelectors = propertyView.matchedSelectors.length;
@ -75,14 +58,5 @@ function checkPropertyView()
is(propertyView.hasMatchedSelectors, true,
"hasMatchedSelectors returns true");
finishUp();
}).then(null, (err) => console.error(err));
}
function finishUp()
{
doc = computedView = null;
gBrowser.removeCurrentTab();
finish();
});
}

Просмотреть файл

@ -1,44 +1,21 @@
/* 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";
// Tests that we correctly display appropriate media query titles in the
// rule view.
let doc;
let inspector;
const TEST_URI = TEST_URL_ROOT + "browser_bug722196_identify_media_queries.html";
const TEST_URI = "http://example.com/browser/browser/devtools/styleinspector/" +
"test/browser_bug722196_identify_media_queries.html";
let test = asyncTest(function*() {
yield addTab(TEST_URI);
let {inspector, view} = yield openRuleView();
function test()
{
waitForExplicitFinish();
addTab(TEST_URI);
browser.addEventListener("load", docLoaded, true);
}
yield selectNode("div", inspector);
function docLoaded()
{
browser.removeEventListener("load", docLoaded, true);
doc = content.document;
openRuleView(selectNode);
}
function selectNode(aInspector, aRuleView)
{
inspector = aInspector;
inspector.selection.setNode(doc.querySelector("div"));
inspector.once("inspector-updated", checkSheets);
}
function checkSheets()
{
var div = doc.querySelector("div");
ok(div, "captain, we have the div");
let elementStyle = ruleView()._elementStyle;
let elementStyle = view._elementStyle;
let _strings = Services.strings
.createBundle("chrome://global/locale/devtools/styleinspector.properties");
@ -50,12 +27,5 @@ function checkSheets()
is(elementStyle.rules[1].title, inline +
":15 @media screen and (min-width: 1px)", "check rule 1 title");
is(elementStyle.rules[2].title, inline + ":8", "check rule 2 title");
finishUp();
}
});
function finishUp()
{
doc = inspector = null;
gBrowser.removeCurrentTab();
finish();
}

Просмотреть файл

@ -1,192 +1,176 @@
/* 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 increasing/decreasing values in rule view using
// arrow keys works correctly.
let doc;
let view;
let inspector;
let test = asyncTest(function*() {
yield addTab("data:text/html,sample document for bug 722691");
createDocument();
let {toolbox, inspector, view} = yield openRuleView();
function setUpTests()
{
doc.body.innerHTML = '<div id="test" style="' +
yield selectNode("#test", inspector);
yield testMarginIncrements(view);
yield testVariousUnitIncrements(view);
yield testHexIncrements(view);
yield testRgbIncrements(view);
yield testShorthandIncrements(view);
yield testOddCases(view);
});
function createDocument() {
content.document.body.innerHTML = '<div id="test" style="' +
'margin-top:0px;' +
'padding-top: 0px;' +
'color:#000000;' +
'background-color: #000000;" >'+
'</div>';
}
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
view = aRuleView;
inspector.selection.setNode(doc.getElementById("test"));
inspector.once("inspector-updated", () => {
runTests();
})
function* testMarginIncrements(view) {
info("Testing keyboard increments on the margin property");
let idRuleEditor = view.element.children[0]._ruleEditor;
let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
yield runIncrementTest(marginPropEditor, view, {
1: {alt: true, start: "0px", end: "0.1px", selectAll: true},
2: {start: "0px", end: "1px", selectAll: true},
3: {shift: true, start: "0px", end: "10px", selectAll: true},
4: {down: true, alt: true, start: "0.1px", end: "0px", selectAll: true},
5: {down: true, start: "0px", end: "-1px", selectAll: true},
6: {down: true, shift: true, start: "0px", end: "-10px", selectAll: true},
7: {pageUp: true, shift: true, start: "0px", end: "100px", selectAll: true},
8: {pageDown: true, shift: true, start: "0px", end: "-100px", selectAll: true}
});
}
function runTests()
{
function* testVariousUnitIncrements(view) {
info("Testing keyboard increments on values with various units");
let idRuleEditor = view.element.children[0]._ruleEditor;
let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
yield runIncrementTest(paddingPropEditor, view, {
1: {start: "0px", end: "1px", selectAll: true},
2: {start: "0pt", end: "1pt", selectAll: true},
3: {start: "0pc", end: "1pc", selectAll: true},
4: {start: "0em", end: "1em", selectAll: true},
5: {start: "0%", end: "1%", selectAll: true},
6: {start: "0in", end: "1in", selectAll: true},
7: {start: "0cm", end: "1cm", selectAll: true},
8: {start: "0mm", end: "1mm", selectAll: true},
9: {start: "0ex", end: "1ex", selectAll: true}
});
};
function* testHexIncrements(view) {
info("Testing keyboard increments with hex colors");
let idRuleEditor = view.element.children[0]._ruleEditor;
let hexColorPropEditor = idRuleEditor.rule.textProps[2].editor;
yield runIncrementTest(hexColorPropEditor, view, {
1: {start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
2: {shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true},
3: {start: "#CCCCCC", end: "#CDCCCC", selection: [1,3]},
4: {shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1,3]},
5: {start: "#FFFFFF", end: "#FFFFFF", selectAll: true},
6: {down: true, shift: true, start: "#000000", end: "#000000", selectAll: true}
});
};
function* testRgbIncrements(view) {
info("Testing keyboard increments with rgb colors");
let idRuleEditor = view.element.children[0]._ruleEditor;
let rgbColorPropEditor = idRuleEditor.rule.textProps[3].editor;
(function() {
info("INCREMENTS");
newTest( marginPropEditor, {
1: { alt: true, start: "0px", end: "0.1px", selectAll: true },
2: { start: "0px", end: "1px", selectAll: true },
3: { shift: true, start: "0px", end: "10px", selectAll: true },
4: { down: true, alt: true, start: "0.1px", end: "0px", selectAll: true },
5: { down: true, start: "0px", end: "-1px", selectAll: true },
6: { down: true, shift: true, start: "0px", end: "-10px", selectAll: true },
7: { pageUp: true, shift: true, start: "0px", end: "100px", selectAll: true },
8: { pageDown: true, shift: true, start: "0px", end: "-100px", selectAll: true,
nextTest: test2 }
});
EventUtils.synthesizeMouse(marginPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
})();
yield runIncrementTest(rgbColorPropEditor, view, {
1: {start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6,7]},
2: {shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6,7]},
3: {start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6,9]},
4: {shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6,9]},
5: {down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6,7]},
6: {down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6,7]}
});
};
function test2() {
info("UNITS");
newTest( paddingPropEditor, {
1: { start: "0px", end: "1px", selectAll: true },
2: { start: "0pt", end: "1pt", selectAll: true },
3: { start: "0pc", end: "1pc", selectAll: true },
4: { start: "0em", end: "1em", selectAll: true },
5: { start: "0%", end: "1%", selectAll: true },
6: { start: "0in", end: "1in", selectAll: true },
7: { start: "0cm", end: "1cm", selectAll: true },
8: { start: "0mm", end: "1mm", selectAll: true },
9: { start: "0ex", end: "1ex", selectAll: true,
nextTest: test3 }
});
EventUtils.synthesizeMouse(paddingPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
};
function* testShorthandIncrements(view) {
info("Testing keyboard increments within shorthand values");
function test3() {
info("HEX COLORS");
newTest( hexColorPropEditor, {
1: { start: "#CCCCCC", end: "#CDCDCD", selectAll: true},
2: { shift: true, start: "#CCCCCC", end: "#DCDCDC", selectAll: true },
3: { start: "#CCCCCC", end: "#CDCCCC", selection: [1,3] },
4: { shift: true, start: "#CCCCCC", end: "#DCCCCC", selection: [1,3] },
5: { start: "#FFFFFF", end: "#FFFFFF", selectAll: true },
6: { down: true, shift: true, start: "#000000", end: "#000000", selectAll: true,
nextTest: test4 }
});
EventUtils.synthesizeMouse(hexColorPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
};
let idRuleEditor = view.element.children[0]._ruleEditor;
let paddingPropEditor = idRuleEditor.rule.textProps[1].editor;
function test4() {
info("RGB COLORS");
newTest( rgbColorPropEditor, {
1: { start: "rgb(0,0,0)", end: "rgb(0,1,0)", selection: [6,7] },
2: { shift: true, start: "rgb(0,0,0)", end: "rgb(0,10,0)", selection: [6,7] },
3: { start: "rgb(0,255,0)", end: "rgb(0,255,0)", selection: [6,9] },
4: { shift: true, start: "rgb(0,250,0)", end: "rgb(0,255,0)", selection: [6,9] },
5: { down: true, start: "rgb(0,0,0)", end: "rgb(0,0,0)", selection: [6,7] },
6: { down: true, shift: true, start: "rgb(0,5,0)", end: "rgb(0,0,0)", selection: [6,7],
nextTest: test5 }
});
EventUtils.synthesizeMouse(rgbColorPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
};
yield runIncrementTest(paddingPropEditor, view, {
1: {start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4,7]},
2: {shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4,7]},
3: {start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true},
4: {shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true},
5: {down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8,11]},
6: {down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true}
});
};
function test5() {
info("SHORTHAND");
newTest( paddingPropEditor, {
1: { start: "0px 0px 0px 0px", end: "0px 1px 0px 0px", selection: [4,7] },
2: { shift: true, start: "0px 0px 0px 0px", end: "0px 10px 0px 0px", selection: [4,7] },
3: { start: "0px 0px 0px 0px", end: "1px 0px 0px 0px", selectAll: true },
4: { shift: true, start: "0px 0px 0px 0px", end: "10px 0px 0px 0px", selectAll: true },
5: { down: true, start: "0px 0px 0px 0px", end: "0px 0px -1px 0px", selection: [8,11] },
6: { down: true, shift: true, start: "0px 0px 0px 0px", end: "-10px 0px 0px 0px", selectAll: true,
nextTest: test6 }
});
EventUtils.synthesizeMouse(paddingPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
};
function* testOddCases(view) {
info("Testing some more odd cases");
function test6() {
info("ODD CASES");
newTest( marginPropEditor, {
1: { start: "98.7%", end: "99.7%", selection: [3,3] },
2: { alt: true, start: "98.7%", end: "98.8%", selection: [3,3] },
3: { start: "0", end: "1" },
4: { down: true, start: "0", end: "-1" },
5: { start: "'a=-1'", end: "'a=0'", selection: [4,4] },
6: { start: "0 -1px", end: "0 0px", selection: [2,2] },
7: { start: "url(-1)", end: "url(-1)", selection: [4,4] },
8: { start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,11] },
9: { start: "url('test1.png')", end: "url('test2.png')", selection: [9,9] },
10: { shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9,9] },
11: { down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9,11] },
12: { start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,12] },
13: { down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10,11] },
14: { alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10,14],
endTest: true }
});
EventUtils.synthesizeMouse(marginPropEditor.valueSpan, 1, 1, {}, view.doc.defaultView);
};
}
let idRuleEditor = view.element.children[0]._ruleEditor;
let marginPropEditor = idRuleEditor.rule.textProps[0].editor;
function newTest( propEditor, tests )
{
waitForEditorFocus(propEditor.element, function onElementFocus(aEditor) {
for( test in tests) {
testIncrement( aEditor, tests[test] );
}
}, false);
}
yield runIncrementTest(marginPropEditor, view, {
1: {start: "98.7%", end: "99.7%", selection: [3,3]},
2: {alt: true, start: "98.7%", end: "98.8%", selection: [3,3]},
3: {start: "0", end: "1"},
4: {down: true, start: "0", end: "-1"},
5: {start: "'a=-1'", end: "'a=0'", selection: [4,4]},
6: {start: "0 -1px", end: "0 0px", selection: [2,2]},
7: {start: "url(-1)", end: "url(-1)", selection: [4,4]},
8: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,11]},
9: {start: "url('test1.png')", end: "url('test2.png')", selection: [9,9]},
10: {shift: true, start: "url('test1.1.png')", end: "url('test11.1.png')", selection: [9,9]},
11: {down: true, start: "url('test-1.png')", end: "url('test-2.png')", selection: [9,11]},
12: {start: "url('test1.1.png')", end: "url('test1.2.png')", selection: [11,12]},
13: {down: true, alt: true, start: "url('test-0.png')", end: "url('test--0.1.png')", selection: [10,11]},
14: {alt: true, start: "url('test--0.1.png')", end: "url('test-0.png')", selection: [10,14]}
});
};
function testIncrement( aEditor, aOptions )
{
aEditor.input.value = aOptions.start;
let input = aEditor.input;
if ( aOptions.selectAll ) {
input.select();
} else if ( aOptions.selection ) {
input.setSelectionRange(aOptions.selection[0], aOptions.selection[1]);
function* runIncrementTest(propertyEditor, view, tests) {
let editor = yield focusEditableField(propertyEditor.valueSpan);
for(let test in tests) {
yield testIncrement(editor, tests[test], view);
}
is(input.value, aOptions.start, "Value initialized at " + aOptions.start);
input.addEventListener("keyup", function onIncrementUp() {
input.removeEventListener("keyup", onIncrementUp, false);
input = aEditor.input;
is(input.value, aOptions.end, "Value changed to " + aOptions.end);
if( aOptions.nextTest) {
aOptions.nextTest();
}
else if( aOptions.endTest ) {
finishTest();
}
}, false);
// Once properties have been set, wait for the inspector to update
yield view.inspector.once("inspector-updated");
}
function* testIncrement(editor, options, view) {
editor.input.value = options.start;
let input = editor.input;
if (options.selectAll) {
input.select();
} else if (options.selection) {
input.setSelectionRange(options.selection[0], options.selection[1]);
}
is(input.value, options.start, "Value initialized at " + options.start);
let onKeyUp = once(input, "keyup");
let key;
key = ( aOptions.down ) ? "VK_DOWN" : "VK_UP";
key = ( aOptions.pageDown ) ? "VK_PAGE_DOWN" : ( aOptions.pageUp ) ? "VK_PAGE_UP" : key;
EventUtils.synthesizeKey(key,
{altKey: aOptions.alt, shiftKey: aOptions.shift},
view.doc.defaultView);
}
key = options.down ? "VK_DOWN" : "VK_UP";
key = options.pageDown ? "VK_PAGE_DOWN" : options.pageUp ? "VK_PAGE_UP" : key;
EventUtils.synthesizeKey(key, {altKey: options.alt, shiftKey: options.shift}, view.doc.defaultView);
function finishTest()
{
doc = view = 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(setUpTests, content);
}, true);
content.location = "data:text/html,sample document for bug 722691";
yield onKeyUp;
input = editor.input;
is(input.value, options.end, "Value changed to " + options.end);
}

Просмотреть файл

@ -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 that the css transform preview tooltip is shown on transform properties
const PAGE_CONTENT = [
'<style type="text/css">',
@ -29,160 +28,60 @@ const PAGE_CONTENT = [
'<div id="testElement" class="test-element" attr="value">transformed element</div>'
].join("\n");
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html,rule view css transform tooltip test");
content.document.body.innerHTML = PAGE_CONTENT;
let {toolbox, inspector, view} = yield openRuleView();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
info("Selecting the test node");
yield selectNode("#testElement", inspector);
content.location = "data:text/html,rule view css transform tooltip test";
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector("#testElement"));
inspector.once("inspector-updated", testTransformTooltipOnIDSelector);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testTransformTooltipOnIDSelector() {
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the #ID rule");
let panel = ruleView.previewTooltip.panel;
ok(panel, "The XUL panel exists for the rule-view preview tooltips");
let {valueSpan} = getRuleViewProperty("#testElement", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the #ID rule");
}).then(testTransformTooltipOnClassSelector);
}
function testTransformTooltipOnClassSelector() {
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the .class rule");
let {valueSpan} = getRuleViewProperty(".test-element", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the .class rule");
}).then(testTransformTooltipOnTagSelector);
}
function testTransformTooltipOnTagSelector() {
Task.spawn(function*() {
info("Testing that a transform tooltip appears on the tag rule");
let {valueSpan} = getRuleViewProperty("div", "transform");
yield assertTooltipShownOn(ruleView.previewTooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property of the tag rule");
}).then(testTransformTooltipNotShownOnInvalidTransform);
}
function testTransformTooltipNotShownOnInvalidTransform() {
Task.spawn(function*() {
info("Testing that a transform tooltip does not appear for invalid values");
let ruleEditor;
for (let rule of ruleView._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor;
}
}
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
let {valueSpan} = getRuleViewProperty("[attr]", "transform");
let isValid = yield isHoverTooltipTarget(ruleView.previewTooltip, valueSpan);
ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
}).then(testTransformTooltipOnComputedView);
}
function testTransformTooltipOnComputedView() {
Task.spawn(function*() {
info("Testing that a transform tooltip appears in the computed view too");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("transform");
yield assertTooltipShownOn(computedView.tooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the computed transform property");
}).then(endTests);
}
function getRule(selectorText) {
let rule;
[].forEach.call(ruleView.doc.querySelectorAll(".ruleview-rule"), aRule => {
let selector = aRule.querySelector(".ruleview-selector-matched");
if (selector && selector.textContent === selectorText) {
rule = aRule;
}
});
return rule;
}
function getRuleViewProperty(selectorText, propertyName) {
let prop;
let rule = getRule(selectorText);
if (rule) {
// Look for the propertyName in that rule element
[].forEach.call(rule.querySelectorAll(".ruleview-property"), property => {
let nameSpan = property.querySelector(".ruleview-propertyname");
let valueSpan = property.querySelector(".ruleview-propertyvalue");
if (nameSpan.textContent === propertyName) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
info("Checking that transforms tooltips are shown in various rule-view properties");
for (let selector of [".test-element", "div", "#testElement"]) {
yield testTransformTooltipOnSelector(view, selector);
}
return prop;
info("Checking that the transform tooltip doesn't appear for invalid transforms");
yield testTransformTooltipNotShownOnInvalidTransform(view);
info("Checking transforms in the computed-view");
let {view} = yield openComputedView();
yield testTransformTooltipOnComputedView(view);
});
function* testTransformTooltipOnSelector(view, selector) {
info("Testing that a transform tooltip appears on transform in " + selector);
let {valueSpan} = getRuleViewProperty(view, selector, "transform");
ok(valueSpan, "The transform property was found");
yield assertHoverTooltipOn(view.previewTooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the transform property in " + selector);
}
function getComputedViewProperty(name) {
let prop;
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
function* testTransformTooltipNotShownOnInvalidTransform(view) {
let ruleEditor;
for (let rule of view._elementStyle.rules) {
if (rule.matchedSelectors[0] === "[attr]") {
ruleEditor = rule.editor;
}
});
return prop;
}
ruleEditor.addProperty("transform", "muchTransform(suchAngle)", "");
let {valueSpan} = getRuleViewProperty(view, "[attr]", "transform");
let isValid = yield isHoverTooltipTarget(view.previewTooltip, valueSpan);
ok(!isValid, "The tooltip did not appear on hover of an invalid transform value");
}
function* testTransformTooltipOnComputedView(view) {
info("Testing that a transform tooltip appears in the computed view too");
let {valueSpan} = getComputedViewProperty(view, "transform");
yield assertHoverTooltipOn(view.tooltip, valueSpan);
// The transform preview is canvas, so there's not much we can test, so for
// now, let's just be happy with the fact that the tooltips is shown!
ok(true, "Tooltip shown on the computed transform property");
}

Просмотреть файл

@ -1,11 +1,11 @@
/* 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 that background-image URLs have image preview tooltips in the rule-view
// and computed-view
const PAGE_CONTENT = [
'<style type="text/css">',
@ -25,150 +25,97 @@ const PAGE_CONTENT = [
'<div class="test-element">test element</div>'
].join("\n");
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html,rule view tooltip test");
content.document.body.innerHTML = PAGE_CONTENT;
let {toolbox, inspector, view} = yield openRuleView();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
info("Testing the background-image property on the body rule");
yield testBodyRuleView(view);
content.location = "data:text/html,rule view tooltip test";
info("Selecting the test div node");
yield selectNode(".test-element", inspector);
info("Testing the the background property on the .test-element rule");
yield testDivRuleView(view);
info("Testing that image preview tooltips show even when there are fields being edited");
yield testTooltipAppearsEvenInEditMode(view);
info("Switching over to the computed-view");
let {view} = yield openComputedView();
info("Testing that the background-image computed style has a tooltip too");
yield testComputedView(view);
});
function* testBodyRuleView(view) {
info("Testing tooltips in the rule view");
let panel = view.previewTooltip.panel;
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(view.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the background-image property inside the rule view
let {valueSpan} = getRuleViewProperty(view, "body", "background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
"The image URL seems fine");
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
function* testDivRuleView(view) {
let panel = view.previewTooltip.panel;
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
// Get the background property inside the rule view
let {valueSpan} = getRuleViewProperty(view, ".test-element", "background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
}
function startTests() {
inspector.selection.setNode(contentDoc.body);
inspector.once("inspector-updated", testBodyRuleView);
}
function* testTooltipAppearsEvenInEditMode(view) {
let panel = view.previewTooltip.panel;
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
info("Switching to edit mode in the rule view");
let editor = yield turnToEditMode(view);
function testBodyRuleView() {
Task.spawn(function*() {
info("Testing tooltips in the rule view");
let panel = ruleView.previewTooltip.panel;
info("Now trying to show the preview tooltip");
let {valueSpan} = getRuleViewProperty(view, ".test-element", "background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
// Check that the rule view has a tooltip and that a XUL panel has been created
ok(ruleView.previewTooltip, "Tooltip instance exists");
ok(panel, "XUL panel exists");
// Get the background-image property inside the rule view
let {valueSpan} = getRuleViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
"The image URL seems fine");
let onUpdated = inspector.once("inspector-updated");
inspector.selection.setNode(contentDoc.querySelector(".test-element"));
yield onUpdated;
}).then(testDivRuleView);
}
function testDivRuleView() {
Task.spawn(function*() {
let panel = ruleView.previewTooltip.panel;
// Get the background property inside the rule view
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri image as expected");
}).then(testTooltipAppearsEvenInEditMode);
}
function testTooltipAppearsEvenInEditMode() {
Task.spawn(function*() {
let panel = ruleView.previewTooltip.panel;
info("Switching to edit mode in the rule view");
let editor = yield turnToEditMode(ruleView);
info("Now trying to show the preview tooltip");
let {valueSpan} = getRuleViewProperty("background");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
is(ruleView.doc.activeElement, editor.input,
"Tooltip was shown in edit mode, and inplace-editor still focused");
}).then(testComputedView);
is(view.doc.activeElement, editor.input,
"Tooltip was shown in edit mode, and inplace-editor still focused");
}
function turnToEditMode(ruleView) {
let def = promise.defer();
let brace = ruleView.doc.querySelector(".ruleview-ruleclose");
waitForEditorFocus(brace.parentNode, def.resolve);
brace.click();
return def.promise;
return focusEditableField(brace);
}
function testComputedView() {
Task.spawn(function*() {
info("Testing tooltips in the computed view");
function* testComputedView(view) {
let tooltip = view.tooltip;
ok(tooltip, "The computed-view has a tooltip defined");
inspector.sidebar.select("computedview");
computedView = inspector.sidebar.getWindowForTab("computedview").computedview.view;
let doc = computedView.styleDocument;
let panel = tooltip.panel;
ok(panel, "The computed-view tooltip has a XUL panel");
let panel = computedView.tooltip.panel;
let {valueSpan} = getComputedViewProperty("background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
let {valueSpan} = getComputedViewProperty(view, "background-image");
let uriSpan = valueSpan.querySelector(".theme-link");
yield assertTooltipShownOn(computedView.tooltip, uriSpan);
yield assertHoverTooltipOn(view.tooltip, uriSpan);
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
let images = panel.getElementsByTagName("image");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
}).then(endTests);
}
function getRuleViewProperty(name) {
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};
}
});
return prop;
}
function getComputedViewProperty(name) {
let prop = null;
[].forEach.call(computedView.styleDocument.querySelectorAll(".property-view"), property => {
let nameSpan = property.querySelector(".property-name");
let valueSpan = property.querySelector(".property-value");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
ok(images[0].getAttribute("src").startsWith("data:"), "Tooltip contains a data-uri in the computed-view too");
}

Просмотреть файл

@ -1,16 +1,14 @@
/* 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/ */
// Test that CSS property names are autocompleted and cycled correctly.
"use strict";
// Test that CSS property names are autocompleted and cycled correctly when
// editing an existing property in the rule view
const MAX_ENTRIES = 10;
let doc;
let inspector;
let ruleViewWindow;
let editor;
let state;
// format :
// [
// what key to press,
@ -54,104 +52,55 @@ let testData = [
["VK_ESCAPE", null, -1, 0],
];
function openRuleView()
{
var target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename" +
": browser_bug893965_css_property_completion_existing_property.js</h1>";
// Highlight a node.
let node = content.document.getElementsByTagName("h1")[0];
inspector.selection.setNode(node);
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
inspector.once("inspector-updated", testCompletion);
});
}
info("Selecting the test node");
yield selectNode("h1", inspector);
function testCompletion()
{
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
let brace = ruleViewWindow.document.querySelector(".ruleview-propertyname");
info("Focusing the css property editable field");
let propertyName = view.doc.querySelectorAll(".ruleview-propertyname")[0];
let editor = yield focusEditableField(propertyName);
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
editor = aEditor;
checkStateAndMoveOn(0);
});
brace.click();
}
function checkStateAndMoveOn(index) {
if (index == testData.length) {
finishUp();
return;
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {
yield testCompletion(testData[i], editor, view);
}
});
let [key] = testData[index];
state = index;
function* testCompletion([key, completion, index, total], editor, view) {
info("Pressing key " + key);
info("Expecting " + completion + ", " + index + ", " + total);
let onSuggest;
info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
"] for state " + state);
if (/(left|right|back_space|escape)/ig.test(key)) {
info("added event listener for right|back_space|escape keys");
editor.input.addEventListener("keypress", function onKeypress() {
if (editor.input) {
editor.input.removeEventListener("keypress", onKeypress);
}
info("inside event listener");
checkState();
});
info("Adding event listener for left|right|back_space|escape keys");
onSuggest = once(editor.input, "keypress");
} else {
info("Waiting for after-suggest event on the editor");
onSuggest = editor.once("after-suggest");
}
else {
editor.once("after-suggest", checkState);
info("Synthesizing key " + key);
EventUtils.synthesizeKey(key, {}, view.doc.defaultView);
yield onSuggest;
yield wait(1); // Equivalent of executeSoon
info("Checking the state");
if (completion != null) {
is(editor.input.value, completion, "Correct value is autocompleted");
}
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
} else {
ok(editor.popup._panel.state == "open" || editor.popup._panel.state == "showing", "Popup is open");
is(editor.popup.getItems().length, total, "Number of suggestions match");
is(editor.popup.selectedIndex, index, "Correct item is selected");
}
EventUtils.synthesizeKey(key, {}, ruleViewWindow);
}
function checkState() {
executeSoon(() => {
info("After keypress for state " + state);
let [key, completion, index, total] = testData[state];
if (completion != null) {
is(editor.input.value, completion,
"Correct value is autocompleted for state " + state);
}
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
state);
}
else {
ok(editor.popup._panel.state == "open" ||
editor.popup._panel.state == "showing",
"Popup is open for state " + state);
is(editor.popup.getItems().length, total,
"Number of suggestions match for state " + state);
is(editor.popup.selectedIndex, index,
"Correct item is selected for state " + state);
}
checkStateAndMoveOn(state + 1);
});
}
function finishUp()
{
doc = inspector = editor = ruleViewWindow = state = 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;
doc.title = "Rule View Test";
waitForFocus(openRuleView, content);
}, true);
content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename" +
": browser_bug893965_css_property_completion_existing_property.js</h1>";
}

Просмотреть файл

@ -1,16 +1,14 @@
/* 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/ */
// Test that CSS property names are autocompleted and cycled correctly.
"use strict";
// Test that CSS property names are autocompleted and cycled correctly when
// creating a new property in the ruleview
const MAX_ENTRIES = 10;
let doc;
let inspector;
let ruleViewWindow;
let editor;
let state;
// format :
// [
// what key to press,
@ -39,98 +37,55 @@ let testData = [
["VK_ESCAPE", null, -1, 0],
];
function openRuleView() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename:" +
"browser_bug893965_css_property_completion_new_property.js</h1>";
// Highlight a node.
let node = content.document.getElementsByTagName("h1")[0];
inspector.selection.setNode(node);
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
inspector.once("inspector-updated", testCompletion);
});
}
info("Selecting the test node");
yield selectNode("h1", inspector);
function testCompletion() {
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
let brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
info("Focusing the css property editable field");
let brace = view.doc.querySelector(".ruleview-ruleclose");
let editor = yield focusEditableField(brace);
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
editor = aEditor;
checkStateAndMoveOn(0);
});
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {
yield testCompletion(testData[i], editor, view);
}
});
brace.click();
}
function* testCompletion([key, completion, index, total], editor, view) {
info("Pressing key " + key);
info("Expecting " + completion + ", " + index + ", " + total);
function checkStateAndMoveOn(index) {
if (index == testData.length) {
finishUp();
return;
let onSuggest;
if (/(right|back_space|escape)/ig.test(key)) {
info("Adding event listener for right|back_space|escape keys");
onSuggest = once(editor.input, "keypress");
} else {
info("Waiting for after-suggest event on the editor");
onSuggest = editor.once("after-suggest");
}
let [key] = testData[index];
state = index;
info("Synthesizing key " + key);
EventUtils.synthesizeKey(key, {}, view.doc.defaultView);
info("pressing key " + key + " to get result: [" + testData[index].slice(1) +
"] for state " + state);
if (/(return|back_space|escape)/ig.test(key)) {
info("added event listener for return|back_space|escape keys");
editor.input.addEventListener("keypress", function onKeypress() {
if (editor.input) {
editor.input.removeEventListener("keypress", onKeypress);
}
info("inside event listener");
checkState();
});
yield onSuggest;
yield wait(1); // Equivalent of executeSoon
info("Checking the state");
if (completion != null) {
is(editor.input.value, completion, "Correct value is autocompleted");
}
else {
editor.once("after-suggest", checkState);
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
} else {
ok(editor.popup._panel.state == "open" || editor.popup._panel.state == "showing", "Popup is open");
is(editor.popup.getItems().length, total, "Number of suggestions match");
is(editor.popup.selectedIndex, index, "Correct item is selected");
}
EventUtils.synthesizeKey(key, {}, ruleViewWindow);
}
function checkState(event) {
executeSoon(() => {
info("After keypress for state " + state);
let [key, completion, index, total] = testData[state];
if (completion != null) {
is(editor.input.value, completion,
"Correct value is autocompleted for state " + state);
}
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
state);
}
else {
ok(editor.popup.isOpen, "Popup is open for state " + state);
is(editor.popup.getItems().length, total,
"Number of suggestions match for state " + state);
is(editor.popup.selectedIndex, index,
"Correct item is selected for state " + state);
}
checkStateAndMoveOn(state + 1);
});
}
function finishUp() {
doc = inspector = editor = ruleViewWindow = state = 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;
doc.title = "Rule View Test";
waitForFocus(openRuleView, content);
}, true);
content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename:" +
"browser_bug893965_css_property_completion_new_property.js</h1>";
}

Просмотреть файл

@ -1,17 +1,12 @@
/* 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/ */
// Test that CSS property names are autocompleted and cycled correctly.
"use strict";
const MAX_ENTRIES = 10;
// Test that CSS property names and values are autocompleted and cycled correctly
// when editing existing properties in the rule view
let doc;
let inspector;
let ruleViewWindow;
let editor;
let state;
let brace;
// format :
// [
// what key to press,
@ -41,110 +36,66 @@ let testData = [
["VK_RETURN", {}, null, -1, 0]
];
function openRuleView()
{
var target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
let TEST_URL = "data:text/html,<h1 style='color: red'>Filename: " +
"browser_bug894376_css_value_completion_existing_property_value_pair.js</h1>";
// Highlight a node.
let node = content.document.getElementsByTagName("h1")[0];
inspector.selection.setNode(node);
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
inspector.once("inspector-updated", testCompletion);
});
}
info("Selecting the test node");
yield selectNode("h1", inspector);
function testCompletion()
{
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
info("Focusing the css property editable value");
let value = view.doc.querySelectorAll(".ruleview-propertyvalue")[0];
let editor = yield focusEditableField(value);
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
editor = aEditor;
checkStateAndMoveOn(0);
});
ruleViewWindow.document.querySelector(".ruleview-propertyvalue").click();
}
function checkStateAndMoveOn(index) {
if (index == testData.length) {
finishUp();
return;
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {
// Re-define the editor at each iteration, because the focus may have moved
// from property to value and back
editor = inplaceEditor(view.doc.activeElement);
yield testCompletion(testData[i], editor, view);
}
});
let [key, modifiers] = testData[index];
state = index;
function* testCompletion([key, modifiers, completion, index, total], editor, view) {
info("Pressing key " + key);
info("Expecting " + completion + ", " + index + ", " + total);
let onKeyPress;
info("pressing key " + key + " to get result: [" + testData[index].slice(2) +
"] for state " + state);
if (/tab/ig.test(key)) {
info("waiting for the editor to get focused");
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
info("editor focused : " + aEditor.input);
editor = aEditor;
checkState();
});
info("Waiting for the new property or value editor to get focused");
let brace = view.doc.querySelector(".ruleview-ruleclose");
onKeyPress = once(brace.parentNode, "focus", true);
} else if (/(right|return|back_space)/ig.test(key)) {
info("Adding event listener for right|return|back_space keys");
onKeyPress = once(editor.input, "keypress");
} else {
info("Waiting for after-suggest event on the editor");
onKeyPress = editor.once("after-suggest");
}
else if (/(right|return|back_space)/ig.test(key)) {
info("added event listener for right|return|back_space keys");
editor.input.addEventListener("keypress", function onKeypress() {
if (editor.input) {
editor.input.removeEventListener("keypress", onKeypress);
}
info("inside event listener");
checkState();
});
info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
EventUtils.synthesizeKey(key, modifiers, view.doc.defaultView);
yield onKeyPress;
yield wait(1); // Equivalent of executeSoon
// The key might have been a TAB or shift-TAB, in which case the editor will
// be a new one
editor = inplaceEditor(view.doc.activeElement);
info("Checking the state");
if (completion != null) {
is(editor.input.value, completion, "Correct value is autocompleted");
}
else {
editor.once("after-suggest", checkState);
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
} else {
ok(editor.popup._panel.state == "open" || editor.popup._panel.state == "showing", "Popup is open");
is(editor.popup.getItems().length, total, "Number of suggestions match");
is(editor.popup.selectedIndex, index, "Correct item is selected");
}
EventUtils.synthesizeKey(key, modifiers, ruleViewWindow);
}
function checkState(event) {
executeSoon(() => {
info("After keypress for state " + state);
let [key, modifier, completion, index, total] = testData[state];
if (completion != null) {
is(editor.input.value, completion,
"Correct value is autocompleted for state " + state);
}
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
state);
}
else {
ok(editor.popup.isOpen, "Popup is open for state " + state);
is(editor.popup.getItems().length, total,
"Number of suggestions match for state " + state);
is(editor.popup.selectedIndex, index,
"Correct item is selected for state " + state);
}
checkStateAndMoveOn(state + 1);
});
}
function finishUp()
{
brace = doc = inspector = editor = ruleViewWindow = state = 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;
doc.title = "Rule View Test";
waitForFocus(openRuleView, content);
}, true);
content.location = "data:text/html,<h1 style='color: red'>Filename: " +
"browser_bug894376_css_value_completion_existing_property_value_pair.js</h1>";
}

Просмотреть файл

@ -1,17 +1,12 @@
/* 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/ */
// Test that CSS property names are autocompleted and cycled correctly.
"use strict";
const MAX_ENTRIES = 10;
// Test that CSS property names and values are autocompleted and cycled correctly
// when editing new properties in the rule view
let doc;
let inspector;
let ruleViewWindow;
let editor;
let state;
let brace;
// format :
// [
// what key to press,
@ -42,107 +37,67 @@ let testData = [
["!", {}, "royalblue !important", 0, 0],
["VK_ESCAPE", {}, null, -1, 0]
];
function openRuleView() {
var target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
inspector.sidebar.select("ruleview");
// Highlight a node.
let node = content.document.getElementsByTagName("h1")[0];
inspector.selection.setNode(node);
let TEST_URL = "data:text/html,<h1 style='border: 1px solid red'>Filename:"+
" browser_bug894376_css_value_completion_new_property_value_pair.js</h1>";
inspector.once("inspector-updated", testCompletion);
});
}
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
function testCompletion() {
ruleViewWindow = inspector.sidebar.getWindowForTab("ruleview");
brace = ruleViewWindow.document.querySelector(".ruleview-ruleclose");
info("Selecting the test node");
yield selectNode("h1", inspector);
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
editor = aEditor;
checkStateAndMoveOn(0);
});
info("Focusing a new css property editable property");
let brace = view.doc.querySelectorAll(".ruleview-ruleclose")[0];
let editor = yield focusEditableField(brace);
brace.click();
}
function checkStateAndMoveOn(index) {
if (index == testData.length) {
finishUp();
return;
info("Starting to test for css property completion");
for (let i = 0; i < testData.length; i ++) {
// Re-define the editor at each iteration, because the focus may have moved
// from property to value and back
editor = inplaceEditor(view.doc.activeElement);
yield testCompletion(testData[i], editor, view);
}
});
let [key, modifiers] = testData[index];
state = index;
function* testCompletion([key, modifiers, completion, index, total], editor, view) {
info("Pressing key " + key);
info("Expecting " + completion + ", " + index + ", " + total);
let onKeyPress;
info("pressing key " + key + " to get result: [" + testData[index].slice(2) +
"] for state " + state);
if (/tab/ig.test(key)) {
info("waiting for the editor to get focused");
waitForEditorFocus(brace.parentNode, function onNewElement(aEditor) {
info("editor focused : " + aEditor.input);
editor = aEditor;
checkState();
});
info("Waiting for the new property or value editor to get focused");
let brace = view.doc.querySelector(".ruleview-ruleclose");
onKeyPress = once(brace.parentNode, "focus", true);
} else if (/(right|back_space|escape|return)/ig.test(key) ||
(modifiers.accelKey || modifiers.ctrlKey)) {
info("Adding event listener for right|escape|back_space|return keys");
onKeyPress = once(editor.input, "keypress");
} else {
info("Waiting for after-suggest event on the editor");
onKeyPress = editor.once("after-suggest");
}
else if (/(right|back_space|escape|return)/ig.test(key) ||
(modifiers.accelKey || modifiers.ctrlKey)) {
info("added event listener for right|escape|back_space|return keys");
editor.input.addEventListener("keypress", function onKeypress() {
if (editor.input) {
editor.input.removeEventListener("keypress", onKeypress);
}
info("inside event listener");
checkState();
});
info("Synthesizing key " + key + ", modifiers: " + Object.keys(modifiers));
EventUtils.synthesizeKey(key, modifiers, view.doc.defaultView);
yield onKeyPress;
yield wait(1); // Equivalent of executeSoon
info("Checking the state");
if (completion != null) {
// The key might have been a TAB or shift-TAB, in which case the editor will
// be a new one
editor = inplaceEditor(view.doc.activeElement);
is(editor.input.value, completion, "Correct value is autocompleted");
}
else {
editor.once("after-suggest", checkState);
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed");
} else {
ok(editor.popup._panel.state == "open" || editor.popup._panel.state == "showing", "Popup is open");
is(editor.popup.getItems().length, total, "Number of suggestions match");
is(editor.popup.selectedIndex, index, "Correct item is selected");
}
EventUtils.synthesizeKey(key, modifiers, ruleViewWindow);
}
function checkState(event) {
executeSoon(() => {
info("After keypress for state " + state);
let [key, modifier, completion, index, total] = testData[state];
if (completion != null) {
is(editor.input.value, completion,
"Correct value is autocompleted for state " + state);
}
if (total == 0) {
ok(!(editor.popup && editor.popup.isOpen), "Popup is closed for state " +
state);
}
else {
ok(editor.popup.isOpen, "Popup is open for state " + state);
is(editor.popup.getItems().length, total,
"Number of suggestions match for state " + state);
is(editor.popup.selectedIndex, index,
"Correct item is selected for state " + state);
}
checkStateAndMoveOn(state + 1);
});
}
function finishUp() {
brace = doc = inspector = editor = ruleViewWindow = state = 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;
doc.title = "Rule View Test";
waitForFocus(openRuleView, content);
}, true);
content.location = "data:text/html,<h1 style='border: 1px solid red'>Filename:"+
" browser_bug894376_css_value_completion_new_property_value_pair.js</h1>";
}

Просмотреть файл

@ -2,12 +2,12 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let doc;
let inspector;
let view;
let viewDoc;
"use strict";
const DOCUMENT_URL = "data:text/html," + encodeURIComponent([
// Test that the computed view properties can be expanded and collapsed with
// either the twisty or by dbl-clicking on the container
const TEST_URL = "data:text/html," + encodeURIComponent([
'<html>' +
'<head>' +
' <title>Computed view toggling test</title>',
@ -22,104 +22,87 @@ const DOCUMENT_URL = "data:text/html," + encodeURIComponent([
'</html>'
].join("\n"));
function test()
{
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openComputedView();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee,
true);
doc = content.document;
waitForFocus(function () { openComputedView(startTests); }, content);
}, true);
info("Selecting the test node");
yield selectNode("h1", inspector);
content.location = DOCUMENT_URL;
}
yield testExpandOnTwistyClick(view, inspector);
yield testCollapseOnTwistyClick(view, inspector);
yield testExpandOnDblClick(view, inspector);
yield testCollapseOnDblClick(view, inspector);
});
function startTests(aInspector, aview)
{
inspector = aInspector;
view = aview;
viewDoc = view.styleDocument;
function* testExpandOnTwistyClick({styleDocument, styleWindow}, inspector) {
info("Testing that a property expands on twisty click");
testExpandOnTwistyClick();
}
function endTests()
{
doc = inspector = view = viewDoc = null;
gBrowser.removeCurrentTab();
finish();
}
function testExpandOnTwistyClick()
{
let h1 = doc.querySelector("h1");
ok(h1, "H1 exists");
inspector.selection.setNode(h1);
inspector.once("inspector-updated", () => {
// Get the first twisty
let twisty = viewDoc.querySelector(".expandable");
ok(twisty, "Twisty found");
// Click and check whether it's been expanded
inspector.once("computed-view-property-expanded", () => {
// Expanded means the matchedselectors div is not empty
let div = viewDoc.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length > 0, "Matched selectors are expanded on twisty click");
testCollapseOnTwistyClick();
});
twisty.click();
});
}
function testCollapseOnTwistyClick() {
// Get the same first twisty again
let twisty = viewDoc.querySelector(".expandable");
info("Getting twisty element");
let twisty = styleDocument.querySelector(".expandable");
ok(twisty, "Twisty found");
// Click and check whether matched selectors are collapsed now
inspector.once("computed-view-property-collapsed", () => {
// Collapsed means the matchedselectors div is empty
let div = viewDoc.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length === 0, "Matched selectors are collapsed on twisty click");
testExpandOnDblClick();
});
let onExpand = inspector.once("computed-view-property-expanded");
info("Clicking on the twisty element");
twisty.click();
yield onExpand;
// Expanded means the matchedselectors div is not empty
let div = styleDocument.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length > 0, "Matched selectors are expanded on twisty click");
}
function testExpandOnDblClick()
{
// Get the computed rule container, not the twisty this time
let container = viewDoc.querySelector(".property-view");
function* testCollapseOnTwistyClick({styleDocument, styleWindow}, inspector) {
info("Testing that a property collapses on twisty click");
// Dblclick on it and check if it expands the matched selectors
inspector.once("computed-view-property-expanded", () => {
// Expanded means the matchedselectors div is not empty
let div = viewDoc.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length > 0, "Matched selectors are expanded on dblclick");
info("Getting twisty element");
let twisty = styleDocument.querySelector(".expandable");
ok(twisty, "Twisty found");
testCollapseOnDblClick();
});
EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, view.styleWindow);
let onCollapse = inspector.once("computed-view-property-collapsed");
info("Clicking on the twisty element");
twisty.click();
yield onCollapse;
// Collapsed means the matchedselectors div is empty
let div = styleDocument.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length === 0, "Matched selectors are collapsed on twisty click");
}
function testCollapseOnDblClick()
{
// Get the computed rule container, not the twisty this time
let container = viewDoc.querySelector(".property-view");
function* testExpandOnDblClick({styleDocument, styleWindow}, inspector) {
info("Testing that a property expands on container dbl-click");
// Dblclick on it and check if it expands the matched selectors
inspector.once("computed-view-property-collapsed", () => {
// Collapsed means the matchedselectors div is empty
let div = viewDoc.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length === 0, "Matched selectors are collapsed on dblclick");
info("Getting computed property container");
let container = styleDocument.querySelector(".property-view");
ok(container, "Container found");
endTests();
});
EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, view.styleWindow);
let onExpand = inspector.once("computed-view-property-expanded");
info("Dbl-clicking on the container");
EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, styleWindow);
yield onExpand;
// Expanded means the matchedselectors div is not empty
let div = styleDocument.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length > 0, "Matched selectors are expanded on dblclick");
}
function* testCollapseOnDblClick({styleDocument, styleWindow}, inspector) {
info("Testing that a property collapses on container dbl-click");
info("Getting computed property container");
let container = styleDocument.querySelector(".property-view");
ok(container, "Container found");
let onCollapse = inspector.once("computed-view-property-collapsed");
info("Dbl-clicking on the container");
EventUtils.synthesizeMouseAtCenter(container, {clickCount: 2}, styleWindow);
yield onCollapse;
// Collapsed means the matchedselectors div is empty
let div = styleDocument.querySelector(".property-content .matchedselectors");
ok(div.childNodes.length === 0, "Matched selectors are collapsed on dblclick");
}

Просмотреть файл

@ -1,17 +1,12 @@
/* 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 that changing a color in a gradient css declaration using the tooltip
// color picker works
let {gDevTools} = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
let contentDoc;
let contentWin;
let inspector;
let ruleView;
const PAGE_CONTENT = [
'<style type="text/css">',
' body {',
@ -21,48 +16,24 @@ const PAGE_CONTENT = [
'Updating a gradient declaration with the color picker tooltip'
].join("\n");
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html,rule view color picker tooltip test");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
contentWin = contentDoc.defaultView;
waitForFocus(createDocument, content);
}, true);
info("Creating the test document");
content.document.body.innerHTML = PAGE_CONTENT;
content.location = "data:text/html,rule view color picker tooltip test";
}
info("Opening the rule-view")
let {toolbox, inspector, view} = yield openRuleView();
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
info("Testing that the colors in gradient properties are parsed correctly");
testColorParsing(view);
openRuleView((aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
startTests();
});
}
info("Testing that changing one of the colors of a gradient property works");
yield testPickingNewColor(view);
});
function startTests() {
inspector.selection.setNode(contentDoc.body);
inspector.once("inspector-updated", testColorParsing);
}
function endTests() {
executeSoon(function() {
gDevTools.once("toolbox-destroyed", () => {
contentDoc = contentWin = inspector = ruleView = null;
gBrowser.removeCurrentTab();
finish();
});
inspector._toolbox.destroy();
});
}
function testColorParsing() {
let ruleEl = getRuleViewProperty("background-image");
function testColorParsing(view) {
let ruleEl = getRuleViewProperty(view, "body", "background-image");
ok(ruleEl, "The background-image gradient declaration was found");
let swatchEls = ruleEl.valueSpan.querySelectorAll(".ruleview-colorswatch");
@ -77,59 +48,29 @@ function testColorParsing() {
for (let i = 0; i < colors.length; i ++) {
is(colorEls[i].textContent, colors[i], "The right color value was found");
}
testPickingNewColor();
}
function testPickingNewColor() {
function* testPickingNewColor(view) {
// Grab the first color swatch and color in the gradient
let ruleEl = getRuleViewProperty("background-image");
let ruleEl = getRuleViewProperty(view, "body", "background-image");
let swatchEl = ruleEl.valueSpan.querySelector(".ruleview-colorswatch");
let colorEl = ruleEl.valueSpan.querySelector(".ruleview-color");
// Get the color picker tooltip
let cPicker = ruleView.colorPicker;
cPicker.tooltip.once("shown", () => {
simulateColorChange(cPicker, [1, 1, 1, 1]);
executeSoon(() => {
is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
"The color swatch's background was updated");
is(colorEl.textContent, "rgba(1, 1, 1, 1)",
"The color text was updated");
is(content.getComputedStyle(content.document.body).backgroundImage,
"linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
"The gradient has been updated correctly");
cPicker.hide();
endTests();
});
});
info("Getting the color picker tooltip and clicking on the swatch to show it");
let cPicker = view.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatchEl.click();
}
yield onShown;
function simulateColorChange(colorPicker, newRgba) {
// 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
colorPicker.spectrum.then(spectrum => {
spectrum.rgb = newRgba;
spectrum.updateUI();
spectrum.onChange();
});
}
yield simulateColorPickerChange(cPicker, [1, 1, 1, 1]);
function getRuleViewProperty(name) {
let prop = null;
[].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
let nameSpan = property.querySelector(".ruleview-propertyname");
let valueSpan = property.querySelector(".ruleview-propertyvalue");
is(swatchEl.style.backgroundColor, "rgb(1, 1, 1)",
"The color swatch's background was updated");
is(colorEl.textContent, "rgba(1, 1, 1, 1)",
"The color text was updated");
is(content.getComputedStyle(content.document.body).backgroundImage,
"linear-gradient(to left, rgb(255, 0, 102) 25%, rgb(51, 51, 51) 95%, rgb(0, 0, 0) 100%)",
"The gradient has been updated correctly");
if (nameSpan.textContent === name) {
prop = {nameSpan: nameSpan, valueSpan: valueSpan};
}
});
return prop;
cPicker.hide();
}

Просмотреть файл

@ -2,102 +2,69 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that user set style properties can be changed from the markup-view and
// don't survive page reload
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let promise = devtools.require("sdk/core/promise");
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
let TEST_PAGE = [
"data:text/html,",
"<p id='id1' style='width:200px;'>element 1</p>",
"<p id='id2' style='width:100px;'>element 2</p>"
].join("");
let doc;
let inspector;
let ruleView;
let markupView;
let test = asyncTest(function*() {
yield addTab(TEST_PAGE);
let {toolbox, inspector, view} = yield openRuleView();
function test() {
waitForExplicitFinish();
yield selectNode("#id1", inspector);
yield modifyRuleViewWidth("300px", view, inspector);
assertRuleAndMarkupViewWidth("id1", "300px", view, inspector);
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(() => {
openRuleView((aInspector, aView) => {
inspector = aInspector;
ruleView = aView;
markupView = inspector.markup;
yield selectNode("#id2", inspector);
assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
yield modifyRuleViewWidth("50px", view, inspector);
assertRuleAndMarkupViewWidth("id2", "50px", view, inspector);
Task.spawn(function() {
yield selectElement("id1");
yield modifyRuleViewWidth("300px");
assertRuleAndMarkupViewWidth("id1", "300px");
yield selectElement("id2");
assertRuleAndMarkupViewWidth("id2", "100px");
yield modifyRuleViewWidth("50px");
assertRuleAndMarkupViewWidth("id2", "50px");
yield reloadPage(inspector);
yield reloadPage();
yield selectElement("id1");
assertRuleAndMarkupViewWidth("id1", "200px");
yield selectElement("id2");
assertRuleAndMarkupViewWidth("id2", "100px");
yield selectNode("#id1", inspector);
assertRuleAndMarkupViewWidth("id1", "200px", view, inspector);
yield selectNode("#id2", inspector);
assertRuleAndMarkupViewWidth("id2", "100px", view, inspector);
});
finishTest();
}).then(null, Cu.reportError);
});
}, content);
}, true);
content.location = TEST_PAGE;
}
function finishTest() {
doc = inspector = ruleView = markupView = null;
gBrowser.removeCurrentTab();
finish();
}
function selectElement(id) {
let deferred = promise.defer();
inspector.selection.setNode(doc.getElementById(id));
inspector.once("inspector-updated", deferred.resolve);
return deferred.promise;
}
function getStyleRule() {
function getStyleRule(ruleView) {
return ruleView.doc.querySelector(".ruleview-rule");
}
function modifyRuleViewWidth(value) {
let deferred = promise.defer();
function* modifyRuleViewWidth(value, ruleView, inspector) {
info("Getting the property value element");
let valueSpan = getStyleRule(ruleView).querySelector(".ruleview-propertyvalue");
let valueSpan = getStyleRule().querySelector(".ruleview-propertyvalue");
waitForEditorFocus(valueSpan.parentNode, () => {
let editor = inplaceEditor(valueSpan);
editor.input.value = value;
waitForEditorBlur(editor, () => {
// Changing the style will refresh the markup view, let's wait for that
inspector.once("markupmutation", () => {
waitForEditorBlur({input: ruleView.doc.activeElement}, deferred.resolve);
EventUtils.sendKey("escape");
});
});
EventUtils.sendKey("return");
});
valueSpan.click();
info("Focusing the property value to set it to edit mode");
let editor = yield focusEditableField(valueSpan.parentNode);
return deferred.promise;
ok(editor.input, "The inplace-editor field is ready");
info("Setting the new value");
editor.input.value = value;
info("Pressing return and waiting for the field to blur and for the markup-view to show the mutation");
let onBlur = once(editor.input, "blur", true);
let onMutation = inspector.once("markupmutation");
EventUtils.sendKey("return");
yield onBlur;
yield onMutation;
info("Escaping out of the new property field that has been created after the value was edited");
let onNewFieldBlur = once(ruleView.doc.activeElement, "blur", true);
EventUtils.sendKey("escape");
yield onNewFieldBlur;
}
function getContainerStyleAttrValue(id) {
let front = markupView.walker.frontForRawNode(doc.getElementById(id));
let container = markupView.getContainer(front);
function getContainerStyleAttrValue(id, {markup}) {
let front = markup.walker.frontForRawNode(content.document.getElementById(id));
let container = markup.getContainer(front);
let attrIndex = 0;
for (let attrName of container.elt.querySelectorAll(".attr-name")) {
@ -108,21 +75,16 @@ function getContainerStyleAttrValue(id) {
}
}
function assertRuleAndMarkupViewWidth(id, value) {
let valueSpan = getStyleRule().querySelector(".ruleview-propertyvalue");
function assertRuleAndMarkupViewWidth(id, value, ruleView, inspector) {
let valueSpan = getStyleRule(ruleView).querySelector(".ruleview-propertyvalue");
is(valueSpan.textContent, value, "Rule-view style width is " + value + " as expected");
let attr = getContainerStyleAttrValue(id);
let attr = getContainerStyleAttrValue(id, inspector);
is(attr.textContent.replace(/\s/g, ""), "width:" + value + ";", "Markup-view style attribute width is " + value);
}
function reloadPage() {
let deferred = promise.defer();
inspector.once("new-root", () => {
doc = content.document;
markupView = inspector.markup;
markupView._waitForChildren().then(deferred.resolve);
});
function reloadPage(inspector) {
let onNewRoot = inspector.once("new-root");
content.location.reload();
return deferred.promise;
return onNewRoot.then(inspector.markup._waitForChildren);
}

Просмотреть файл

@ -1,81 +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/ */
let contentDoc;
let inspector;
let ruleView;
let computedView;
"use strict";
const PAGE_CONTENT = '<div class="one">el 1</div><div class="two">el 2</div>';
// Test that if a tooltip is visible when a new selection is made, it closes
function test() {
waitForExplicitFinish();
let test = asyncTest(function*() {
yield addTab("data:text/html,<div class='one'>el 1</div><div class='two'>el 2</div>");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function(evt) {
gBrowser.selectedBrowser.removeEventListener(evt.type, arguments.callee, true);
contentDoc = content.document;
waitForFocus(createDocument, content);
}, true);
let {toolbox, inspector, view} = yield openRuleView();
yield selectNode(".one", inspector);
content.location = "data:text/html,rule/computed views tooltip hiding test";
}
function createDocument() {
contentDoc.body.innerHTML = PAGE_CONTENT;
openView("ruleview", (aInspector, aRuleView) => {
inspector = aInspector;
ruleView = aRuleView;
openView("computedview", (_, aComputedView) => {
computedView = aComputedView;
startTests();
});
});
}
function startTests() {
inspector.selection.setNode(contentDoc.querySelector(".one"));
inspector.once("inspector-updated", testRuleView);
}
function endTests() {
contentDoc = inspector = ruleView = computedView = null;
gBrowser.removeCurrentTab();
finish();
}
function testRuleView() {
info("Testing rule view tooltip closes on new selection");
yield testRuleView(view, inspector);
// Show the rule view tooltip
let tooltip = ruleView.previewTooltip;
tooltip.show();
tooltip.once("shown", () => {
// Select a new node and assert that the tooltip closes
tooltip.once("hidden", () => {
ok(true, "Rule view tooltip closed after a new node got selected");
inspector.once("inspector-updated", testComputedView);
});
inspector.selection.setNode(contentDoc.querySelector(".two"));
});
}
function testComputedView() {
info("Testing computed view tooltip closes on new selection");
let {view} = yield openComputedView();
yield testComputedView(view, inspector);
});
inspector.sidebar.select("computedview");
// Show the computed view tooltip
let tooltip = computedView.tooltip;
function* testRuleView(ruleView, inspector) {
info("Showing the tooltip");
let tooltip = ruleView.previewTooltip;
let onShown = tooltip.once("shown");
tooltip.show();
tooltip.once("shown", () => {
// Select a new node and assert that the tooltip closes
tooltip.once("hidden", () => {
ok(true, "Computed view tooltip closed after a new node got selected");
inspector.once("inspector-updated", endTests);
});
inspector.selection.setNode(contentDoc.querySelector(".one"));
});
yield onShown;
info("Selecting a new node");
let onHidden = tooltip.once("hidden");
yield selectNode(".two", inspector);
ok(true, "Rule view tooltip closed after a new node got selected");
}
function* testComputedView(computedView, inspector) {
info("Showing the tooltip");
let tooltip = computedView.tooltip;
let onShown = tooltip.once("shown");
tooltip.show();
yield onShown;
info("Selecting a new node");
let onHidden = tooltip.once("hidden");
yield selectNode(".one", inspector);
ok(true, "Computed view tooltip closed after a new node got selected");
}

Просмотреть файл

@ -1,12 +1,11 @@
/* Any copyright", " is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.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/ */
"use strict";
// Tests that the rule-view displays correctly on MathML elements
waitForExplicitFinish();
const TEST_URL = [
"data:text/html,",
"<div>",
@ -26,45 +25,30 @@ const TEST_URL = [
"</div>"
].join("");
function test() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(runTests, content);
}, true);
content.location = TEST_URL;
}
let test = asyncTest(function*() {
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
function runTests() {
openRuleView((inspector, ruleView) => {
Task.spawn(function() {
info("Select the DIV node and verify the rule-view shows rules");
yield selectNode("div", inspector);
ok(ruleView.element.querySelectorAll(".ruleview-rule").length,
"The rule-view shows rules for the div element");
info("Select the DIV node and verify the rule-view shows rules");
yield selectNode("div", inspector);
ok(view.element.querySelectorAll(".ruleview-rule").length,
"The rule-view shows rules for the div element");
info("Select various MathML nodes and verify the rule-view is empty");
yield selectNode("math", inspector);
ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the math element");
info("Select various MathML nodes and verify the rule-view is empty");
yield selectNode("math", inspector);
ok(!view.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the math element");
yield selectNode("msubsup", inspector);
ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the msubsup element");
yield selectNode("msubsup", inspector);
ok(!view.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the msubsup element");
yield selectNode("mn", inspector);
ok(!ruleView.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the mn element");
yield selectNode("mn", inspector);
ok(!view.element.querySelectorAll(".ruleview-rule").length,
"The rule-view is empty for the mn element");
info("Select again the DIV node and verify the rule-view shows rules");
yield selectNode("div", inspector);
ok(ruleView.element.querySelectorAll(".ruleview-rule").length,
"The rule-view shows rules for the div element");
}).then(null, ok.bind(null, false)).then(finishUp);
});
}
function finishUp() {
gBrowser.removeCurrentTab();
finish();
}
info("Select again the DIV node and verify the rule-view shows rules");
yield selectNode("div", inspector);
ok(view.element.querySelectorAll(".ruleview-rule").length,
"The rule-view shows rules for the div element");
});

Просмотреть файл

@ -2,98 +2,68 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Tests that CSS specificity is properly calculated.
const DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"]
.getService(Ci.inIDOMUtils);
const TEST_DATA = [
{text: "*", expected: 0},
{text: "LI", expected: 1},
{text: "UL LI", expected: 2},
{text: "UL OL + LI", expected: 3},
{text: "H1 + [REL=\"up\"]", expected: 257},
{text: "UL OL LI.red", expected: 259},
{text: "LI.red.level", expected: 513},
{text: ".red .level", expected: 512},
{text: "#x34y", expected: 65536},
{text: "#s12:not(FOO)", expected: 65537},
{text: "body#home div#warning p.message", expected: 131331},
{text: "* body#home div#warning p.message", expected: 131331},
{text: "#footer :not(nav) li", expected: 65538},
{text: "bar:nth-child(n)", expected: 257},
{text: "li::-moz-list-number", expected: 1},
{text: "a:hover", expected: 257}
];
function createDocument()
{
let doc = content.document;
doc.body.innerHTML = getStylesheetText();
doc.title = "Computed view specificity test";
runTests(doc);
}
let test = asyncTest(function*() {
yield addTab("data:text/html,Computed view specificity test");
createDocument();
function runTests(doc) {
info("Creating a CssLogic instance");
let cssLogic = new CssLogic();
cssLogic.highlight(doc.body);
let tests = getTests();
cssLogic.highlight(content.document.body);
let cssSheet = cssLogic.sheets[0];
let cssRule = cssSheet.domSheet.cssRules[0];
let selectors = CssLogic.getSelectors(cssRule);
info("Iterating over the test selectors")
for (let i = 0; i < selectors.length; i++) {
let selectorText = selectors[i];
info("Testing selector " + selectorText);
let selector = new CssSelector(cssRule, selectorText, i);
let expected = getExpectedSpecificity(selectorText);
let specificity = DOMUtils.getSpecificity(selector.cssRule,
selector.selectorIndex)
is(specificity, expected,
'selector "' + selectorText + '" has a specificity of ' + expected);
'Selector "' + selectorText + '" has a specificity of ' + expected);
}
finishUp();
}
});
function getExpectedSpecificity(selectorText) {
let tests = getTests();
for (let test of tests) {
if (test.text == selectorText) {
return test.expected;
}
}
}
function getTests() {
return [
{text: "*", expected: 0},
{text: "LI", expected: 1},
{text: "UL LI", expected: 2},
{text: "UL OL + LI", expected: 3},
{text: "H1 + [REL=\"up\"]", expected: 257},
{text: "UL OL LI.red", expected: 259},
{text: "LI.red.level", expected: 513},
{text: ".red .level", expected: 512},
{text: "#x34y", expected: 65536},
{text: "#s12:not(FOO)", expected: 65537},
{text: "body#home div#warning p.message", expected: 131331},
{text: "* body#home div#warning p.message", expected: 131331},
{text: "#footer :not(nav) li", expected: 65538},
{text: "bar:nth-child(n)", expected: 257},
{text: "li::-moz-list-number", expected: 1},
{text: "a:hover", expected: 257},
];
function createDocument() {
let doc = content.document;
doc.body.innerHTML = getStylesheetText();
doc.title = "Computed view specificity test";
}
function getStylesheetText() {
let tests = getTests();
let text = "";
tests.forEach(function(test) {
if (text.length > 0) {
text += ",";
}
text += test.text;
});
info("Creating the test stylesheet");
let text = TEST_DATA.map(i=>i.text).join(",");
return '<style type="text/css">' + text + " {color:red;}</style>";
}
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;
}

Просмотреть файл

@ -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 = "<div style='color:blue;'></div>";
let test = asyncTest(function*() {
yield addTab("data:text/html,<div style='color:blue;'></div>");
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;
}

Просмотреть файл

@ -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(
'</body>',
'</html>'].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");
}

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
content.document.body.innerHTML = '<style type="text/css"> ' +
'span { font-variant: small-caps; color: #000000; } ' +
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
@ -38,57 +25,38 @@ function createDocument()
'<p id="closing">more text</p>\n' +
'<p>even more text</p>' +
'</div>';
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");
});

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
let test = asyncTest(function*() {
yield addTab("data:text/html,computed view copy test");
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
'span { font-variant: small-caps; color: #000000; } ' +
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA">\n' +
@ -30,132 +30,89 @@ function createDocument()
'<p id="closing">more text</p>\n' +
'<p>even more text</p>' +
'</div>';
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));
}

Просмотреть файл

@ -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
);
}

Просмотреть файл

@ -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 = '<div style="margin-left:10px; font-size: 5px"><div id="innerdiv">Inner div</div></div>';
doc.title = "Style Inspector Inheritance Test";
content.document.body.innerHTML = '<div style="margin-left:10px; font-size: 5px"><div id="innerdiv">Inner div</div></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";
}
});

Просмотреть файл

@ -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(
['<html>' +
@ -50,97 +44,81 @@ const DOCUMENT_URL = "data:text/html,"+encodeURIComponent(
'</body>',
'</html>'].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;
}

Просмотреть файл

@ -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");
}
}

Просмотреть файл

@ -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 = '<div id="testid">Styled Node</div>';
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 = '<div id="testid">Styled Node</div>';
}
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);
}
}

Просмотреть файл

@ -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");
}

Просмотреть файл

@ -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");
}

Просмотреть файл

@ -6,8 +6,6 @@
// Test that color pickers appear when clicking on color swatches
let ruleView, swatches;
const PAGE_CONTENT = [
'<style type="text/css">',
' body {',
@ -20,58 +18,37 @@ 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, view) => {
ruleView = view;
inspector.once("inspector-updated", () => {
let cSwatch = getRuleViewProperty("color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
let bSwatch = getRuleViewProperty("border", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
swatches = [cSwatch, bgSwatch, bSwatch];
let cSwatch = getRuleViewProperty(view, "body", "color").valueSpan
.querySelector(".ruleview-colorswatch");
let bgSwatch = getRuleViewProperty(view, "body", "background-color").valueSpan
.querySelector(".ruleview-colorswatch");
let bSwatch = getRuleViewProperty(view, "body", "border").valueSpan
.querySelector(".ruleview-colorswatch");
testColorPickerAppearsOnColorSwatchClick();
});
});
}
for (let swatch of [cSwatch, bgSwatch, bSwatch]) {
info("Testing that the colorpicker appears colorswatch click");
yield testColorPickerAppearsOnColorSwatchClick(view, swatch);
}
});
function* testColorPickerAppearsOnColorSwatchClick(view, swatch) {
let cPicker = view.colorPicker;
ok(cPicker, "The rule-view has the expected colorPicker property");
function testColorPickerAppearsOnColorSwatchClick() {
let cPicker = ruleView.colorPicker;
let cPickerPanel = cPicker.tooltip.panel;
ok(cPickerPanel, "The XUL panel for the color picker exists");
function clickOnSwatch(index, cb) {
if (index === swatches.length) {
return cb();
}
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
let swatch = swatches[index];
cPicker.tooltip.once("shown", () => {
ok(true, "The color picker was shown on click of the color swatch");
ok(!inplaceEditor(swatch.parentNode),
"The inplace editor wasn't shown as a result of the color swatch click");
cPicker.hide();
clickOnSwatch(index + 1, cb);
});
swatch.click();
}
clickOnSwatch(0, () => {
ruleView = swatches = null;
finish();
});
ok(true, "The color picker was shown on click of the color swatch");
ok(!inplaceEditor(swatch.parentNode),
"The inplace editor wasn't shown as a result of the color swatch click");
cPicker.hide();
}

Просмотреть файл

@ -15,59 +15,45 @@ 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 swatch = getRuleViewProperty("border", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
testPressingEnterCommitsChanges(swatch, ruleView);
});
let swatch = getRuleViewProperty(view, "body" , "border").valueSpan
.querySelector(".ruleview-colorswatch");
yield testPressingEnterCommitsChanges(swatch, view);
});
function* testPressingEnterCommitsChanges(swatch, ruleView) {
let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
yield simulateColorPickerChange(cPicker, [0, 255, 0, .5], {
element: content.document.body,
name: "borderLeftColor",
value: "rgba(0, 255, 0, 0.5)"
});
}
function testPressingEnterCommitsChanges(swatch, ruleView) {
Task.spawn(function*() {
let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
yield simulateColorChange(cPicker, [0, 255, 0, .5], {
element: content.document.body,
name: "borderLeftColor",
value: "rgba(0, 255, 0, 0.5)"
});
is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
"The color swatch's background was updated");
is(getRuleViewProperty("border", ruleView).valueSpan.textContent,
"2em solid rgba(0, 255, 0, 0.5)",
"The text of the border css property was updated");;
let spectrum = yield cPicker.spectrum;
let onHidden = cPicker.tooltip.once("hidden");
EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
yield onHidden;
is(content.getComputedStyle(content.document.body).borderLeftColor,
"rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
"The color swatch's background was kept after RETURN");
is(getRuleViewProperty("border", ruleView).valueSpan.textContent,
"2em solid rgba(0, 255, 0, 0.5)",
"The text of the border css property was kept after RETURN");
}).then(finish);
is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
"The color swatch's background was updated");
is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
"2em solid rgba(0, 255, 0, 0.5)",
"The text of the border css property was updated");;
let spectrum = yield cPicker.spectrum;
let onHidden = cPicker.tooltip.once("hidden");
EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
yield onHidden;
is(content.getComputedStyle(content.document.body).borderLeftColor,
"rgba(0, 255, 0, 0.5)", "The element's border was kept after RETURN");
is(swatch.style.backgroundColor, "rgba(0, 255, 0, 0.5)",
"The color swatch's background was kept after RETURN");
is(getRuleViewProperty(ruleView, "body", "border").valueSpan.textContent,
"2em solid rgba(0, 255, 0, 0.5)",
"The text of the border css property was kept after RETURN");
}

Просмотреть файл

@ -7,8 +7,6 @@
// Test that the color picker tooltip hides when an image or transform
// tooltip appears
let ruleView, swatches;
const PAGE_CONTENT = [
'<style type="text/css">',
' body {',
@ -22,75 +20,49 @@ 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, view) => {
ruleView = view;
inspector.once("inspector-updated", () => {
let cSwatch = getRuleViewProperty("color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
let bgSwatch = getRuleViewProperty("background-color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
let bSwatch = getRuleViewProperty("border", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
swatches = [cSwatch, bgSwatch, bSwatch];
let swatch = getRuleViewProperty(view, "body", "color").valueSpan
.querySelector(".ruleview-colorswatch");
testColorPickerHidesWhenImageTooltipAppears();
});
});
yield testColorPickerHidesWhenImageTooltipAppears(view, swatch);
yield testColorPickerHidesWhenTransformTooltipAppears(view, swatch);
});
function* testColorPickerHidesWhenImageTooltipAppears(view, swatch) {
let bgImageSpan = getRuleViewProperty(view, "body", "background-image").valueSpan;
let uriSpan = bgImageSpan.querySelector(".theme-link");
let tooltip = view.colorPicker.tooltip;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Now showing the image preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertHoverTooltipOn(view.previewTooltip, uriSpan);
yield onHidden;
ok(true, "The color picker closed when the image preview tooltip appeared");
}
function testColorPickerHidesWhenImageTooltipAppears() {
Task.spawn(function*() {
let swatch = swatches[0];
let bgImageSpan = getRuleViewProperty("background-image", ruleView).valueSpan;
let uriSpan = bgImageSpan.querySelector(".theme-link");
let tooltip = ruleView.colorPicker.tooltip;
function* testColorPickerHidesWhenTransformTooltipAppears(view, swatch) {
let transformSpan = getRuleViewProperty(view, "body", "transform").valueSpan;
let tooltip = view.colorPicker.tooltip;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Now showing the image preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertTooltipShownOn(ruleView.previewTooltip, uriSpan);
yield onHidden;
info("Now showing the transform preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertHoverTooltipOn(view.previewTooltip, transformSpan);
yield onHidden;
ok(true, "The color picker closed when the image preview tooltip appeared");
}).then(testColorPickerHidesWhenTransformTooltipAppears);
}
function testColorPickerHidesWhenTransformTooltipAppears() {
Task.spawn(function*() {
let swatch = swatches[0];
let transformSpan = getRuleViewProperty("transform", ruleView).valueSpan;
let tooltip = ruleView.colorPicker.tooltip;
info("Showing the color picker tooltip by clicking on the color swatch");
let onShown = tooltip.once("shown");
swatch.click();
yield onShown;
info("Now showing the transform preview tooltip to hide the color picker");
let onHidden = tooltip.once("hidden");
yield assertTooltipShownOn(ruleView.previewTooltip, transformSpan);
yield onHidden;
ok(true, "The color picker closed when the transform preview tooltip appeared");
}).then(() => {
swatches = ruleView = null;
finish();
});
ok(true, "The color picker closed when the transform preview tooltip appeared");
}

Просмотреть файл

@ -24,123 +24,103 @@ const PAGE_CONTENT = [
'<p>Testing the color picker tooltip!</p>'
].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", () => {
testSimpleMultipleColorChanges(inspector, ruleView);
yield testSimpleMultipleColorChanges(inspector, view);
yield testComplexMultipleColorChanges(inspector, view);
yield testOverriddenMultipleColorChanges(inspector, view);
});
function* testSimpleMultipleColorChanges(inspector, ruleView) {
yield selectNode("p", inspector);
info("Getting the <p> tag's color property");
let swatch = getRuleViewProperty(ruleView, "p", "color").valueSpan
.querySelector(".ruleview-colorswatch");
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
element: content.document.querySelector("p"),
name: "color",
value: computed
});
});
}
}
function testSimpleMultipleColorChanges(inspector, ruleView) {
Task.spawn(function*() {
yield selectNode("p", inspector);
function* testComplexMultipleColorChanges(inspector, ruleView) {
yield selectNode("body", inspector);
info("Getting the <p> tag's color property");
let swatch = getRuleViewSelectorProperty("p", "color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
info("Getting the <body> tag's color property");
let swatch = getRuleViewProperty(ruleView, "body", "background").valueSpan
.querySelector(".ruleview-colorswatch");
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorChange(picker, rgba, {
element: content.document.querySelector("p"),
name: "color",
value: computed
});
}
}).then(() => {
testComplexMultipleColorChanges(inspector, ruleView);
});
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
element: content.document.body,
name: "backgroundColor",
value: computed
});
}
info("Closing the color picker");
let onHidden = picker.tooltip.once("hidden");
picker.tooltip.hide();
yield onHidden;
}
function testComplexMultipleColorChanges(inspector, ruleView) {
Task.spawn(function*() {
yield selectNode("body", inspector);
function* testOverriddenMultipleColorChanges(inspector, ruleView) {
yield selectNode("p", inspector);
info("Getting the <body> tag's color property");
let swatch = getRuleViewSelectorProperty("body", "background", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
info("Getting the <body> tag's color property");
let swatch = getRuleViewProperty(ruleView, "body", "color").valueSpan
.querySelector(".ruleview-colorswatch");
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorChange(picker, rgba, {
element: content.document.body,
name: "backgroundColor",
value: computed
});
}
info("Closing the color picker");
let onHidden = picker.tooltip.once("hidden");
picker.tooltip.hide();
yield onHidden;
}).then(() => {
testOverriddenMultipleColorChanges(inspector, ruleView);
});
}
function testOverriddenMultipleColorChanges(inspector, ruleView) {
Task.spawn(function*() {
yield selectNode("p", inspector);
info("Getting the <body> tag's color property");
let swatch = getRuleViewSelectorProperty("body", "color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
info("Opening the color picker");
let picker = ruleView.colorPicker;
let onShown = picker.tooltip.once("shown");
swatch.click();
yield onShown;
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorChange(picker, rgba, {
element: content.document.body,
name: "color",
value: computed
});
is(content.getComputedStyle(content.document.querySelector("p")).color,
"rgb(200, 200, 200)", "The color of the P tag is still correct");
}
}).then(finish);
info("Changing the color several times");
let colors = [
{rgba: [0, 0, 0, 1], computed: "rgb(0, 0, 0)"},
{rgba: [100, 100, 100, 1], computed: "rgb(100, 100, 100)"},
{rgba: [200, 200, 200, 1], computed: "rgb(200, 200, 200)"}
];
for (let {rgba, computed} of colors) {
yield simulateColorPickerChange(picker, rgba, {
element: content.document.body,
name: "color",
value: computed
});
is(content.getComputedStyle(content.document.querySelector("p")).color,
"rgb(200, 200, 200)", "The color of the P tag is still correct");
}
}

Просмотреть файл

@ -15,59 +15,42 @@ 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 swatch = getRuleViewProperty("background-color", ruleView).valueSpan
.querySelector(".ruleview-colorswatch");
testPressingEscapeRevertsChanges(swatch, ruleView);
});
let swatch = getRuleViewProperty(view, "body", "background-color").valueSpan
.querySelector(".ruleview-colorswatch");
yield testPressingEscapeRevertsChanges(swatch, view);
});
function* testPressingEscapeRevertsChanges(swatch, ruleView) {
let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
yield simulateColorPickerChange(cPicker, [0, 0, 0, 1], {
element: content.document.body,
name: "backgroundColor",
value: "rgb(0, 0, 0)"
});
}
function testPressingEscapeRevertsChanges(swatch, ruleView) {
Task.spawn(function*() {
let cPicker = ruleView.colorPicker;
let onShown = cPicker.tooltip.once("shown");
swatch.click();
yield onShown;
yield simulateColorChange(cPicker, [0, 0, 0, 1], {
element: content.document.body,
name: "backgroundColor",
value: "rgb(0, 0, 0)"
});
is(swatch.style.backgroundColor, "rgb(0, 0, 0)",
"The color swatch's background was updated");
is(getRuleViewProperty("background-color", ruleView).valueSpan.textContent,
"rgba(0, 0, 0, 1)", "The text of the background-color css property was updated");
let spectrum = yield cPicker.spectrum;
// ESC out of the color picker
let onHidden = cPicker.tooltip.once("hidden");
EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
yield onHidden;
yield waitForSuccess({
validatorFn: () => {
return content.getComputedStyle(content.document.body).backgroundColor === "rgb(237, 237, 237)";
},
name: "The element's background-color was reverted"
});
}).then(finish);
is(swatch.style.backgroundColor, "rgb(0, 0, 0)",
"The color swatch's background was updated");
is(getRuleViewProperty(ruleView, "body", "background-color").valueSpan.textContent,
"rgba(0, 0, 0, 1)", "The text of the background-color css property was updated");
let spectrum = yield cPicker.spectrum;
// ESC out of the color picker
let onHidden = cPicker.tooltip.once("hidden");
EventUtils.sendKey("ESCAPE", spectrum.element.ownerDocument.defaultView);
yield onHidden;
yield waitForSuccess(() => {
return content.getComputedStyle(content.document.body).backgroundColor === "rgb(237, 237, 237)";
}, "The element's background-color was reverted");
}

Просмотреть файл

@ -6,8 +6,6 @@
// Test that color swatches are displayed next to colors in the rule-view
let ruleView;
const PAGE_CONTENT = [
'<style type="text/css">',
' body {',
@ -16,42 +14,42 @@ const PAGE_CONTENT = [
' background-image: url(chrome://global/skin/icons/warning-64.png);',
' border: 2em solid rgba(120, 120, 120, .5);',
' }',
' * {',
' color: blue;',
' box-shadow: inset 0 0 2px 20px red, inset 0 0 2px 40px blue;',
' }',
'</style>',
'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");
}
});

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
let test = asyncTest(function*() {
yield addTab("data:text/html,<p>rule view context menu test</p>");
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
'html { color: #000000; } ' +
'span { font-variant: small-caps; color: #000000; } ' +
'.nomatches {color: #ff0000;}</style> <div id="first" style="margin: 10em; ' +
@ -29,44 +31,32 @@ function createDocument()
'<p id="closing">more text</p>\n' +
'<p>even more text</p>' +
'</div>';
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,<p>rule view context menu test</p>";
info("Expected: " + escape(expectedPattern));
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 = '<div id="testid" class="testclass">Styled Node</div>';
let testElement = doc.getElementById("testid");
let TEST_URL = 'url("' + TEST_URL_ROOT + 'test-image.png")';
let PAGE_CONTENT = [
'<style type="text/css">',
' #testid {',
' background-color: blue;',
' }',
' .testclass {',
' background-color: green;',
' }',
'</style>',
'<div id="testid" class="testclass">Styled Node</div>'
].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");
}

Просмотреть файл

@ -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,<h1>Some header text</h1>");
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,<h1>Some header text</h1>";
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);
}

Просмотреть файл

@ -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 = '<div id="test2"><div id="test1">Styled Node</div></div>';
let styleNode = addStyle(content.document, style);
content.document.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
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 = '<div id="test2"><div id="test1">Styled Node</div></div>';
let styleNode = addStyle(content.document, style);
content.document.body.innerHTML = '<div id="test2"><div id="test1">Styled Node</div></div>';
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 = '<div id="test2" style="color: red"><div id="test1">Styled Node</div></div>';
function* elementStyleInherit(inspector, view) {
content.document.body.innerHTML = '<div id="test2" style="color: red"><div id="test1">Styled Node</div></div>';
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.");
}

Просмотреть файл

@ -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 = '<div id="testid">Styled Node</div><span>inline element</span>';
let testElement = getNode("#testid");
let styleNode = addStyle(doc, style);
doc.body.innerHTML = '<div id="testid">Styled Node</div><span>inline element</span>';
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);
}

Просмотреть файл

@ -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 = '<div id="testid">Styled Node</div>';
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 = '<div id="testid">Styled Node</div>';
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.");
});

Просмотреть файл

@ -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 = '<h1>Testing Multiple Properties</h1>';
// 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 = "<h1>Testing Multiple Properties</h1>";
/*
* 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");
}

Просмотреть файл

@ -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
);
}

Просмотреть файл

@ -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 = '<div id="testid" class="testclass">Styled Node</div>';
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 = '<div id="testid" class="testclass">Styled Node</div>';
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 = '<div id="testid" class="testclass">Styled Node</div>';
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 = '<div id="testid" class="testclass">Styled Node</div>';
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 = '<div id="testid" class="testclass">Styled Node</div>';
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");
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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 = "<div id='testid' class='testclass'>Styled Node</div>" +
"<div id='testid2'>Styled Node</div>";
let styleNode = addStyle(content.document, style);
content.document.body.innerHTML = "<div id='testid' class='testclass'>Styled Node</div>" +
"<div id='testid2'>Styled Node</div>";
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");
}
}

Просмотреть файл

@ -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 = '<div id="testid" class="testclass">Styled Node</div>';
let styleNode = addStyle(doc, style);
doc.body.innerHTML = '<div id="testid" class="testclass">Styled Node</div>';
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";
}

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
'.matches {color: #F00;}</style>' +
'<span id="matches" class="matches">Some styled text</span>' +
'</div>';
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";
}

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
'.matches {color: #F00;}</style>' +
'<span id="matches" class="matches">Some styled text</span>' +
'</div>';
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";
}

Просмотреть файл

@ -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");
}

Просмотреть файл

@ -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 = '<style type="text/css"> ' +
info("Creating the test document");
content.document.body.innerHTML = '<style type="text/css"> ' +
'.matches {color: #F00;}</style>' +
'<span id="matches" class="matches">Some styled text</span>';
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";
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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;
}