Bug 825410 - intermittent browser_inspector_pseudoclass_lock.js test failures; r=bgrins

This commit is contained in:
Patrick Brosset 2014-04-16 09:55:09 +02:00
Родитель a64f3ea049
Коммит b05a01e60c
6 изменённых файлов: 243 добавлений и 156 удалений

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

@ -36,14 +36,12 @@ function test()
// Make sure the body element is selected initially.
node = doc.querySelector("body");
inspector.once("inspector-updated", () => {
is(inspector.selection.node, node, "Body should be selected initially.");
node = doc.querySelector("h1")
inspector.once("inspector-updated", highlightHeaderNode);
let bc = inspector.breadcrumbs;
bc.nodeHierarchy[bc.currentIndex].button.focus();
EventUtils.synthesizeKey("VK_RIGHT", { });
});
is(inspector.selection.node, node, "Body should be selected initially.");
node = doc.querySelector("h1")
inspector.once("inspector-updated", highlightHeaderNode);
let bc = inspector.breadcrumbs;
bc.nodeHierarchy[bc.currentIndex].button.focus();
EventUtils.synthesizeKey("VK_RIGHT", {});
}
function highlightHeaderNode()

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

@ -25,7 +25,7 @@ function test() {
openInspector((aInspector, aToolbox) => {
inspector = aInspector;
markupView = inspector.markup;
inspector.once("inspector-updated", startTests);
startTests();
});
}, content);
}, true);

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

@ -35,9 +35,7 @@ function createDocument() {
// Open the inspector, start the picker mode, and start the tests
openInspector(aInspector => {
inspector = aInspector;
inspector.once("inspector-updated", () => {
inspector.toolbox.highlighterUtils.startPicker().then(runTests);
});
inspector.toolbox.highlighterUtils.startPicker().then(runTests);
});
}, false);

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

@ -13,9 +13,7 @@ function test() {
openInspector(aInspector => {
inspector = aInspector;
inspector.once("inspector-updated", () => {
inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
});
inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
});
}

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

@ -1,189 +1,142 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that locking the pseudoclass displays correctly in the ruleview
let DOMUtils = Cc["@mozilla.org/inspector/dom-utils;1"].getService(Ci.inIDOMUtils);
const PSEUDO = ":hover";
const TEST_URL = 'data:text/html,' +
'<head>' +
' <style>div {color:red;} div:hover {color:blue;}</style>' +
'</head>' +
'<body>' +
' <div id="parent-div">' +
' <div id="div-1">test div</div>' +
' <div id="div-2">test div2</div>' +
' </div>' +
'</body>';
let doc;
let parentDiv, div, div2;
let inspector;
let ruleview;
waitForExplicitFinish();
let pseudo = ":hover";
function test()
{
waitForExplicitFinish();
function test() {
ignoreAllUncaughtExceptions();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
waitForFocus(startTests, content);
}, true);
content.location = "data:text/html,pseudo-class lock tests";
content.location = TEST_URL;
}
function createDocument()
{
parentDiv = doc.createElement("div");
parentDiv.textContent = "parent div";
let startTests = Task.async(function*() {
let {toolbox, inspector, view} = yield openRuleView();
yield selectNode("#div-1", inspector);
div = doc.createElement("div");
div.textContent = "test div";
yield performTests(inspector, view);
div2 = doc.createElement("div");
div2.textContent = "test div2";
yield finishUp(toolbox);
finish();
});
let head = doc.getElementsByTagName('head')[0];
let style = doc.createElement('style');
let rules = doc.createTextNode('div { color: red; } div:hover { color: blue; }');
function* performTests(inspector, ruleview) {
yield togglePseudoClass(inspector);
yield testAdded(inspector, ruleview);
style.appendChild(rules);
head.appendChild(style);
parentDiv.appendChild(div);
parentDiv.appendChild(div2);
doc.body.appendChild(parentDiv);
yield togglePseudoClass(inspector);
yield testRemoved();
yield testRemovedFromUI(inspector, ruleview);
openInspector(selectNode);
yield togglePseudoClass(inspector);
yield testNavigate(inspector, ruleview);
}
function selectNode(aInspector)
{
inspector = aInspector;
function* togglePseudoClass(inspector) {
info("Toggle the pseudoclass, wait for the pseudoclass event and wait for the refresh of the rule view");
waitForView("ruleview", () => {
ruleview = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
inspector.sidebar.select("ruleview");
inspector.selection.setNode(div, "test");
inspector.once("inspector-updated", performTests);
});
let onPseudo = inspector.selection.once("pseudoclass");
let onRefresh = inspector.once("rule-view-refreshed");
inspector.togglePseudoClass(PSEUDO);
yield onPseudo;
yield onRefresh;
}
function performTests()
{
// toggle the class
inspector.togglePseudoClass(pseudo);
function* testNavigate(inspector, ruleview) {
yield selectNode("#parent-div", inspector);
// Wait for the "pseudoclass" event so we know the
// inspector has been told of the pseudoclass lock change.
inspector.selection.once("pseudoclass", () => {
inspector.once("rule-view-refreshed", () => {
testAdded(() => {
// Change the pseudo class and give the rule view time to update.
inspector.togglePseudoClass(pseudo);
inspector.selection.once("pseudoclass", () => {
inspector.once("rule-view-refreshed", () => {
testRemoved();
testRemovedFromUI(() => {
// toggle it back on
inspector.togglePseudoClass(pseudo);
inspector.selection.once("pseudoclass", () => {
inspector.once("rule-view-refreshed", () => {
testNavigate(() => {
// close the inspector
finishUp();
});
});
});
});
});
});
});
});
});
info("Make sure the pseudoclass is still on after navigating to a parent");
is(DOMUtils.hasPseudoClassLock(getNode("#div-1"), PSEUDO), true,
"pseudo-class lock is still applied after inspecting ancestor");
let onPseudo = inspector.selection.once("pseudoclass");
yield selectNode("#div-2", inspector);
yield onPseudo;
info("Make sure the pseudoclass is removed after navigating to a non-hierarchy node");
is(DOMUtils.hasPseudoClassLock(getNode("#div-1"), PSEUDO), false,
"pseudo-class lock is removed after inspecting sibling node");
yield selectNode("#div-1", inspector);
yield togglePseudoClass(inspector);
yield inspector.once("computed-view-refreshed");
}
function testNavigate(callback)
{
inspector.selection.setNode(parentDiv, "test");
inspector.once("inspector-updated", () => {
// make sure it's still on after naving to parent
is(DOMUtils.hasPseudoClassLock(div, pseudo), true,
"pseudo-class lock is still applied after inspecting ancestor");
inspector.selection.setNode(div2, "test");
inspector.selection.once("pseudoclass", () => {
// make sure it's removed after naving to a non-hierarchy node
is(DOMUtils.hasPseudoClassLock(div, pseudo), false,
"pseudo-class lock is removed after inspecting sibling node");
// toggle it back on
inspector.selection.setNode(div, "test");
inspector.once("inspector-updated", () => {
inspector.togglePseudoClass(pseudo);
inspector.once("computed-view-refreshed", callback);
});
});
});
}
function showPickerOn(node, cb)
{
function showPickerOn(node, inspector) {
let highlighter = inspector.toolbox.highlighter;
highlighter.showBoxModel(getNodeFront(node)).then(cb);
return highlighter.showBoxModel(getNodeFront(node));
}
function testAdded(cb)
{
// lock is applied to it and ancestors
let node = div;
function* testAdded(inspector, ruleview) {
info("Make sure the pseudoclass lock is applied to #div-1 and its ancestors");
let node = getNode("#div-1");
do {
is(DOMUtils.hasPseudoClassLock(node, pseudo), true,
is(DOMUtils.hasPseudoClassLock(node, PSEUDO), true,
"pseudo-class lock has been applied");
node = node.parentNode;
} while (node.parentNode)
// ruleview contains pseudo-class rule
info("Check that the ruleview contains the pseudo-class rule");
let rules = ruleview.element.querySelectorAll(".ruleview-rule.theme-separator");
is(rules.length, 3, "rule view is showing 3 rules for pseudo-class locked div");
is(rules[1]._ruleEditor.rule.selectorText, "div:hover", "rule view is showing " + pseudo + " rule");
is(rules[1]._ruleEditor.rule.selectorText, "div:hover", "rule view is showing " + PSEUDO + " rule");
// Show the highlighter by starting the pick mode and hovering over the div
showPickerOn(div, () => {
// infobar selector contains pseudo-class
let pseudoClassesBox = getHighlighter().querySelector(".highlighter-nodeinfobar-pseudo-classes");
is(pseudoClassesBox.textContent, pseudo, "pseudo-class in infobar selector");
inspector.toolbox.highlighter.hideBoxModel().then(cb);
});
info("Show the highlighter on #div-1");
yield showPickerOn(getNode("#div-1"), inspector);
info("Check that the infobar selector contains the pseudo-class");
let pseudoClassesBox = getHighlighter().querySelector(".highlighter-nodeinfobar-pseudo-classes");
is(pseudoClassesBox.textContent, PSEUDO, "pseudo-class in infobar selector");
yield inspector.toolbox.highlighter.hideBoxModel();
}
function testRemoved()
{
// lock removed from node and ancestors
let node = div;
function* testRemoved() {
info("Make sure the pseudoclass lock is removed from #div-1 and its ancestors");
let node = getNode("#div-1");
do {
is(DOMUtils.hasPseudoClassLock(node, pseudo), false,
is(DOMUtils.hasPseudoClassLock(node, PSEUDO), false,
"pseudo-class lock has been removed");
node = node.parentNode;
} while (node.parentNode)
}
function testRemovedFromUI(cb)
{
// ruleview no longer contains pseudo-class rule
function* testRemovedFromUI(inspector, ruleview) {
info("Check that the ruleview no longer contains the pseudo-class rule");
let rules = ruleview.element.querySelectorAll(".ruleview-rule.theme-separator");
is(rules.length, 2, "rule view is showing 2 rules after removing lock");
showPickerOn(div, () => {
let pseudoClassesBox = getHighlighter().querySelector(".highlighter-nodeinfobar-pseudo-classes");
is(pseudoClassesBox.textContent, "", "pseudo-class removed from infobar selector");
inspector.toolbox.highlighter.hideBoxModel().then(cb);
});
yield showPickerOn(getNode("#div-1"), inspector);
let pseudoClassesBox = getHighlighter().querySelector(".highlighter-nodeinfobar-pseudo-classes");
is(pseudoClassesBox.textContent, "", "pseudo-class removed from infobar selector");
yield inspector.toolbox.highlighter.hideBoxModel();
}
function finishUp()
{
gDevTools.once("toolbox-destroyed", function() {
testRemoved();
inspector = ruleview = null;
doc = div = null;
gBrowser.removeCurrentTab();
finish();
});
let target = TargetFactory.forTab(gBrowser.selectedTab);
let toolbox = gDevTools.getToolbox(target);
function* finishUp(toolbox) {
let onDestroy = gDevTools.once("toolbox-destroyed");
toolbox.destroy();
yield onDestroy;
yield testRemoved(getNode("#div-1"));
gBrowser.removeCurrentTab();
}

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

@ -41,12 +41,152 @@ SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
});
function openInspector(callback)
{
/**
* Simple DOM node accesor function that takes either a node or a string css
* selector as argument and returns the corresponding node
* @param {String|DOMNode} nodeOrSelector
* @return {DOMNode}
*/
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 {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") {
info("Selecting the node " + nodeOrSelector);
let node = getNode(nodeOrSelector);
let updated = inspector.once("inspector-updated");
inspector.selection.setNode(node, reason);
return updated;
}
/**
* Open the toolbox, with the inspector tool visible.
* @param {Function} cb Optional callback, if you don't want to use the returned
* promise
* @return a promise that resolves when the inspector is ready
*/
let openInspector = Task.async(function*(cb) {
info("Opening the inspector");
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
callback(toolbox.getCurrentPanel(), toolbox);
}).then(null, console.error);
let inspector, toolbox;
// 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");
if (cb) {
return cb(inspector, toolbox);
} else {
return {
toolbox: toolbox,
inspector: inspector
};
}
}
}
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");
if (cb) {
return cb(inspector, toolbox);
} else {
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;
}
/**
* 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();
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
};
});
/**
* 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 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");
}
/**
* 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);
}
function getActiveInspector()