Bug 988314 - Clean up and rewrite Inspector tests to use Task.jsm and generators. r=pbrosset

This commit is contained in:
Sami Jaktholm 2014-07-08 02:29:00 +02:00
Родитель 65aa288259
Коммит ca224fd52d
33 изменённых файлов: 1510 добавлений и 2179 удалений

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

@ -1,100 +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/ */
"use strict";
function test()
{
ignoreAllUncaughtExceptions();
// Test that the breadcrumbs widget content is correct.
let nodes = [
{nodeId: "i1111", result: "i1 i11 i111 i1111"},
{nodeId: "i22", result: "i2 i22 i221"},
{nodeId: "i2111", result: "i2 i21 i211 i2111"},
{nodeId: "i21", result: "i2 i21 i211 i2111"},
{nodeId: "i22211", result: "i2 i22 i222 i2221 i22211"},
{nodeId: "i22", result: "i2 i22 i222 i2221 i22211"},
];
const TEST_URI = TEST_URL_ROOT + "browser_inspector_breadcrumbs.html";
const NODES = [
{nodeId: "#i1111", result: "i1 i11 i111 i1111"},
{nodeId: "#i22", result: "i2 i22 i221"},
{nodeId: "#i2111", result: "i2 i21 i211 i2111"},
{nodeId: "#i21", result: "i2 i21 i211 i2111"},
{nodeId: "#i22211", result: "i2 i22 i222 i2221 i22211"},
{nodeId: "#i22", result: "i2 i22 i222 i2221 i22211"},
];
let doc;
let nodes;
let cursor;
let inspector;
let target;
let panel;
let container;
let test = asyncTest(function*() {
let { inspector } = yield openInspectorForURL(TEST_URI);
let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupTest, content);
}, true);
for (let node of NODES) {
info("Testing node " + node.nodeId);
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_breadcrumbs.html";
let documentNode = getNode(node.nodeId);
function setupTest()
{
for (let i = 0; i < nodes.length; i++) {
let node = doc.getElementById(nodes[i].nodeId);
nodes[i].node = node;
ok(nodes[i].node, "node " + nodes[i].nodeId + " found");
}
info("Selecting node and waiting for breadcrumbs to update");
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
let nodeSelected = selectNode(documentNode, inspector);
openInspector(runTests);
}
yield Promise.all([breadcrumbsUpdated, nodeSelected]);
function runTests(aInspector)
{
inspector = aInspector;
target = TargetFactory.forTab(gBrowser.selectedTab);
panel = gDevTools.getToolbox(target).getPanel("inspector");
container = panel.panelDoc.getElementById("inspector-breadcrumbs");
cursor = 0;
inspector.on("breadcrumbs-updated", nodeSelected);
executeSoon(function() {
inspector.selection.setNode(nodes[0].node);
});
}
function nodeSelected()
{
performTest();
cursor++;
if (cursor >= nodes.length) {
inspector.off("breadcrumbs-updated", nodeSelected);
// breadcrumbs-updated is an event that is fired before the rest of the
// inspector is updated, so there'll be hanging connections if we finish
// up before waiting for everything to end.
inspector.once("inspector-updated", finishUp);
} else {
let node = nodes[cursor].node;
inspector.selection.setNode(node);
}
}
function performTest()
{
let buttonsLabelIds = nodes[cursor].result.split(" ");
info("Performing checks for node " + node.nodeId);
let buttonsLabelIds = node.result.split(" ");
// html > body > …
is(container.childNodes.length, buttonsLabelIds.length + 2, "Node " + cursor + ": Items count");
is(container.childNodes.length, buttonsLabelIds.length + 2,
"Node " + node.nodeId + ": Items count");
for (let i = 2; i < container.childNodes.length; i++) {
let expectedId = "#" + buttonsLabelIds[i - 2];
let button = container.childNodes[i];
let labelId = button.querySelector(".breadcrumbs-widget-item-id");
is(labelId.textContent, expectedId, "Node " + cursor + ": button " + i + " matches");
is(labelId.textContent, expectedId,
"Node #" + node.nodeId + ": button " + i + " matches");
}
let checkedButton = container.querySelector("button[checked]");
let labelId = checkedButton.querySelector(".breadcrumbs-widget-item-id");
let id = inspector.selection.node.id;
is(labelId.textContent, "#" + id, "Node " + cursor + ": selection matches");
is(labelId.textContent, "#" + id,
"Node #" + node.nodeId + ": selection matches");
}
function finishUp() {
doc = nodes = inspector = null;
gBrowser.removeCurrentTab();
finish();
}
}
});

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

@ -1,118 +1,82 @@
/* 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";
function test()
{
let inspector, searchBox, state;
let keypressStates = [3,4,8,18,19,20,21,22];
// Test that searching for nodes in the search field actually selects those
// nodes.
// The various states of the inspector: [key, id, isValid]
// [
// what key to press,
// what id should be selected after the keypress,
// is the searched text valid selector
// ]
let keyStates = [
["d", "b1", false],
["i", "b1", false],
["v", "d1", true],
["VK_DOWN", "d2", true],
["VK_RETURN", "d1", true],
[".", "d1", false],
["c", "d1", false],
["1", "d2", true],
["VK_DOWN", "d2", true],
["VK_BACK_SPACE", "d2", false],
["VK_BACK_SPACE", "d2", false],
["VK_BACK_SPACE", "d1", true],
["VK_BACK_SPACE", "d1", false],
["VK_BACK_SPACE", "d1", false],
["VK_BACK_SPACE", "d1", true],
[".", "d1", false],
["c", "d1", false],
["1", "d2", true],
["VK_DOWN", "s2", true],
["VK_DOWN", "p1", true],
["VK_UP", "s2", true],
["VK_UP", "d2", true],
["VK_UP", "p1", true],
["VK_BACK_SPACE", "p1", false],
["2", "p3", true],
["VK_BACK_SPACE", "p3", false],
["VK_BACK_SPACE", "p3", false],
["VK_BACK_SPACE", "p3", true],
["r", "p3", false],
];
const TEST_URL = TEST_URL_ROOT + "browser_inspector_bug_650804_search.html";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
// Indexes of the keys in the KEY_STATES array that should listen to "keypress"
// event instead of "command". These are keys that don't change the content of
// the search field and thus don't trigger command event.
const LISTEN_KEYPRESS = [3,4,8,18,19,20,21,22];
content.location = "http://mochi.test:8888/browser/browser/devtools/" +
"inspector/test/browser_inspector_bug_650804_search.html";
// The various states of the inspector: [key, id, isValid]
// [
// what key to press,
// what id should be selected after the keypress,
// is the searched text valid selector
// ]
const KEY_STATES = [
["d", "b1", false],
["i", "b1", false],
["v", "d1", true],
["VK_DOWN", "d2", true], // keypress
["VK_RETURN", "d1", true], //keypress
[".", "d1", false],
["c", "d1", false],
["1", "d2", true],
["VK_DOWN", "d2", true], // keypress
["VK_BACK_SPACE", "d2", false],
["VK_BACK_SPACE", "d2", false],
["VK_BACK_SPACE", "d1", true],
["VK_BACK_SPACE", "d1", false],
["VK_BACK_SPACE", "d1", false],
["VK_BACK_SPACE", "d1", true],
[".", "d1", false],
["c", "d1", false],
["1", "d2", true],
["VK_DOWN", "s2", true], // keypress
["VK_DOWN", "p1", true], // kepress
["VK_UP", "s2", true], // keypress
["VK_UP", "d2", true], // keypress
["VK_UP", "p1", true],
["VK_BACK_SPACE", "p1", false],
["2", "p3", true],
["VK_BACK_SPACE", "p3", false],
["VK_BACK_SPACE", "p3", false],
["VK_BACK_SPACE", "p3", true],
["r", "p3", false],
];
function $(id) {
if (id == null) return null;
return content.document.getElementById(id);
}
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
let { searchBox } = inspector;
function setupTest()
{
openInspector(startTest);
}
yield selectNode("#b1", inspector);
yield focusSearchBoxUsingShortcut(inspector.panelWin);
function startTest(aInspector)
{
inspector = aInspector;
inspector.selection.setNode($("b1"));
let index = 0;
for (let [ key, id, isValid ] of KEY_STATES) {
let event = (LISTEN_KEYPRESS.indexOf(index) !== -1) ? "keypress" : "command";
let eventHandled = once(searchBox, event, true);
searchBox =
inspector.panelWin.document.getElementById("inspector-searchbox");
focusSearchBoxUsingShortcut(inspector.panelWin, function() {
searchBox.addEventListener("command", checkState, true);
searchBox.addEventListener("keypress", checkState, true);
checkStateAndMoveOn(0);
});
}
function checkStateAndMoveOn(index) {
if (index == keyStates.length) {
finishUp();
return;
}
let [key, id, isValid] = keyStates[index];
state = index;
info("pressing key " + key + " to get id " + id);
info(index + ": Pressing key " + key + " to get id " + id);
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
}
yield eventHandled;
function checkState(event) {
if (event.type == "keypress" && keypressStates.indexOf(state) == -1) {
return;
}
info("Got " + event + " event. Waiting for search query to complete");
yield inspector.searchSuggestions._lastQuery;
inspector.searchSuggestions._lastQuery.then(() => {
executeSoon(() => {
let [key, id, isValid] = keyStates[state];
info(inspector.selection.node.id + " is selected with text " +
inspector.searchBox.value);
is(inspector.selection.node, $(id),
"Correct node is selected for state " + state);
is(!searchBox.classList.contains("devtools-no-search-result"), isValid,
"Correct searchbox result state for state " + state);
checkStateAndMoveOn(state + 1);
});
});
}
info(inspector.selection.node.id + " is selected with text " +
searchBox.value);
is(inspector.selection.node, content.document.getElementById(id),
"Correct node is selected for state " + index);
is(!searchBox.classList.contains("devtools-no-search-result"), isValid,
"Correct searchbox result state for state " + index);
function finishUp() {
searchBox = null;
gBrowser.removeCurrentTab();
finish();
index++;
}
}
});

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

@ -1,44 +1,18 @@
/* 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";
function test() {
ignoreAllUncaughtExceptions();
// A regression test for bug 665880 to make sure elements inside <object> can
// be inspected without exceptions.
let doc;
let objectNode;
const TEST_URI = "data:text/html;charset=utf-8," +
"<object><p>browser_inspector_inspect-object-element.js</p></object>";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(setupObjectInspectionTest, content);
}, true);
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URI);
let objectNode = getNode("object");
ok(objectNode, "We have the object node");
content.location = "data:text/html,<object style='padding: 100px'><p>foobar</p></object>";
function setupObjectInspectionTest() {
objectNode = doc.querySelector("object");
ok(objectNode, "we have the object node");
openInspector(runObjectInspectionTest);
}
function runObjectInspectionTest(inspector) {
inspector.once("inspector-updated", performTestComparison);
inspector.selection.setNode(objectNode, "");
}
function performTestComparison() {
is(getActiveInspector().selection.node, objectNode, "selection matches node");
let target = TargetFactory.forTab(gBrowser.selectedTab);
executeSoon(function() {
gDevTools.closeToolbox(target);
finishUp();
});
}
function finishUp() {
doc = objectNode = null;
gBrowser.removeCurrentTab();
finish();
}
}
yield selectNode(objectNode, inspector);
});

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

@ -1,92 +1,40 @@
/* 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 keybindings for highlighting different elements work as
// intended.
function test()
{
let doc;
let node;
let inspector;
const TEST_URI = "data:text/html;charset=utf-8," +
"<html><head><title>Test for the highlighter keybindings</title></head>" +
"<body><h1>Hello</h1><p><strong>Greetings, earthlings!</strong>" +
" I come in peace.</p></body></html>";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupKeyBindingsTest, content);
}, true);
const TEST_DATA = [
{ key: "VK_RIGHT", selectedNode: "h1" },
{ key: "VK_DOWN", selectedNode: "p" },
{ key: "VK_UP", selectedNode: "h1" },
{ key: "VK_LEFT", selectedNode: "body" },
];
content.location = "data:text/html,<html><head><title>Test for the " +
"highlighter keybindings</title></head><body><h1>Hello" +
"</h1><p><strong>Greetings, earthlings!</strong> I come" +
" in peace.</body></html>";
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URI);
is(inspector.selection.node, getNode("body"),
"Body should be selected initially.");
function setupKeyBindingsTest()
{
openInspector(findAndHighlightNode);
info("Focusing the currently active breadcrumb button");
let bc = inspector.breadcrumbs;
bc.nodeHierarchy[bc.currentIndex].button.focus();
for (let { key, selectedNode } of TEST_DATA) {
info("Pressing " + key + " to select " + selectedNode);
let updated = inspector.once("inspector-updated");
EventUtils.synthesizeKey(key, {});
yield updated;
is(inspector.selection.node, getNode(selectedNode),
selectedNode + " is selected.");
}
function findAndHighlightNode(aInspector, aToolbox)
{
inspector = aInspector;
// Make sure the body element is selected initially.
node = doc.querySelector("body");
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()
{
is(inspector.selection.node, node, "selected h1 element");
executeSoon(function() {
inspector.once("inspector-updated", highlightParagraphNode);
// Test that moving to the next sibling works.
node = doc.querySelector("p");
EventUtils.synthesizeKey("VK_DOWN", { });
});
}
function highlightParagraphNode()
{
is(inspector.selection.node, node, "selected p element");
executeSoon(function() {
inspector.once("inspector-updated", highlightHeaderNodeAgain);
// Test that moving to the previous sibling works.
node = doc.querySelector("h1");
EventUtils.synthesizeKey("VK_UP", { });
});
}
function highlightHeaderNodeAgain()
{
is(inspector.selection.node, node, "selected h1 element");
executeSoon(function() {
inspector.once("inspector-updated", highlightParentNode);
// Test that moving to the parent works.
node = doc.querySelector("body");
EventUtils.synthesizeKey("VK_LEFT", { });
});
}
function highlightParentNode()
{
is(inspector.selection.node, node, "selected body element");
finishUp();
}
function finishUp() {
doc = node = null;
gBrowser.removeCurrentTab();
finish();
}
}
});

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

@ -1,110 +1,70 @@
/* 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";
function test()
{
let doc;
let iframeNode, iframeBodyNode;
let inspector;
// Test that iframes are correctly highlighted.
let iframeSrc = "<style>" +
"body {" +
"margin:0;" +
"height:100%;" +
"background-color:red" +
"}" +
"</style>" +
"<body></body>";
let docSrc = "<style>" +
"iframe {" +
"height:200px;" +
"border: 11px solid black;" +
"padding: 13px;" +
"}" +
"body,iframe {" +
"margin:0" +
"}" +
"</style>" +
"<body>" +
"<iframe src='data:text/html," + iframeSrc + "'></iframe>" +
"</body>";
const IFRAME_SRC = "<style>" +
"body {" +
"margin:0;" +
"height:100%;" +
"background-color:red" +
"}" +
"</style><body>hello from iframe</body>";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupTest, content);
}, true);
const DOCUMENT_SRC = "<style>" +
"iframe {" +
"height:200px;" +
"border: 11px solid black;" +
"padding: 13px;" +
"}" +
"body,iframe {" +
"margin:0" +
"}" +
"</style>" +
"<body>" +
"<iframe src='data:text/html," + IFRAME_SRC + "'></iframe>" +
"</body>";
content.location = "data:text/html," + docSrc;
const TEST_URI = "data:text/html;charset=utf-8," + DOCUMENT_SRC;
function setupTest()
{
iframeNode = doc.querySelector("iframe");
iframeBodyNode = iframeNode.contentDocument.querySelector("body");
ok(iframeNode, "we have the iframe node");
ok(iframeBodyNode, "we have the body node");
openInspector(aInspector => {
inspector = aInspector;
// Make sure the highlighter is shown so we can disable transitions
inspector.toolbox.highlighter.showBoxModel(getNodeFront(doc.body)).then(() => {
runTests();
});
});
}
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
let outerDocument = content.document;
function runTests()
{
inspector.toolbox.highlighterUtils.startPicker().then(() => {
moveMouseOver(iframeNode, 1, 1, isTheIframeHighlighted);
});
}
let iframeNode = getNode("iframe");
let iframeBodyNode = getNode("body", { document: iframeNode.contentDocument });
function isTheIframeHighlighted()
{
let {p1, p2, p3, p4} = getBoxModelStatus().border.points;
let {top, right, bottom, left} = iframeNode.getBoundingClientRect();
info("Waiting for box mode to show.");
yield toolbox.highlighter.showBoxModel(getNodeFront(outerDocument.body));
is(top, p1.y, "iframeRect.top === boxModelStatus.p1.y");
is(top, p2.y, "iframeRect.top === boxModelStatus.p2.y");
is(right, p2.x, "iframeRect.right === boxModelStatus.p2.x");
is(right, p3.x, "iframeRect.right === boxModelStatus.p3.x");
is(bottom, p3.y, "iframeRect.bottom === boxModelStatus.p3.y");
is(bottom, p4.y, "iframeRect.bottom === boxModelStatus.p4.y");
is(left, p1.x, "iframeRect.left === boxModelStatus.p1.x");
is(left, p4.x, "iframeRect.left === boxModelStatus.p4.x");
info("Waiting for element picker to become active.");
yield toolbox.highlighterUtils.startPicker();
iframeNode.style.marginBottom = doc.defaultView.innerHeight + "px";
doc.defaultView.scrollBy(0, 40);
info("Moving mouse over iframe padding.");
yield moveMouseOver(iframeNode, 1, 1);
moveMouseOver(iframeNode, 40, 40, isTheIframeContentHighlighted);
}
info("Performing checks");
isNodeCorrectlyHighlighted(iframeNode);
function isTheIframeContentHighlighted()
{
is(getHighlitNode(), iframeBodyNode, "highlighter shows the right node");
info("Scrolling the document");
iframeNode.style.marginBottom = outerDocument.defaultView.innerHeight + "px";
outerDocument.defaultView.scrollBy(0, 40);
let outlineRect = getSimpleBorderRect();
is(outlineRect.height, 200, "highlighter height");
info("Moving mouse over iframe body");
yield moveMouseOver(iframeNode, 40, 40);
inspector.toolbox.highlighterUtils.stopPicker().then(() => {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
finishUp();
});
}
is(getHighlitNode(), iframeBodyNode, "highlighter shows the right node");
isNodeCorrectlyHighlighted(iframeBodyNode);
function finishUp()
{
doc = inspector = iframeNode = iframeBodyNode = null;
gBrowser.removeCurrentTab();
finish();
}
info("Waiting for the element picker to deactivate.");
yield inspector.toolbox.highlighterUtils.stopPicker();
function moveMouseOver(aElement, x, y, cb)
{
inspector.toolbox.once("picker-node-hovered", cb);
function moveMouseOver(aElement, x, y) {
info("Waiting for element " + aElement + " to be highlighted");
EventUtils.synthesizeMouse(aElement, x, y, {type: "mousemove"},
aElement.ownerDocument.defaultView);
return inspector.toolbox.once("picker-node-hovered");
}
}
});

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

@ -1,77 +1,45 @@
/* 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";
function test() {
let iframe;
let iframeLoads = 0;
let checksAfterLoads = false;
let inspector;
// Test that the highlighter element picker still works through iframe
// navigations.
function startTest() {
openInspector(aInspector => {
inspector = aInspector;
runInspectorTests();
});
const TEST_URI = "data:text/html;charset=utf-8," +
"<p>bug 699308 - test iframe navigation</p>" +
"<iframe src='data:text/html;charset=utf-8,hello world'></iframe>";
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
let iframe = getNode("iframe");
info("Starting element picker.");
yield toolbox.highlighterUtils.startPicker();
info("Waiting for highlighter to activate.");
let highlighterShowing = toolbox.once("highlighter-ready");
EventUtils.synthesizeMouse(content.document.body, 1, 1,
{type: "mousemove"}, content);
yield highlighterShowing;
ok(isHighlighting(), "Inspector is highlighting.");
yield reloadFrame();
info("Frame reloaded. Reloading again.");
yield reloadFrame();
info("Frame reloaded twice.");
ok(isHighlighting(), "Inspector is highlighting after iframe nav.");
info("Stopping element picker.");
yield toolbox.highlighterUtils.stopPicker();
function reloadFrame() {
info("Reloading frame.");
let frameLoaded = once(iframe, "load");
iframe.contentWindow.location.reload();
return frameLoaded;
}
function showHighlighter(cb) {
inspector.toolbox.highlighterUtils.startPicker().then(() => {
EventUtils.synthesizeMouse(content.document.body, 1, 1,
{type: "mousemove"}, content);
inspector.toolbox.once("highlighter-ready", cb);
});
}
function runInspectorTests() {
iframe = content.document.querySelector("iframe");
ok(iframe, "found the iframe element");
showHighlighter(() => {
ok(isHighlighting(), "Inspector is highlighting");
iframe.addEventListener("load", onIframeLoad, false);
executeSoon(() => {
iframe.contentWindow.location = "javascript:location.reload()";
});
});
}
function onIframeLoad() {
if (++iframeLoads != 2) {
executeSoon(function() {
iframe.contentWindow.location = "javascript:location.reload()";
});
return;
}
iframe.removeEventListener("load", onIframeLoad, false);
info("Finished reloading iframe and inspector updated");
ok(isHighlighting(), "Inspector is highlighting after iframe nav");
checksAfterLoads = true;
finishTest();
}
function finishTest() {
is(iframeLoads, 2, "iframe loads");
ok(checksAfterLoads, "the Inspector tests got the chance to run after iframe reloads");
inspector.toolbox.highlighterUtils.stopPicker().then(() => {
iframe = null;
gBrowser.removeCurrentTab();
executeSoon(finish);
});
}
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onBrowserLoad() {
gBrowser.selectedBrowser.removeEventListener("load", onBrowserLoad, true);
waitForFocus(startTest, content);
}, true);
content.location = "data:text/html;charset=utf-8," +
"<p>bug 699308 - test iframe navigation</p>" +
"<iframe src='data:text/html;charset=utf-8,hello world'></iframe>";
}
});

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

@ -1,52 +1,28 @@
/* 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";
function test()
{
//ignoreAllUncaughtExceptions();
// Test to ensure inspector handles deletion of selected node correctly.
let node, iframe, inspector;
const TEST_URL = TEST_URL_ROOT + "browser_inspector_destroyselection.html";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
let iframe = getNode("iframe");
let span = getNode("span", { document: iframe.contentDocument });
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_destroyselection.html";
yield selectNode(span, inspector);
function setupTest()
{
iframe = content.document.querySelector("iframe");
node = iframe.contentDocument.querySelector("span");
openInspector(runTests);
}
info("Removing selected <span> element.");
let parentNode = span.parentNode;
span.remove();
function runTests(aInspector)
{
inspector = aInspector;
inspector.selection.setNode(node);
inspector.once("inspector-updated", () => {
let parentNode = node.parentNode;
parentNode.removeChild(node);
let tmp = {};
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
let lh = new tmp.LayoutHelpers(window.content);
ok(!lh.isNodeConnected(node), "Node considered as disconnected.");
// Wait for the inspector to process the mutation
inspector.once("inspector-updated", () => {
is(inspector.selection.node, parentNode, "parent of selection got selected");
finishUp();
});
});
};
function finishUp() {
node = null;
gBrowser.removeCurrentTab();
finish();
}
}
let lh = new LayoutHelpers(window.content);
ok(!lh.isNodeConnected(span), "Node considered as disconnected.");
// Wait for the inspector to process the mutation
yield inspector.once("inspector-updated");
is(inspector.selection.node, parentNode,
"Parent node of selected <span> got selected.");
});

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

@ -1,111 +1,157 @@
/* 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";
function test()
{
let inspector, searchBox, state, popup;
// Testing that searching for combining selectors using the inspector search
// field produces correct suggestions.
// The various states of the inspector: [key, suggestions array]
// [
// what key to press,
// suggestions array with count [
// [suggestion1, count1], [suggestion2] ...
// ] count can be left to represent 1
// ]
let keyStates = [
["d", [["div", 4]]],
["i", [["div", 4]]],
["v", []],
[" ", [["div div", 2], ["div span", 2]]],
[">", [["div >div", 2], ["div >span", 2]]],
["VK_BACK_SPACE", [["div div", 2], ["div span", 2]]],
["+", [["div +span"]]],
["VK_BACK_SPACE", [["div div", 2], ["div span", 2]]],
["VK_BACK_SPACE", []],
["VK_BACK_SPACE", [["div", 4]]],
["VK_BACK_SPACE", [["div", 4]]],
["VK_BACK_SPACE", []],
["p", []],
[" ", [["p strong"]]],
["+", [["p +button"], ["p +p"]]],
["b", [["p +button"]]],
["u", [["p +button"]]],
["t", [["p +button"]]],
["t", [["p +button"]]],
["o", [["p +button"]]],
["n", []],
["+", [["p +button+p"]]],
];
const TEST_URL = TEST_URL_ROOT + "browser_inspector_bug_831693_search_suggestions.html";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_831693_search_suggestions.html";
function $(id) {
if (id == null) return null;
return content.document.getElementById(id);
}
function setupTest()
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
// Suggestion is an object with label of the entry and optional count
// (defaults to 1)
const TEST_DATA = [
{
openInspector(startTest);
}
function startTest(aInspector)
key: "d",
suggestions: [{label: "div", count: 4}]
},
{
inspector = aInspector;
searchBox =
inspector.panelWin.document.getElementById("inspector-searchbox");
popup = inspector.searchSuggestions.searchPopup;
focusSearchBoxUsingShortcut(inspector.panelWin, function() {
searchBox.addEventListener("command", checkState, true);
checkStateAndMoveOn(0);
});
key: "i",
suggestions: [{label: "div", count: 4}]
},
{
key: "v",
suggestions: []
},
{
key: " ",
suggestions: [
{label: "div div", count: 2},
{label: "div span", count: 2}
]
},
{
key: ">",
suggestions: [
{label: "div >div", count: 2},
{label: "div >span", count: 2}
]
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: "div div", count: 2 },
{label: "div span", count: 2}
]
},
{
key: "+",
suggestions: [{label: "div +span"}]
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: "div div", count: 2 },
{label: "div span", count: 2}
]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "VK_BACK_SPACE",
suggestions: [{label: "div", count: 4}]
},
{
key: "VK_BACK_SPACE",
suggestions: [{label: "div", count: 4}]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "p",
suggestions: []
},
{
key: " ",
suggestions: [{label: "p strong"}]
},
{
key: "+",
suggestions: [
{label: "p +button" },
{label: "p +p"}
]
},
{
key: "b",
suggestions: [{label: "p +button"}]
},
{
key: "u",
suggestions: [{label: "p +button"}]
},
{
key: "t",
suggestions: [{label: "p +button"}]
},
{
key: "t",
suggestions: [{label: "p +button"}]
},
{
key: "o",
suggestions: [{label: "p +button"}]
},
{
key: "n",
suggestions: []
},
{
key: "+",
suggestions: [{label: "p +button+p"}]
}
];
function checkStateAndMoveOn(index) {
if (index == keyStates.length) {
finishUp();
return;
}
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
let searchBox = inspector.searchBox;
let popup = inspector.searchSuggestions.searchPopup;
let [key, suggestions] = keyStates[index];
state = index;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
info("pressing key " + key + " to get suggestions " +
JSON.stringify(suggestions));
for (let { key, suggestions } of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
}
yield command;
function checkState(event) {
inspector.searchSuggestions._lastQuery.then(() => {
let [key, suggestions] = keyStates[state];
let actualSuggestions = popup.getItems();
is(popup.isOpen ? actualSuggestions.length: 0, suggestions.length,
"There are expected number of suggestions at " + state + "th step.");
actualSuggestions = actualSuggestions.reverse();
for (let i = 0; i < suggestions.length; i++) {
is(suggestions[i][0], actualSuggestions[i].label,
"The suggestion at " + i + "th index for " + state +
"th step is correct.")
is(suggestions[i][1] || 1, actualSuggestions[i].count,
"The count for suggestion at " + i + "th index for " + state +
"th step is correct.")
}
checkStateAndMoveOn(state + 1);
});
}
info("Waiting for search query to complete");
yield inspector.searchSuggestions._lastQuery;
function finishUp() {
searchBox = null;
popup = null;
gBrowser.removeCurrentTab();
finish();
info("Query completed. Performing checks for input '" + searchBox.value + "'");
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length: 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(suggestions[i].label, actualSuggestions[i].label,
"The suggestion at " + i + "th index is correct.");
is(suggestions[i].count || 1, actualSuggestions[i].count,
"The count for suggestion at " + i + "th index is correct.");
}
}
});
function formatSuggestions(suggestions) {
return "[" + suggestions
.map(s => "'" + s.label + "' (" + s.count || 1 + ")")
.join(", ") + "]";
}

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

@ -1,112 +1,194 @@
/* 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";
function test()
{
let inspector, searchBox, state, popup;
// Testing that searching for elements using the inspector search field
// produces correct suggestions.
// The various states of the inspector: [key, suggestions array]
// [
// what key to press,
// suggestions array with count [
// [suggestion1, count1], [suggestion2] ...
// ] count can be left to represent 1
// ]
let keyStates = [
["d", [["div", 2]]],
["i", [["div", 2]]],
["v", []],
[".", [["div.c1"]]],
["VK_BACK_SPACE", []],
["#", [["div#d1"], ["div#d2"]]],
["VK_BACK_SPACE", []],
["VK_BACK_SPACE", [["div", 2]]],
["VK_BACK_SPACE", [["div", 2]]],
["VK_BACK_SPACE", []],
[".", [[".c1", 3], [".c2"]]],
["c", [[".c1", 3], [".c2"]]],
["2", []],
["VK_BACK_SPACE", [[".c1", 3], [".c2"]]],
["1", []],
["#", [["#d2"], ["#p1"], ["#s2"]]],
["VK_BACK_SPACE", []],
["VK_BACK_SPACE", [[".c1", 3], [".c2"]]],
["VK_BACK_SPACE", [[".c1", 3], [".c2"]]],
["VK_BACK_SPACE", []],
["#", [["#b1"], ["#d1"], ["#d2"], ["#p1"], ["#p2"], ["#p3"], ["#s1"], ["#s2"]]],
["p", [["#p1"], ["#p2"], ["#p3"]]],
["VK_BACK_SPACE", [["#b1"], ["#d1"], ["#d2"], ["#p1"], ["#p2"], ["#p3"], ["#s1"], ["#s2"]]],
["VK_BACK_SPACE", []],
];
const TEST_URL = TEST_URL_ROOT + "browser_inspector_bug_650804_search.html";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_650804_search.html";
function $(id) {
if (id == null) return null;
return content.document.getElementById(id);
}
function setupTest()
// An array of (key, suggestions) pairs where key is a key to press and
// suggestions is an array of suggestions that should be shown in the popup.
// Suggestion is an object with label of the entry and optional count
// (defaults to 1)
let TEST_DATA = [
{
openInspector(startTest);
}
function startTest(aInspector)
key: "d",
suggestions: [{label: "div", count: 2}]
},
{
inspector = aInspector;
searchBox =
inspector.panelWin.document.getElementById("inspector-searchbox");
popup = inspector.searchSuggestions.searchPopup;
focusSearchBoxUsingShortcut(inspector.panelWin, function() {
searchBox.addEventListener("command", checkState, true);
checkStateAndMoveOn(0);
});
key: "i",
suggestions: [{label: "div", count: 2}]
},
{
key: "v",
suggestions: []
},
{
key: ".",
suggestions: [{label: "div.c1"}]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "#",
suggestions: [
{label: "div#d1"},
{label: "div#d2"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "VK_BACK_SPACE",
suggestions: [{label: "div", count: 2}]
},
{
key: "VK_BACK_SPACE",
suggestions: [{label: "div", count: 2}]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: ".",
suggestions: [
{label: ".c1", count: 3},
{label: ".c2"}
]
},
{
key: "c",
suggestions: [
{label: ".c1", count: 3},
{label: ".c2"}
]
},
{
key: "2",
suggestions: []
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: ".c1", count: 3},
{label: ".c2"}
]
},
{
key: "1",
suggestions: []
},
{
key: "#",
suggestions: [
{label: "#d2"},
{label: "#p1"},
{label: "#s2"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: ".c1", count: 3},
{label: ".c2"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: ".c1", count: 3},
{label: ".c2"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: []
},
{
key: "#",
suggestions: [
{label: "#b1"},
{label: "#d1"},
{label: "#d2"},
{label: "#p1"},
{label: "#p2"},
{label: "#p3"},
{label: "#s1"},
{label: "#s2"}
]
},
{
key: "p",
suggestions: [
{label: "#p1"},
{label: "#p2"},
{label: "#p3"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: [
{label: "#b1"},
{label: "#d1"},
{label: "#d2"},
{label: "#p1"},
{label: "#p2"},
{label: "#p3"},
{label: "#s1"},
{label: "#s2"}
]
},
{
key: "VK_BACK_SPACE",
suggestions: []
}
];
function checkStateAndMoveOn(index) {
if (index == keyStates.length) {
finishUp();
return;
}
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
let searchBox = inspector.searchBox;
let popup = inspector.searchSuggestions.searchPopup;
let [key, suggestions] = keyStates[index];
state = index;
yield focusSearchBoxUsingShortcut(inspector.panelWin);
info("pressing key " + key + " to get suggestions " +
JSON.stringify(suggestions));
for (let { key, suggestions } of TEST_DATA) {
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
let command = once(searchBox, "command");
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
}
yield command;
function checkState(event) {
inspector.searchSuggestions._lastQuery.then(() => {
let [key, suggestions] = keyStates[state];
let actualSuggestions = popup.getItems();
is(popup.isOpen ? actualSuggestions.length: 0, suggestions.length,
"There are expected number of suggestions at " + state + "th step.");
actualSuggestions = actualSuggestions.reverse();
for (let i = 0; i < suggestions.length; i++) {
is(suggestions[i][0], actualSuggestions[i].label,
"The suggestion at " + i + "th index for " + state +
"th step is correct.")
is(suggestions[i][1] || 1, actualSuggestions[i].count,
"The count for suggestion at " + i + "th index for " + state +
"th step is correct.")
}
checkStateAndMoveOn(state + 1);
});
}
info("Waiting for search query to complete");
yield inspector.searchSuggestions._lastQuery;
function finishUp() {
searchBox = null;
popup = null;
gBrowser.removeCurrentTab();
finish();
info("Query completed. Performing checks for input '" + searchBox.value + "'");
let actualSuggestions = popup.getItems().reverse();
is(popup.isOpen ? actualSuggestions.length: 0, suggestions.length,
"There are expected number of suggestions.");
for (let i = 0; i < suggestions.length; i++) {
is(suggestions[i].label, actualSuggestions[i].label,
"The suggestion at " + i + "th index is correct.");
is(suggestions[i].count || 1, actualSuggestions[i].count,
"The count for suggestion at " + i + "th index is correct.");
}
}
});
function formatSuggestions(suggestions) {
return "[" + suggestions
.map(s => "'" + s.label + "' (" + s.count || 1 + ")")
.join(", ") + "]";
}

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

@ -1,59 +1,29 @@
/* 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";
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let Toolbox = devtools.Toolbox;
let TargetFactory = devtools.TargetFactory;
// Testing that closing the inspector after navigating to a page doesn't fail.
function test() {
const URL_1 = "data:text/plain;charset=UTF-8,abcde";
const URL_2 = "data:text/plain;charset=UTF-8,12345";
const URL_1 = "data:text/plain;charset=UTF-8,abcde";
const URL_2 = "data:text/plain;charset=UTF-8,12345";
let target, toolbox;
let test = asyncTest(function* () {
let { toolbox } = yield openInspectorForURL(URL_1);
// open tab, load URL_1, and wait for load to finish
let tab = gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let deferred = promise.defer();
let browser = gBrowser.getBrowserForTab(tab);
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
deferred.resolve(null);
info("Navigating to different URL.");
let navigated = toolbox.target.once("navigate");
content.location = URL_2;
info("Waiting for 'navigate' event from toolbox target.");
yield navigated;
info("Destroying toolbox");
try {
yield toolbox.destroy();
ok(true, "Toolbox destroyed");
} catch (e) {
ok(false, "An exception occured while destroying toolbox");
console.error(e);
}
browser.addEventListener("load", onTabLoad, true);
browser.loadURI(URL_1);
// open devtools panel
deferred.promise
.then(function () gDevTools.showToolbox(target, null, Toolbox.HostType.BOTTOM))
.then(function (aToolbox) { toolbox = aToolbox; })
// select the inspector
.then(function () toolbox.selectTool("inspector"))
// wait until inspector ready
.then(function () {
let deferred = promise.defer();
toolbox.getPanel("inspector").once("inspector-updated", deferred.resolve);
return deferred.promise;
})
// navigate to URL_2
.then(function () {
let deferred = promise.defer();
target.once("navigate", function () deferred.resolve());
browser.loadURI(URL_2);
return deferred.promise;
})
// destroy the toolbox (and hence the inspector) before the load completes
.then(function () toolbox.destroy())
// this (or any other) exception should not occur:
// [JavaScript Error: "TypeError: self.selection is null" {file: "resource:///modules/devtools/InspectorPanel.jsm" line: 250}]
.then(function cleanUp() {
gBrowser.removeCurrentTab();
finish();
});
}
});

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

@ -3,139 +3,94 @@
/* 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/. */
"use strict";
// Test that when nodes are being deleted in the page, the current selection
// and therefore the markup view, css rule view, computed view, font view,
// box model view, and breadcrumbs, reset accordingly to show the right node
const TEST_PAGE = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_848731_reset_selection_on_delete.html";
const TEST_PAGE = TEST_URL_ROOT +
"browser_inspector_bug_848731_reset_selection_on_delete.html";
function test() {
let inspector, toolbox;
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_PAGE);
// Create a tab, load test HTML, wait for load and start the tests
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(function() {
openInspector((aInspector, aToolbox) => {
inspector = aInspector;
toolbox = aToolbox;
startTests();
});
}, content);
}, true);
content.location = TEST_PAGE;
yield testManuallyDeleteSelectedNode();
yield testAutomaticallyDeleteSelectedNode();
yield testDeleteSelectedNodeContainerFrame();
function startTests() {
testManuallyDeleteSelectedNode();
function* testManuallyDeleteSelectedNode() {
info("Selecting a node, deleting it via context menu and checking that " +
"its parent node is selected and breadcrumbs are updated.");
let div = getNode("#deleteManually");
yield selectNode(div, inspector);
info("Getting the node container in the markup view.");
let container = getContainerForRawNode(inspector.markup, div);
info("Simulating right-click on the markup view container.");
EventUtils.synthesizeMouse(container.tagLine, 2, 2,
{type: "contextmenu", button: 2}, inspector.panelWin);
info("Waiting for the context menu to open.");
yield once(inspector.panelDoc.getElementById("inspectorPopupSet"), "popupshown");
info("Clicking 'Delete Node' in the context menu.");
inspector.panelDoc.getElementById("node-menu-delete").click();
info("Waiting for inspector to update.");
yield inspector.once("inspector-updated");
info("Inspector updated, performing checks.");
let parent = getNode("#deleteChildren");
assertNodeSelectedAndPanelsUpdated(parent, "ul#deleteChildren");
}
function getContainerForRawNode(rawNode) {
let front = inspector.markup.walker.frontForRawNode(rawNode);
let container = inspector.markup.getContainer(front);
return container;
function* testAutomaticallyDeleteSelectedNode() {
info("Selecting a node, deleting it via javascript and checking that " +
"its parent node is selected and breadcrumbs are updated.");
let div = getNode("#deleteAutomatically");
yield selectNode(div, inspector);
info("Deleting selected node via javascript.");
div.remove();
info("Waiting for inspector to update.");
yield inspector.once("inspector-updated");
info("Inspector updated, performing checks.");
let parent = getNode("#deleteChildren");
assertNodeSelectedAndPanelsUpdated(parent, "ul#deleteChildren");
}
// 1 - select a node, right click, hit delete, verify that its parent is selected
// and that all other tools are fine
function testManuallyDeleteSelectedNode() {
info("Deleting a node via the devtools contextual menu");
function* testDeleteSelectedNodeContainerFrame() {
info("Selecting a node inside iframe, deleting the iframe via javascript " +
"and checking the parent node of the iframe is selected and " +
"breadcrumbs are updated.");
// Select our div
let div = content.document.getElementById("deleteManually");
inspector.selection.setNode(div);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, div, "Test node is selected");
// Get the node container in the markup view
let container = getContainerForRawNode(div);
// Simulate right-click
EventUtils.synthesizeMouse(container.tagLine, 2, 2,
{type: "contextmenu", button: 2}, inspector.panelWin);
// And react to the popup shown event
let contextMenu = inspector.panelDoc.getElementById("inspectorPopupSet");
contextMenu.addEventListener("popupshown", function contextShown() {
contextMenu.removeEventListener("popupshown", contextShown, false);
// Click on the delete sub-menu item
inspector.panelDoc.getElementById("node-menu-delete").click();
// Once updated, make sure eveything is in place, and move on
inspector.once("inspector-updated", () => {
let parent = content.document.getElementById("deleteChildren");
assertNodeSelectedAndPanelsUpdated(parent, "ul#deleteChildren");
testAutomaticallyDeleteSelectedNode();
});
}, false);
});
}
// 2 - select a node, delete it via javascript, verify the same things as 1
function testAutomaticallyDeleteSelectedNode() {
info("Deleting a node via javascript");
// Select our second div
let div = content.document.getElementById("deleteAutomatically");
inspector.selection.setNode(div);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, div, "Test node is selected");
// Now remove that div via javascript
let parent = content.document.getElementById("deleteChildren");
parent.removeChild(div);
// Once updated, make sure eveything is in place, and move on
inspector.once("inspector-updated", () => {
assertNodeSelectedAndPanelsUpdated(parent, "ul#deleteChildren");
testDeleteSelectedNodeContainerFrame();
});
});
}
// 3 - select a node inside an iframe, delete the iframe via javascript, verify that the default node is selected
// and that all other tools are fine
function testDeleteSelectedNodeContainerFrame() {
info("Deleting an iframe via javascript");
// Select our third test element, inside the iframe
let iframe = content.document.getElementById("deleteIframe");
info("Selecting an element inside iframe.");
let iframe = getNode("#deleteIframe");
let div = iframe.contentDocument.getElementById("deleteInIframe");
inspector.selection.setNode(div);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, div, "Test node is selected");
yield selectNode(div, inspector);
// Now remove that parent iframe via javascript
let parent = content.document.body;
parent.removeChild(iframe);
info("Deleting selected node via javascript.");
iframe.remove();
// Once updated, make sure eveything is in place, and move on
inspector.once("inspector-updated", () => {
assertNodeSelectedAndPanelsUpdated(parent, "body");
endTests();
});
});
}
info("Waiting for inspector to update.");
yield inspector.once("inspector-updated");
function endTests() {
executeSoon(() => {
toolbox.destroy();
toolbox = inspector = null;
gBrowser.removeCurrentTab();
finish();
});
info("Inspector updated, performing checks.");
assertNodeSelectedAndPanelsUpdated(getNode("body"), "body");
}
function assertNodeSelectedAndPanelsUpdated(node, crumbLabel) {
// Right node selected?
is(inspector.selection.nodeFront, getNodeFront(node),
"The right node is selected");
// breadcrumbs updated?
let breadcrumbs = inspector.panelDoc.getElementById("inspector-breadcrumbs");
is(breadcrumbs.querySelector("button[checked=true]").textContent, crumbLabel,
"The right breadcrumb is selected");
}
}
});

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

@ -1,77 +1,41 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let Toolbox = devtools.Toolbox;
let TargetFactory = devtools.TargetFactory;
// Test that markup view handles page navigation correctly.
function test() {
const URL_1 = "data:text/html;charset=UTF-8,<div id='one' style='color:red;'>ONE</div>";
const URL_2 = "data:text/html;charset=UTF-8,<div id='two' style='color:green;'>TWO</div>";
const SCHEMA = "data:text/html;charset=UTF-8,";
const URL_1 = SCHEMA + "<div id='one' style='color:red;'>ONE</div>";
const URL_2 = SCHEMA + "<div id='two' style='color:green;'>TWO</div>";
let toolbox, inspector;
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(URL_1);
// open tab, load URL_1, and wait for load to finish
let tab = gBrowser.selectedTab = gBrowser.addTab();
let target = TargetFactory.forTab(gBrowser.selectedTab);
let deferred = promise.defer();
let browser = gBrowser.getBrowserForTab(tab);
let firstNode = getNode("#one");
function onTabLoad() {
browser.removeEventListener("load", onTabLoad, true);
deferred.resolve(null);
}
browser.addEventListener("load", onTabLoad, true);
browser.loadURI(URL_1);
assertMarkupViewIsLoaded();
yield selectNode(firstNode, inspector);
// open devtools panel
deferred.promise.then(() => {
return gDevTools.showToolbox(target, null, Toolbox.HostType.BOTTOM);
}).then(aToolbox => {
toolbox = aToolbox;
}).then(() => {
// select the inspector
return toolbox.selectTool("inspector").then(i => {
inspector = i;
// Verify we are on page one
let testNode = content.document.querySelector("#one");
ok(testNode, "We have the test node on page 1");
let willNavigate = toolbox.target.once("will-navigate");
content.location = URL_2;
assertMarkupViewIsLoaded();
});
}).then(() => {
// navigate to URL_2
let deferred = promise.defer();
info("Waiting for will-navigate");
yield willNavigate;
// Listen to will-navigate to check if the view is empty
target.on("will-navigate", () => {
info("Navigation to page 2 has started, the inspector should be empty");
assertMarkupViewIsEmpty();
});
inspector.once("new-root", () => {
info("Navigation to page 2 was done, the inspector should be back up");
info("Navigation to page 2 has started, the inspector should be empty");
assertMarkupViewIsEmpty();
// Verify we are on page one
let testNode = content.document.querySelector("#two");
ok(testNode, "We have the test node on page 2");
info("Waiting for new-root");
yield inspector.once("new-root");
// On page 2 load, verify we have the right content
assertMarkupViewIsLoaded();
info("Checking that the page has node #two.");
let secondNode = getNode("#two");
inspector.selection.setNode(content.document.querySelector("#two"));
inspector.once("inspector-updated", () => {
deferred.resolve();
});
});
info("Navigation to page 2 was done, the inspector should be back up");
assertMarkupViewIsLoaded();
inspector.selection.setNode(content.document.querySelector("#one"));
inspector.once("inspector-updated", () => {
browser.loadURI(URL_2);
});
return deferred.promise;
}).then(() => {
endTests();
});
yield selectNode(secondNode, inspector);
function assertMarkupViewIsLoaded() {
let markupViewBox = inspector.panelDoc.getElementById("markup-box");
@ -82,10 +46,4 @@ function test() {
let markupViewBox = inspector.panelDoc.getElementById("markup-box");
is(markupViewBox.childNodes.length, 0, "The markup-view is unloaded");
}
function endTests() {
target = browser = tab = inspector = TargetFactory = Toolbox = null;
gBrowser.removeCurrentTab();
finish();
}
}
});

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

@ -1,55 +1,39 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let doc;
let toolbox;
// Testing that clicking the pick button switches the toolbox to the inspector
// panel.
function test() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(startTests, content);
}, true);
const TEST_URI = "data:text/html;charset=UTF-8," +
"<p>Switch to inspector on pick</p>";
content.location = "data:text/html,<p>Switch to inspector on pick</p>";
let test = asyncTest(function* () {
let tab = yield addTab(TEST_URI);
let toolbox = yield openToolbox(tab);
yield startPickerAndAssertSwitchToInspector(toolbox);
info("Stoppping element picker.");
yield toolbox.highlighterUtils.stopPicker();
});
function openToolbox(tab) {
info("Opening webconsole.");
let target = TargetFactory.forTab(tab);
return gDevTools.showToolbox(target, "webconsole");
}
function startTests() {
Task.spawn(function() {
yield openToolbox();
yield startPickerAndAssertSwitchToInspector();
yield toolbox.highlighterUtils.stopPicker();
finishTests();
}).then(null, Cu.reportError);
}
function openToolbox() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
return gDevTools.showToolbox(target, "webconsole").then(aToolbox => {
toolbox = aToolbox;
});
}
function startPickerAndAssertSwitchToInspector() {
let deferred = promise.defer();
function* startPickerAndAssertSwitchToInspector(toolbox) {
info("Clicking element picker button.");
let pickButton = toolbox.doc.querySelector("#command-button-pick");
pickButton.click();
toolbox.once("inspector-selected", () => {
is(toolbox.currentToolId, "inspector", "Switched to the inspector");
toolbox.getCurrentPanel().once("inspector-updated", deferred.resolve);
});
return deferred.promise;
}
info("Waiting for inspector to be selected.");
yield toolbox.once("inspector-selected");
is(toolbox.currentToolId, "inspector", "Switched to the inspector");
function finishTests() {
doc = toolbox = null;
gBrowser.removeCurrentTab();
finish();
info("Waiting for inspector to update.");
yield toolbox.getCurrentPanel().once("inspector-updated");
}

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

@ -3,113 +3,77 @@
/* 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/. */
"use strict";
// Test that hovering over the markup-view's containers doesn't always show the
// highlighter, depending on the type of node hovered over.
let {devtools} = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
let {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const TEST_PAGE = TEST_URL_ROOT +
"browser_inspector_bug_958456_highlight_comments.html";
const TEST_PAGE = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_bug_958456_highlight_comments.html";
let inspector, markupView, doc;
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_PAGE);
let markupView = inspector.markup;
yield selectNode("p", inspector);
function test() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
info("Hovering over #id1 and waiting for highlighter to appear.");
yield hoverElement("#id1");
assertHighlighterShownOn("#id1");
waitForFocus(function() {
openInspector((aInspector, aToolbox) => {
inspector = aInspector;
markupView = inspector.markup;
startTests();
});
}, content);
}, true);
content.location = TEST_PAGE;
}
info("Hovering over comment node and ensuring highlighter doesn't appear.");
yield hoverComment();
assertHighlighterHidden();
function startTests() {
Task.spawn(function() {
yield prepareHighlighter();
info("Hovering over #id1 again and waiting for highlighter to appear.");
yield hoverElement("#id1");
assertHighlighterShownOn("#id1");
// Highlighter should be shown on this element
yield hoverElement("#id1");
assertHighlighterShownOn("#id1");
info("Hovering over #id2 and waiting for highlighter to appear.");
yield hoverElement("#id2");
assertHighlighterShownOn("#id2");
// But not over a comment
yield hoverComment();
assertHighlighterHidden();
info("Hovering over <script> and ensuring highlighter doesn't appear.");
yield hoverElement("script");
assertHighlighterHidden();
// It should be shown again when coming back to the same element tough
yield hoverElement("#id1");
assertHighlighterShownOn("#id1");
info("Hovering over #id3 and waiting for highlighter to appear.");
yield hoverElement("#id3");
assertHighlighterShownOn("#id3");
// Shown here too
yield hoverElement("#id2");
assertHighlighterShownOn("#id2");
info("Hovering over hidden #id4 and ensuring highlighter doesn't appear.");
yield hoverElement("#id4");
assertHighlighterHidden();
// But not over a script tag
yield hoverElement("script");
assertHighlighterHidden();
function hoverContainer(container) {
let promise = inspector.toolbox.once("node-highlight");
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
markupView.doc.defaultView);
// Shown here
yield hoverElement("#id3");
assertHighlighterShownOn("#id3");
return promise;
}
// But not over a hidden element
yield hoverElement("#id4");
assertHighlighterHidden();
}).then(null, Cu.reportError).then(finishTest);
}
function hoverElement(selector) {
info("Hovering node " + selector + " in the markup view");
let container = getContainerForRawNode(markupView, getNode(selector));
return hoverContainer(container);
}
function finishTest() {
doc = inspector = markupView = null;
gBrowser.removeCurrentTab();
finish();
}
function prepareHighlighter() {
// Make sure the highlighter doesn't have transitions enabled
let deferred = promise.defer();
inspector.selection.setNode(doc.querySelector("p"), null);
inspector.once("inspector-updated", () => {
deferred.resolve();
});
return deferred.promise;
}
function hoverContainer(container) {
let deferred = promise.defer();
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
markupView.doc.defaultView);
inspector.toolbox.once("node-highlight", deferred.resolve);
return deferred.promise;
}
function hoverElement(selector) {
info("Hovering node " + selector + " in the markup view");
let container = getContainerForRawNode(markupView, doc.querySelector(selector));
return hoverContainer(container);
}
function hoverComment() {
info("Hovering the comment node in the markup view");
for (let [node, container] of markupView._containers) {
if (node.nodeType === Ci.nsIDOMNode.COMMENT_NODE) {
return hoverContainer(container);
function hoverComment() {
info("Hovering the comment node in the markup view");
for (let [node, container] of markupView._containers) {
if (node.nodeType === Ci.nsIDOMNode.COMMENT_NODE) {
return hoverContainer(container);
}
}
}
}
function assertHighlighterShownOn(selector) {
let node = doc.querySelector(selector);
let highlightNode = getHighlitNode();
is(node, highlightNode, "Highlighter is shown on the right node: " + selector);
}
function assertHighlighterShownOn(selector) {
let node = getNode(selector);
let highlightNode = getHighlitNode();
is(node, highlightNode, "Highlighter is shown on the right node: " + selector);
}
function assertHighlighterHidden() {
ok(!isHighlighting(), "Highlighter is hidden");
}
function assertHighlighterHidden() {
ok(!isHighlighting(), "Highlighter is hidden");
}
});

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

@ -1,38 +1,27 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
"use strict";
// Test that the highlighter's picker should be stopped when a different tool is
// Test that the highlighter's picker is stopped when a different tool is
// selected
function test() {
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const TEST_URI = "data:text/html;charset=UTF-8," +
"testing the highlighter goes away on tool selection";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
content.location = "data:text/html,testing the highlighter goes away on tool selection";
let test = asyncTest(function* () {
let { toolbox } = yield openInspectorForURL(TEST_URI);
let pickerStopped = toolbox.once("picker-stopped");
function setupTest() {
openInspector((aInspector, toolbox) => {
let pickerStopped = toolbox.once("picker-stopped");
info("Starting the inspector picker");
yield toolbox.highlighterUtils.startPicker();
Task.spawn(function() {
info("Starting the inspector picker");
yield toolbox.highlighterUtils.startPicker();
info("Selecting another tool than the inspector in the toolbox");
yield toolbox.selectNextTool();
info("Waiting for the picker-stopped event to be fired")
yield pickerStopped;
ok(true, "picker-stopped event fired after switch tools, so picker is closed");
}).then(null, ok.bind(null, false)).then(finishUp);
});
}
info("Selecting another tool than the inspector in the toolbox");
yield toolbox.selectNextTool();
function finishUp() {
gBrowser.removeCurrentTab();
finish();
}
}
info("Waiting for the picker-stopped event to be fired");
yield pickerStopped;
ok(true, "picker-stopped event fired after switch tools; picker is closed");
});

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

@ -1,43 +1,30 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
"use strict";
// Test that the highlighter's picker should be stopped when the toolbox is
// closed
function test() {
let {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
const TEST_URI = "data:text/html;charset=utf-8," +
"<p>testing the highlighter goes away on destroy</p>";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(runTest, content);
}, true);
content.location = "data:text/html,<p>testing the highlighter goes away on destroy</p>";
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
let pickerStopped = toolbox.once("picker-stopped");
function runTest() {
openInspector((inspector, toolbox) => {
let pickerStopped = toolbox.once("picker-stopped");
yield selectNode("p", inspector);
Task.spawn(function() {
// Selecting a node and waiting for inspector-updated event gives the
// inspector a chance to fully update its side-panels and therefore
// avoids errors when removing the tab (due to ongoing requests)
yield inspector.selection.setNode(content.document.querySelector("p"));
yield inspector.once("inspector-updated");
info("inspector displayed and ready, starting the picker");
yield toolbox.highlighterUtils.startPicker();
info("destroying the toolbox");
yield toolbox.destroy();
info("waiting for the picker-stopped event that should be fired when the toolbox is destroyed");
yield pickerStopped;
ok(true, "picker-stopped event fired after switch tools, so picker is closed");
}).then(null, ok.bind(null, false)).then(finishUp);
});
}
info("Inspector displayed and ready, starting the picker.");
yield toolbox.highlighterUtils.startPicker();
function finishUp() {
gBrowser.removeCurrentTab();
finish();
}
}
info("Destroying the toolbox.");
yield toolbox.destroy();
info("Waiting for the picker-stopped event that should be fired when the " +
"toolbox is destroyed.");
yield pickerStopped;
ok(true, "picker-stopped event fired after switch tools, so picker is closed.");
});

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

@ -1,13 +1,14 @@
/* vim: set 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 inspect command works as it should
// Testing that the gcli 'inspect' command works as it should.
const TEST_URI = "http://example.com/browser/browser/devtools/inspector/" +
"test/browser_inspector_cmd_inspect.html";
const TEST_URI = TEST_URL_ROOT + "browser_inspector_cmd_inspect.html";
function test() {
helpers.addTabWithToolbar(TEST_URI, function(options) {
let test = asyncTest(function* () {
return helpers.addTabWithToolbar(TEST_URI, function(options) {
return helpers.audit(options, [
{
setup: "inspect",
@ -128,6 +129,6 @@ function test() {
status: 'VALID'
},
},
]);
}).then(finish);
}
]); // helpers.audit
}); // helpers.addTabWithToolbar
}); // asyncTest

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

@ -12,24 +12,24 @@
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe.remove();
yay.textContent = "before events";
document.addEventListener("DOMContentLoaded", function() {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe.remove();
yay.textContent = "DOMContentLoaded";
});
window.addEventListener("load", function() {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe.remove();
yay.textContent = "load";
});
</script>
</body>
</html>
</html>

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

@ -1,54 +1,40 @@
/* Any copyright", " is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
let contentTab, contentDoc, inspector;
// Testing that the inspector doesn't go blank when navigating to a page that
// deletes an iframe while loading.
// Create a tab
contentTab = gBrowser.selectedTab = gBrowser.addTab();
const TEST_URL = TEST_URL_ROOT + "browser_inspector_dead_node_exception.html";
// Open the toolbox's inspector first
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
inspector = toolbox.getCurrentPanel();
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL("about:blank");
inspector.selection.setNode(content.document.querySelector("body"));
inspector.once("inspector-updated", () => {
is(inspector.selection.node.tagName, "BODY", "Inspector displayed");
yield selectNode("body", inspector);
// Then load our test page
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
contentDoc = content.document;
let loaded = once(gBrowser.selectedBrowser, "load", true);
content.location = TEST_URL;
// The content doc contains a script that creates an iframe and deletes
// it immediately after. This is what used to make the inspector go
// blank when navigating to that page.
info("Waiting for test page to load.");
yield loaded;
var iframe = contentDoc.createElement("iframe");
contentDoc.body.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
// The content doc contains a script that creates an iframe and deletes
// it immediately after. This is what used to make the inspector go
// blank when navigating to that page.
info("Creating and removing an iframe.");
var iframe = content.document.createElement("iframe");
content.document.body.appendChild(iframe);
iframe.remove();
is(contentDoc.querySelector("iframe"), null, "Iframe has been removed");
ok(!getNode("iframe", {expectNoMatch: true}), "Iframe has been removed.");
inspector.once("markuploaded", () => {
// Assert that the markup-view is displayed and works
is(contentDoc.querySelector("iframe"), null, "Iframe has been removed");
is(contentDoc.getElementById("yay").textContent, "load", "Load event fired");
info("Waiting for markup-view to load.");
yield inspector.once("markuploaded");
inspector.selection.setNode(contentDoc.getElementById("yay"));
inspector.once("inspector-updated", () => {
ok(inspector.selection.node, "Inspector still displayed");
// Assert that the markup-view is displayed and works
ok(!getNode("iframe", {expectNoMatch: true}), "Iframe has been removed.");
is(getNode("#yay").textContent, "load", "Load event fired.");
// Clean up and go
contentTab, contentDoc, inspector = null;
gBrowser.removeTab(contentTab);
finish();
});
});
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/" +
"inspector/test/browser_inspector_dead_node_exception.html";
});
});
}
yield selectNode("#yay", inspector);
});

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

@ -1,50 +1,26 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test()
{
let node, iframe, inspector;
// Test to ensure inspector can handle destruction of selected node inside an
// iframe.
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(setupTest, content);
}, true);
const TEST_URL = TEST_URL_ROOT + "browser_inspector_destroyselection.html";
content.location = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_destroyselection.html";
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
function setupTest()
{
iframe = content.document.querySelector("iframe");
node = iframe.contentDocument.querySelector("span");
openInspector(runTests);
}
let iframe = getNode("iframe");
let node = getNode("span", { document: iframe.contentDocument });
yield selectNode(node, inspector);
function runTests(aInspector)
{
inspector = aInspector;
inspector.selection.setNode(node);
info("Removing iframe.");
iframe.remove();
inspector.once("inspector-updated", () => {
iframe.parentNode.removeChild(iframe);
iframe = null;
let tmp = {};
Cu.import("resource://gre/modules/devtools/LayoutHelpers.jsm", tmp);
let lh = new tmp.LayoutHelpers(window.content);
ok(!lh.isNodeConnected(node), "Node considered as disconnected.");
ok(!inspector.selection.isConnected(), "Selection considered as disconnected");
inspector.once("inspector-updated", () => {
finishUp();
});
});
}
function finishUp() {
node = inspector = null;
gBrowser.removeCurrentTab();
finish();
}
}
let lh = new LayoutHelpers(window.content);
ok(!lh.isNodeConnected(node), "Node considered as disconnected.");
ok(!inspector.selection.isConnected(), "Selection considered as disconnected.");
yield inspector.once("inspector-updated");
});

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

@ -8,15 +8,10 @@
// Test that the highlighter is correctly displayed over a variety of elements
const TEST_URI = TEST_URL_ROOT + "browser_inspector_highlighter.html";
let test = asyncTest(function*() {
const TEST_URI = "http://example.com/browser/browser/devtools/inspector/" +
"test/browser_inspector_highlighter.html";
info("Opening the document");
yield addTab(TEST_URI);
info("Opening the inspector");
let {toolbox, inspector} = yield openInspector();
let { inspector } = yield openInspectorForURL(TEST_URI);
info("Selecting the simple, non-transformed DIV");
let div = getNode("#simple-div");
@ -43,7 +38,6 @@ let test = asyncTest(function*() {
testMouseOverWidthHeightZeroDiv(zeroWidthHeight);
gBrowser.removeCurrentTab();
});
function testSimpleDivHighlighted(div) {

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

@ -3,109 +3,55 @@
/* 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/. */
"use strict";
let doc;
let div1;
let div2;
let iframe1;
let iframe2;
let inspector;
// Testing that moving the mouse over the document with the element picker
// started highlights nodes
function createDocument() {
doc.title = "Inspector iframe Tests";
const NESTED_FRAME_SRC = "data:text/html;charset=utf-8," +
"nested iframe<div>nested div</div>";
iframe1 = doc.createElement('iframe');
const OUTER_FRAME_SRC = "data:text/html;charset=utf-8," +
"little frame<div>little div</div>" +
"<iframe src='" + NESTED_FRAME_SRC + "' />";
iframe1.addEventListener("load", function () {
iframe1.removeEventListener("load", arguments.callee, false);
const TEST_URI = "data:text/html;charset=utf-8," +
"iframe tests for inspector" +
"<iframe src=\"" + OUTER_FRAME_SRC + "\" />";
div1 = iframe1.contentDocument.createElement('div');
div1.textContent = 'little div';
iframe1.contentDocument.body.appendChild(div1);
let test = asyncTest(function*() {
let { inspector } = yield openInspectorForURL(TEST_URI);
let outerFrame = getNode("iframe");
let outerFrameDiv = getNode("div", { document: outerFrame.contentDocument});
let innerFrame = getNode("iframe", { document: outerFrame.contentDocument});
let innerFrameDiv = getNode("div", { document: innerFrame.contentDocument});
iframe2 = iframe1.contentDocument.createElement('iframe');
info("Waiting for element picker to activate.");
yield inspector.toolbox.highlighterUtils.startPicker();
iframe2.addEventListener('load', function () {
iframe2.removeEventListener("load", arguments.callee, false);
info("Moving mouse over outerFrameDiv");
yield moveMouseOver(outerFrameDiv);
is(getHighlitNode(), outerFrameDiv, "outerFrameDiv is highlighted.");
div2 = iframe2.contentDocument.createElement('div');
div2.textContent = 'nested div';
iframe2.contentDocument.body.appendChild(div2);
info("Moving mouse over innerFrameDiv");
yield moveMouseOver(innerFrameDiv);
is(getHighlitNode(), innerFrameDiv, "innerFrameDiv is highlighted.");
// Open the inspector, start the picker mode, and start the tests
openInspector(aInspector => {
inspector = aInspector;
inspector.toolbox.highlighterUtils.startPicker().then(runTests);
});
}, false);
info("Selecting root node");
yield selectNode(content.document.documentElement, inspector);
iframe2.src = 'data:text/html,nested iframe';
iframe1.contentDocument.body.appendChild(iframe2);
}, false);
info("Selecting an element from the nested iframe directly");
yield selectNode(innerFrameDiv, inspector);
iframe1.src = 'data:text/html,little iframe';
doc.body.appendChild(iframe1);
}
is(inspector.breadcrumbs.nodeHierarchy.length, 9, "Breadcrumbs have 9 items.");
function moveMouseOver(aElement, cb) {
inspector.toolbox.once("picker-node-hovered", cb);
EventUtils.synthesizeMouseAtCenter(aElement, {type: "mousemove"},
aElement.ownerDocument.defaultView);
}
info("Waiting for element picker to deactivate.");
yield inspector.toolbox.highlighterUtils.stopPicker();
function runTests() {
testDiv1Highlighter();
}
function testDiv1Highlighter() {
moveMouseOver(div1, () => {
is(getHighlitNode(), div1, "highlighter matches selection of div1");
testDiv2Highlighter();
});
}
function testDiv2Highlighter() {
moveMouseOver(div2, () => {
is(getHighlitNode(), div2, "highlighter matches selection of div2");
selectRoot();
});
}
function selectRoot() {
// Select the root document element to clear the breadcrumbs.
inspector.selection.setNode(doc.documentElement, null);
inspector.once("inspector-updated", selectIframe);
}
function selectIframe() {
// Directly select an element in an iframe (without navigating to it
// with mousemoves).
inspector.selection.setNode(div2, null);
inspector.once("inspector-updated", () => {
let breadcrumbs = inspector.breadcrumbs;
is(breadcrumbs.nodeHierarchy.length, 9, "Should have 9 items");
finishUp();
});
}
function finishUp() {
inspector.toolbox.highlighterUtils.stopPicker().then(() => {
doc = div1 = div2 = iframe1 = iframe2 = inspector = null;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
gBrowser.removeCurrentTab();
finish();
});
}
function test() {
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
gBrowser.selectedBrowser.focus();
createDocument();
}, true);
content.location = "data:text/html,iframe tests for inspector";
}
function moveMouseOver(element) {
info("Waiting for element " + element + " to be highlighted");
EventUtils.synthesizeMouseAtCenter(element, {type: "mousemove"},
element.ownerDocument.defaultView);
return inspector.toolbox.once("picker-node-hovered");
}
});

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

@ -3,138 +3,122 @@
/* 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/. */
let doc;
let salutation;
"use strict";
function createDocument()
{
doc.body.innerHTML = '<div id="first" style="{ margin: 10em; ' +
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA}">\n' +
'<h1>Some header text</h1>\n' +
'<p id="salutation" style="{font-size: 12pt}">hi.</p>\n' +
'<p id="body" style="{font-size: 12pt}">I am a test-case. This text exists ' +
'solely to provide some things to test the inspector initialization.</p>\n' +
'If you are reading this, you should go do something else instead. Maybe ' +
'read a book. Or better yet, write some test-cases for another bit of code. ' +
'<span style="{font-style: italic}">Inspector\'s!</span></p>\n' +
'<p id="closing">end transmission</p>\n' +
'</div>';
doc.title = "Inspector Initialization Test";
// Tests for different ways to initialize the inspector.
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
startInspectorTests(toolbox);
}).then(null, console.error);
}
const DOCUMENT_HTML = '<div id="first" style="{margin: 10em; font-size: 14pt;' +
'font-family: helvetica, sans-serif; color: #AAA}">\n' +
'<h1>Some header text</h1>\n' +
'<p id="salutation" style="{font-size: 12pt}">hi.</p>\n' +
'<p id="body" style="{font-size: 12pt}">I am a test-case. This text exists ' +
'solely to provide some things to test the inspector initialization.</p>\n' +
'If you are reading this, you should go do something else instead. Maybe ' +
'read a book. Or better yet, write some test-cases for another bit of code. ' +
'<span style="{font-style: italic}">Inspector\'s!</span></p>\n' +
'<p id="closing">end transmission</p>\n' +
'</div>';
function startInspectorTests(toolbox)
{
const TEST_URI = "data:text/html;charset=utf-8," +
"browser_inspector_initialization.js";
let test = asyncTest(function* () {
let tab = yield addTab(TEST_URI);
content.document.body.innerHTML = DOCUMENT_HTML;
content.document.title = "Inspector Initialization Test";
yield testToolboxInitialization(tab);
yield testContextMenuInitialization();
yield testContextMenuInspectorAlreadyOpen();
});
function* testToolboxInitialization(tab) {
let target = TargetFactory.forTab(tab);
info("Opening inspector with gDevTools.");
let toolbox = yield gDevTools.showToolbox(target, "inspector");
let inspector = toolbox.getCurrentPanel();
ok(true, "Inspector started, and notification received.");
ok(inspector, "Inspector instance is accessible.");
ok(inspector.isReady, "Inspector instance is ready.");
is(inspector.target.tab, tab, "Valid target.");
ok(inspector, "Inspector instance is accessible");
ok(inspector.isReady, "Inspector instance is ready");
is(inspector.target.tab, gBrowser.selectedTab, "Valid target");
let p = getNode("p");
yield selectNode(p, inspector);
testMarkupView(p, inspector);
testBreadcrumbs(p, inspector);
let p = doc.querySelector("p");
let span = getNode("span");
span.scrollIntoView();
inspector.selection.setNode(p);
inspector.once("inspector-updated", () => {
testMarkupView(p);
testBreadcrumbs(p);
yield selectNode(span, inspector);
testMarkupView(span, inspector);
testBreadcrumbs(span, inspector);
let span = doc.querySelector("span");
span.scrollIntoView();
info("Destroying toolbox");
let destroyed = toolbox.once("destroyed");
toolbox.destroy();
yield destroyed;
inspector.selection.setNode(span);
inspector.once("inspector-updated", () => {
testMarkupView(span);
testBreadcrumbs(span);
toolbox.once("destroyed", function() {
ok("true", "'destroyed' notification received.");
let target = TargetFactory.forTab(gBrowser.selectedTab);
ok(!gDevTools.getToolbox(target), "Toolbox destroyed.");
executeSoon(runContextMenuTest);
});
toolbox.destroy();
});
});
ok("true", "'destroyed' notification received.");
ok(!gDevTools.getToolbox(target), "Toolbox destroyed.");
}
let callNo = 0;
function testMarkupView(node)
{
let i = getActiveInspector();
function* testContextMenuInitialization() {
info("Opening inspector by clicking on 'Inspect Element' context menu item");
let salutation = getNode("#salutation");
yield clickOnInspectMenuItem(salutation);
info("Checking inspector state.");
testMarkupView(salutation);
testBreadcrumbs(salutation);
}
function* testContextMenuInspectorAlreadyOpen() {
info("Changing node by clicking on 'Inspect Element' context menu item");
let inspector = getActiveInspector();
ok(inspector, "Inspector is active");
let closing = getNode("#closing");
yield clickOnInspectMenuItem(closing);
ok(true, "Inspector was updated when 'Inspect Element' was clicked.");
testMarkupView(closing, inspector);
testBreadcrumbs(closing, inspector);
}
function testMarkupView(node, inspector) {
inspector = inspector || getActiveInspector();
try {
is(i.markup._selectedContainer.node.rawNode(), node, "Right node is selected in the markup view");
} catch(ex) { console.error(ex); }
is(inspector.markup._selectedContainer.node.rawNode(), node,
"Right node is selected in the markup view");
} catch(ex) {
ok(false, "Got exception while resolving selected node of markup view.");
console.error(ex);
}
}
function testBreadcrumbs(node)
{
let b = getActiveInspector().breadcrumbs;
function testBreadcrumbs(node, inspector) {
inspector = inspector || getActiveInspector();
let b = inspector.breadcrumbs;
let expectedText = b.prettyPrintNodeAsText(getNodeFront(node));
let button = b.container.querySelector("button[checked=true]");
ok(button, "A crumbs is checked=true");
is(button.getAttribute("tooltiptext"), expectedText, "Crumb refers to the right node");
}
function _clickOnInspectMenuItem(node) {
function* clickOnInspectMenuItem(node) {
info("Clicking on 'Inspect Element' context menu item of " + node);
document.popupNode = node;
var contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
var contentAreaContextMenu = getNode("#contentAreaContextMenu", { document });
var contextMenu = new nsContextMenu(contentAreaContextMenu);
var {Promise: promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
var deferred = promise.defer();
contextMenu.inspectNode().then(() => {
let i = getActiveInspector();
i.once("inspector-updated", () => {
deferred.resolve(undefined);
});
});
return deferred.promise;
}
function runContextMenuTest()
{
salutation = doc.getElementById("salutation");
_clickOnInspectMenuItem(salutation).then(testInitialNodeIsSelected);
}
info("Triggering inspect action.");
yield contextMenu.inspectNode();
function testInitialNodeIsSelected() {
testMarkupView(salutation);
testBreadcrumbs(salutation);
inspectNodesFromContextTestWhileOpen();
}
function inspectNodesFromContextTestWhileOpen()
{
let closing = doc.getElementById("closing");
getActiveInspector().selection.once("new-node", function() {
ok(true, "Get selection's 'new-node' selection");
executeSoon(function() {
testMarkupView(closing);
testBreadcrumbs(closing);
getActiveInspector().once("inspector-updated", finishInspectorTests)
}
)});
_clickOnInspectMenuItem(closing);
}
function finishInspectorTests(subject, topic, aWinIdString)
{
gBrowser.removeCurrentTab();
finish();
}
function test()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_initialization.js";
info("Waiting for inspector to update.");
yield getActiveInspector().once("inspector-updated");
}

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

@ -1,54 +1,33 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
function test() {
let doc;
let div;
let inspector;
// Test that highlighter handles geometry changes correctly.
const TEST_URI = "data:text/html;charset=utf-8," +
"browser_inspector_invalidate.js\n" +
"<div style=\"width: 100px; height: 100px; background:yellow;\"></div>";
function createDocument() {
div = doc.createElement("div");
div.setAttribute("style", "width: 100px; height: 100px; background:yellow;");
doc.body.appendChild(div);
let test = asyncTest(function*() {
let { inspector } = yield openInspectorForURL(TEST_URI);
let div = getNode("div");
openInspector(aInspector => {
inspector = aInspector;
inspector.toolbox.highlighter.showBoxModel(getNodeFront(div)).then(runTest);
});
}
info("Waiting for highlighter to activate");
yield inspector.toolbox.highlighter.showBoxModel(getNodeFront(div));
function runTest() {
info("Checking that the highlighter has the right size");
let rect = getSimpleBorderRect();
is(rect.width, 100, "outline has the right width");
let rect = getSimpleBorderRect();
is(rect.width, 100, "Outline has the right width.");
waitForBoxModelUpdate().then(testRectWidth);
info("Changing the test element's size");
let boxModelUpdated = waitForBoxModelUpdate();
div.style.width = "200px";
info("Changing the test element's size");
div.style.width = "200px";
}
info("Waiting for the box model to update.");
yield boxModelUpdated;
function testRectWidth() {
info("Checking that the highlighter has the right size after update");
let rect = getSimpleBorderRect();
is(rect.width, 200, "outline updated");
finishUp();
}
rect = getSimpleBorderRect();
is(rect.width, 200, "Outline has the right width after update.");
function finishUp() {
inspector.toolbox.highlighter.hideBoxModel().then(() => {
doc = div = inspector = null;
gBrowser.removeCurrentTab();
finish();
});
}
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_invalidate.js";
}
info("Waiting for highlighter to hide");
yield inspector.toolbox.highlighter.hideBoxModel();
});

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

@ -1,218 +1,210 @@
/* vim: set 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 context menu functionality:
// 1) menu items are disabled/enabled depending on the clicked node
// 2) actions triggered by the items work correctly
function test() {
let clipboard = require("sdk/clipboard");
let doc;
let inspector;
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
doc = content.document;
waitForFocus(setupTest, content);
}, true);
content.location = "http://mochi.test:8888/browser/browser/devtools/" +
"inspector/test/browser_inspector_menu.html";
function setupTest() {
openInspector(runTests);
const TEST_URL = TEST_URL_ROOT + "browser_inspector_menu.html";
const MENU_SENSITIVITY_TEST_DATA = [
{
desc: "doctype node",
selector: null,
disabled: true,
},
{
desc: "element node",
selector: "p",
disabled: false,
}
];
function runTests(aInspector) {
inspector = aInspector;
checkDocTypeMenuItems();
}
function checkDocTypeMenuItems() {
info("Checking context menu entries for doctype node");
inspector.selection.setNode(doc.doctype);
inspector.once("inspector-updated", () => {
let docTypeNode = getMarkupTagNodeContaining("<!DOCTYPE html>");
// Right-click doctype tag
contextMenuClick(docTypeNode);
checkDisabled("node-menu-copyinner");
checkDisabled("node-menu-copyouter");
checkDisabled("node-menu-copyuniqueselector");
checkDisabled("node-menu-delete");
checkDisabled("node-menu-pasteouterhtml");
for (let name of ["hover", "active", "focus"]) {
checkDisabled("node-menu-pseudo-" + name);
}
checkElementMenuItems();
});
}
function checkElementMenuItems() {
info("Checking context menu entries for p tag");
inspector.selection.setNode(doc.querySelector("p"));
inspector.once("inspector-updated", () => {
let tag = getMarkupTagNodeContaining("p");
// Right-click p tag
contextMenuClick(tag);
checkEnabled("node-menu-copyinner");
checkEnabled("node-menu-copyouter");
checkEnabled("node-menu-copyuniqueselector");
checkEnabled("node-menu-delete");
for (let name of ["hover", "active", "focus"]) {
checkEnabled("node-menu-pseudo-" + name);
}
checkElementPasteOuterHTMLMenuItemForText();
});
}
function checkPasteOuterHTMLMenuItem(data, type, check, next) {
clipboard.set(data, type);
inspector.selection.setNode(doc.querySelector("p"));
inspector.once("inspector-updated", () => {
contextMenuClick(getMarkupTagNodeContaining("p"));
check("node-menu-pasteouterhtml");
next();
});
}
function checkElementPasteOuterHTMLMenuItemForText() {
checkPasteOuterHTMLMenuItem(
"some text",
undefined,
checkEnabled,
checkElementPasteOuterHTMLMenuItemForImage);
}
function checkElementPasteOuterHTMLMenuItemForImage() {
checkPasteOuterHTMLMenuItem(
const PASTE_OUTER_HTML_TEST_DATA = [
{
desc: "some text",
clipboardData: "some text",
clipboardDataType: undefined,
disabled: false
},
{
desc: "base64 encoded image data uri",
clipboardData:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABC" +
"AAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJggg==",
undefined,
checkDisabled,
checkElementPasteOuterHTMLMenuItemForHTML);
clipboardDataType: undefined,
disabled: true
},
{
desc: "html",
clipboardData: "<p>some text</p>",
clipboardDataType: "html",
disabled: false
},
{
desc: "empty string",
clipboardData: "",
clipboardDataType: undefined,
disabled: true
},
{
desc: "whitespace only",
clipboardData: " \n\n\t\n\n \n",
clipboardDataType: undefined,
disabled: true
},
];
const COPY_ITEMS_TEST_DATA = [
{
desc: "copy inner html",
id: "node-menu-copyinner",
text: "This is some example text",
},
{
desc: "copy outer html",
id: "node-menu-copyouter",
text: "<p>This is some example text</p>",
},
{
desc: "copy unique selector",
id: "node-menu-copyuniqueselector",
text: "body > div:nth-child(1) > p:nth-child(2)",
},
];
let clipboard = devtools.require("sdk/clipboard");
registerCleanupFunction(() => {
clipboard = null;
});
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL);
yield testMenuItemSensitivity();
yield testPasteOuterHTMLMenuItemSensitivity();
yield testCopyMenuItems();
yield testPasteOuterHTMLMenu();
yield testDeleteNode();
yield testDeleteRootNode();
function* testMenuItemSensitivity() {
info("Testing sensitivity of menu items for different elements.");
const MENU_ITEMS = [
"node-menu-copyinner",
"node-menu-copyouter",
"node-menu-copyuniqueselector",
"node-menu-delete",
"node-menu-pasteouterhtml",
"node-menu-pseudo-hover",
"node-menu-pseudo-active",
"node-menu-pseudo-focus"
];
// To ensure clipboard contains something to paste.
clipboard.set("<p>test</p>", "html");
for (let {desc, selector, disabled} of MENU_SENSITIVITY_TEST_DATA) {
info("Testing context menu entries for " + desc);
let node = getNode(selector) || content.document.doctype;
yield selectNode(node, inspector);
contextMenuClick(getContainerForRawNode(inspector.markup, node).tagLine);
for (let name of MENU_ITEMS) {
checkMenuItem(name, disabled);
}
}
}
function checkElementPasteOuterHTMLMenuItemForHTML() {
checkPasteOuterHTMLMenuItem(
"<p>some text</p>",
"html",
checkEnabled,
checkElementPasteOuterHTMLMenuItemForEmptyString);
function* testPasteOuterHTMLMenuItemSensitivity() {
info("Checking 'Paste Outer HTML' menu item sensitivity for different types" +
"of data");
let node = getNode("p");
let markupTagLine = getContainerForRawNode(inspector.markup, node).tagLine;
for (let data of PASTE_OUTER_HTML_TEST_DATA) {
let { desc, clipboardData, clipboardDataType, disabled } = data;
info("Checking 'Paste Outer HTML' for " + desc);
clipboard.set(clipboardData, clipboardDataType);
yield selectNode(node, inspector);
contextMenuClick(markupTagLine);
checkMenuItem("node-menu-pasteouterhtml", disabled);
}
}
function checkElementPasteOuterHTMLMenuItemForEmptyString() {
checkPasteOuterHTMLMenuItem(
"",
undefined,
checkDisabled,
checkElementPasteOuterHTMLMenuItemForWhitespaceOnly);
function* testCopyMenuItems() {
info("Testing various copy actions of context menu.");
for (let {desc, id, text} of COPY_ITEMS_TEST_DATA) {
info("Testing " + desc);
let item = inspector.panelDoc.getElementById(id);
ok(item, "The popup has a " + desc + " menu item.");
let deferred = promise.defer();
waitForClipboard(text, () => item.doCommand(),
deferred.resolve, deferred.reject);
yield deferred.promise;
}
}
function checkElementPasteOuterHTMLMenuItemForWhitespaceOnly() {
checkPasteOuterHTMLMenuItem(
" \n\n\t\n\n \n",
undefined,
checkDisabled,
testCopyInnerMenu);
}
function testCopyInnerMenu() {
let copyInner = inspector.panelDoc.getElementById("node-menu-copyinner");
ok(copyInner, "the popup menu has a copy inner html menu item");
waitForClipboard("This is some example text",
function() { copyInner.doCommand(); },
testCopyOuterMenu, testCopyOuterMenu);
}
function testCopyOuterMenu() {
let copyOuter = inspector.panelDoc.getElementById("node-menu-copyouter");
ok(copyOuter, "the popup menu has a copy outer html menu item");
waitForClipboard("<p>This is some example text</p>",
function() { copyOuter.doCommand(); },
testCopyUniqueSelectorMenu, testCopyUniqueSelectorMenu);
}
function testCopyUniqueSelectorMenu() {
let copyUniqueSelector = inspector.panelDoc.getElementById("node-menu-copyuniqueselector");
ok(copyUniqueSelector, "the popup menu has a copy unique selector menu item");
waitForClipboard("body > div:nth-child(1) > p:nth-child(2)",
function() { copyUniqueSelector.doCommand(); },
testPasteOuterHTMLMenu, testPasteOuterHTMLMenu);
}
function testPasteOuterHTMLMenu() {
function* testPasteOuterHTMLMenu() {
info("Testing that 'Paste Outer HTML' menu item works.");
clipboard.set("this was pasted");
inspector.selection.setNode(doc.querySelector("h1"));
inspector.once("inspector-updated", () => {
contextMenuClick(getMarkupTagNodeContaining("h1"));
let menu = inspector.panelDoc.getElementById("node-menu-pasteouterhtml");
let event = document.createEvent("XULCommandEvent");
event.initCommandEvent("command", true, true, window, 0, false, false,
false, false, null);
menu.dispatchEvent(event);
inspector.selection.once("new-node", (event, oldNode, newNode) => {
ok(doc.body.outerHTML.contains(clipboard.get()),
"Clipboard content was pasted into the node's outer HTML.");
ok(!doc.querySelector("h1"), "The original node was removed.");
testDeleteNode();
});
});
let node = getNode("h1");
yield selectNode(node, inspector);
contextMenuClick(getContainerForRawNode(inspector.markup, node).tagLine);
let menu = inspector.panelDoc.getElementById("node-menu-pasteouterhtml");
dispatchCommandEvent(menu);
info("Waiting for inspector selection to update");
yield inspector.selection.once("new-node");
ok(content.document.body.outerHTML.contains(clipboard.get()),
"Clipboard content was pasted into the node's outer HTML.");
ok(!getNode("h1", { expectNoMatch: true }), "The original node was removed.");
}
function testDeleteNode() {
function* testDeleteNode() {
info("Testing 'Delete Node' menu item for normal elements.");
let deleteNode = inspector.panelDoc.getElementById("node-menu-delete");
ok(deleteNode, "the popup menu has a delete menu item");
inspector.once("inspector-updated", deleteTest);
let updated = inspector.once("inspector-updated");
let commandEvent = document.createEvent("XULCommandEvent");
commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
false, false, null);
deleteNode.dispatchEvent(commandEvent);
info("Triggering 'Delete Node' and waiting for inspector to update");
dispatchCommandEvent(deleteNode);
yield updated;
ok(!getNode("p", { expectNoMatch: true }), "Node deleted");
}
function deleteTest() {
let p = doc.querySelector("P");
is(p, null, "node deleted");
function* testDeleteRootNode() {
info("Testing 'Delete Node' menu item does not delete root node.");
yield selectNode(content.document.documentElement, inspector);
deleteRootNode();
}
let deleteNode = inspector.panelDoc.getElementById("node-menu-delete");
dispatchCommandEvent(deleteNode);
function deleteRootNode() {
inspector.selection.setNode(doc.documentElement);
inspector.once("inspector-updated", () => {
let deleteNode = inspector.panelDoc.getElementById("node-menu-delete");
let commandEvent = inspector.panelDoc.createEvent("XULCommandEvent");
commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
false, false, null);
deleteNode.dispatchEvent(commandEvent);
executeSoon(isRootStillAlive);
executeSoon(() => {
ok(content.document.documentElement, "Document element still alive.");
});
}
function isRootStillAlive() {
ok(doc.documentElement, "Document element still alive.");
gBrowser.removeCurrentTab();
finish();
}
function getMarkupTagNodeContaining(text) {
let tags = inspector._markupFrame.contentDocument.querySelectorAll("span");
for (let tag of tags) {
if (tag.textContent == text) {
return tag;
}
function checkMenuItem(elementId, disabled) {
if (disabled) {
checkDisabled(elementId);
} else {
checkEnabled(elementId);
}
}
@ -228,7 +220,16 @@ function test() {
'"' + elt.label + '" context menu option is disabled');
}
function dispatchCommandEvent(node) {
info("Dispatching command event on " + node);
let commandEvent = document.createEvent("XULCommandEvent");
commandEvent.initCommandEvent("command", true, true, window, 0, false, false,
false, false, null);
node.dispatchEvent(commandEvent);
}
function contextMenuClick(element) {
info("Simulating contextmenu event on " + element);
let evt = element.ownerDocument.createEvent('MouseEvents');
let button = 2; // right click
@ -238,4 +239,4 @@ function test() {
element.dispatchEvent(evt);
}
}
});

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

@ -3,63 +3,41 @@
/* 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/. */
"use strict";
// Test that inspector updates when page is navigated.
function test() {
let inspector, toolbox;
const TEST_URL_FILE = "browser/browser/devtools/inspector/test/" +
"browser_inspector_breadcrumbs.html";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(function() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
startInspectorTests(toolbox);
}).then(null, console.error);
}, content);
}, true);
const TEST_URL_1 = "http://test1.example.org/" + TEST_URL_FILE;
const TEST_URL_2 = "http://test2.example.org/" + TEST_URL_FILE;
content.location = "http://test1.example.org/browser/browser/devtools/inspector/test/browser_inspector_breadcrumbs.html";
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(TEST_URL_1);
let markuploaded = inspector.once("markuploaded");
function startInspectorTests(aToolbox)
{
toolbox = aToolbox;
inspector = toolbox.getCurrentPanel();
info("Inspector started");
let node = content.document.querySelector("#i1");
inspector.selection.setNode(node);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, node, "Node selected.");
inspector.once("markuploaded", onSecondLoad);
content.location = "http://test2.example.org/browser/browser/devtools/inspector/test/browser_inspector_breadcrumbs.html";
});
}
yield selectNode("#i1", inspector);
function onSecondLoad() {
info("New page loaded");
let node = content.document.querySelector("#i1");
inspector.selection.setNode(node);
info("Navigating to a different page.");
content.location = TEST_URL_2;
inspector.once("inspector-updated", () => {
is(inspector.selection.node, node, "Node re-selected.");
inspector.once("markuploaded", onThirdLoad);
content.history.go(-1);
});
}
info("Waiting for markup view to load after navigation.");
yield markuploaded;
function onThirdLoad() {
info("Old page loaded");
is(content.location.href, "http://test1.example.org/browser/browser/devtools/inspector/test/browser_inspector_breadcrumbs.html");
let node = content.document.querySelector("#i1");
inspector.selection.setNode(node);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, node, "Node re-selected.");
inspector.once("markuploaded", onThirdLoad);
toolbox.destroy();
gBrowser.removeCurrentTab();
finish();
});
}
}
ok(true, "New page loaded");
yield selectNode("#i1", inspector);
markuploaded = inspector.once("markuploaded");
info("Going back in history");
content.history.go(-1);
info("Waiting for markup view to load after going back in history.");
yield markuploaded;
ok(true, "Old page loaded");
is(content.location.href, TEST_URL_1, "URL is correct.");
yield selectNode("#i1", inspector);
});

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

@ -1,6 +1,6 @@
/* vim: set 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 the inspector has the correct pseudo-class locking menu items and
@ -25,20 +25,12 @@ let test = asyncTest(function*() {
yield openMenu(menu);
yield testMenuItems(div, menu, inspector);
gBrowser.removeCurrentTab();
});
function openMenu(menu) {
let def = promise.defer();
menu.addEventListener("popupshowing", function onOpen() {
menu.removeEventListener("popupshowing", onOpen, true);
def.resolve();
}, true);
let promise = once(menu, "popupshowing", true);
menu.openPopup();
return def.promise;
return promise;
}
function* testMenuItems(div,menu, inspector) {
@ -49,7 +41,7 @@ function* testMenuItems(div,menu, inspector) {
// Give the inspector panels a chance to update when the pseudoclass changes
let onPseudo = inspector.selection.once("pseudoclass");
let onRefresh = inspector.once("rule-view-refreshed");
let onMutations = waitForMutation(inspector);
let onMutations = inspector.walker.once("mutations");
menuitem.doCommand();
@ -61,9 +53,3 @@ function* testMenuItems(div,menu, inspector) {
"pseudo-class lock has been applied");
}
}
function waitForMutation(inspector) {
let def = promise.defer();
inspector.walker.once("mutations", def.resolve);
return def.promise;
}

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

@ -1,5 +1,7 @@
/* vim: set 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 locking the pseudoclass displays correctly in the ruleview
@ -18,8 +20,8 @@ const TEST_URL = 'data:text/html,' +
let test = asyncTest(function*() {
info("Creating the test tab and opening the rule-view");
yield addTab(TEST_URL);
let {toolbox, inspector, view} = yield openRuleView();
let {toolbox, inspector} = yield openInspectorForURL(TEST_URL);
let view = yield ensureRuleView(inspector);
info("Selecting the test node");
yield selectNode("#div-1", inspector);
@ -37,8 +39,6 @@ let test = asyncTest(function*() {
info("Destroying the toolbox");
yield toolbox.destroy();
yield assertPseudoRemovedFromNode(getNode("#div-1"));
gBrowser.removeCurrentTab();
});
@ -48,7 +48,7 @@ function* togglePseudoClass(inspector) {
// Give the inspector panels a chance to update when the pseudoclass changes
let onPseudo = inspector.selection.once("pseudoclass");
let onRefresh = inspector.once("rule-view-refreshed");
let onMutations = waitForMutation(inspector);
let onMutations = inspector.walker.once("mutations");
yield inspector.togglePseudoClass(PSEUDO);
@ -57,12 +57,6 @@ function* togglePseudoClass(inspector) {
yield onMutations;
}
function waitForMutation(inspector) {
let def = promise.defer();
inspector.walker.once("mutations", def.resolve);
return def.promise;
}
function* testNavigate(inspector, ruleview) {
yield selectNode("#parent-div", inspector);
@ -132,3 +126,15 @@ function* assertPseudoRemovedFromView(inspector, ruleview) {
is(pseudoClassesBox.textContent, "", "pseudo-class removed from infobar selector");
yield inspector.toolbox.highlighter.hideBoxModel();
}
function* ensureRuleView(inspector) {
if (!inspector.sidebar.getWindowForTab("ruleview")) {
info("Waiting for ruleview initialization to complete.");
yield inspector.sidebar.once("ruleview-ready");
}
info("Selecting the ruleview sidebar");
inspector.sidebar.select("ruleview");
return inspector.sidebar.getWindowForTab("ruleview")["ruleview"].view;
}

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

@ -3,51 +3,29 @@
/* 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/. */
"use strict";
// A test to ensure reloading a page doesn't break the inspector.
function test() {
let inspector, toolbox;
// Reload should reselect the currently selected markup view element.
// This should work even when an element whose selector needs escaping
// is selected (bug 1002280).
const TEST_URI = "data:text/html,<p id='1'>p</p>";
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(function() {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.showToolbox(target, "inspector").then(function(toolbox) {
startInspectorTests(toolbox);
}).then(null, console.error);
}, content);
}, true);
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
yield selectNode("p", inspector);
// Reload should reselect the currently selected markup view element.
// This should work even when an element whose selector needs escaping
// is selected (bug 100228).
content.location = "data:text/html,<p id='1'>p</p>";
let markupLoaded = inspector.once("markuploaded");
function startInspectorTests(aToolbox)
{
toolbox = aToolbox;
inspector = toolbox.getCurrentPanel();
info("Inspector started");
let p = content.document.querySelector("p");
inspector.selection.setNode(p);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, p, "Node selected.");
inspector.once("markuploaded", onReload);
content.location.reload();
});
}
info("Reloading page.");
content.location.reload();
function onReload() {
info("Page reloaded");
let p = content.document.querySelector("p");
inspector.selection.setNode(p);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, p, "Node re-selected.");
toolbox.destroy();
toolbox = inspector = null;
gBrowser.removeCurrentTab();
finish();
});
}
}
info("Waiting for markupview to load after reload.");
yield markupLoaded;
is(inspector.selection.node, getNode("p"), "<p> selected after reload.");
info("Selecting a node to see that inspector still works.");
yield selectNode("body", inspector);
});

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

@ -3,74 +3,42 @@
/* 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/. */
"use strict";
let doc;
let div;
let iframe;
let inspector;
// Test that highlighted nodes can be scrolled.
// TODO: This doesn't test anything useful. See b.m.o 1035661.
const IFRAME_SRC = "data:text/html;charset=utf-8," +
"<div style='height:500px; width:500px; border:1px solid gray;'>" +
"big div" +
"</div>";
function createDocument()
{
doc.title = "Inspector scrolling Tests";
const TEST_URI = "data:text/html;charset=utf-8," +
"<p>browser_inspector_scrolling.js</p>" +
"<iframe src=\"" + IFRAME_SRC + "\" />";
iframe = doc.createElement("iframe");
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
iframe.addEventListener("load", function () {
iframe.removeEventListener("load", arguments.callee, false);
let iframe = getNode("iframe");
let div = getNode("div", { document: iframe.contentDocument });
div = iframe.contentDocument.createElement("div");
div.textContent = "big div";
div.setAttribute("style", "height:500px; width:500px; border:1px solid gray;");
iframe.contentDocument.body.appendChild(div);
openInspector(inspectNode);
}, false);
info("Waiting for highlighter box model to appear.");
yield toolbox.highlighter.showBoxModel(getNodeFront(div));
iframe.src = "data:text/html,foo bar";
doc.body.appendChild(iframe);
}
function inspectNode(aInspector)
{
inspector = aInspector;
let highlighter = inspector.toolbox.highlighter;
highlighter.showBoxModel(getNodeFront(div)).then(performScrollingTest);
}
function performScrollingTest()
{
gBrowser.selectedBrowser.addEventListener("scroll", function() {
gBrowser.selectedBrowser.removeEventListener("scroll", arguments.callee,
false);
let isRetina = devicePixelRatio === 2;
is(iframe.contentDocument.body.scrollTop,
isRetina ? 25 : 50, "inspected iframe scrolled");
finishUp();
}, false);
let scrolled = once(gBrowser.selectedBrowser, "scroll");
info("Scrolling iframe.");
EventUtils.synthesizeWheel(div, 10, 10,
{ deltaY: 50.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL },
iframe.contentWindow);
}
function finishUp()
{
inspector = div = iframe = doc = null;
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
gBrowser.removeCurrentTab();
finish();
}
info("Waiting for scroll event");
yield scrolled;
function test()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
let isRetina = devicePixelRatio === 2;
is(iframe.contentDocument.body.scrollTop,
isRetina ? 25 : 50, "inspected iframe scrolled");
content.location = "data:text/html,mouse scrolling test for inspector";
}
info("Hiding box model.");
yield toolbox.highlighter.hideBoxModel();
});

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

@ -4,114 +4,84 @@
* 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/. */
function test() {
let inspector, toolbox;
let page1 = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_select_last_selected.html";
let page2 = "http://mochi.test:8888/browser/browser/devtools/inspector/test/browser_inspector_select_last_selected2.html";
// Checks that the expected default node is selected after a page navigation or
// a reload.
let PAGE_1 = TEST_URL_ROOT + "browser_inspector_select_last_selected.html";
let PAGE_2 = TEST_URL_ROOT + "browser_inspector_select_last_selected2.html";
// Create a tab, load test HTML, wait for load and start the tests
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
waitForFocus(function() {
openInspector((aInspector, aToolbox) => {
inspector = aInspector;
toolbox = aToolbox;
startTests();
});
}, content);
}, true);
content.location = page1;
function startTests() {
testSameNodeSelectedOnPageReload();
}
function endTests() {
inspector.destroy();
toolbox.destroy().then(() => {
toolbox = inspector = page1 = page2 = null;
gBrowser.removeCurrentTab();
finish();
});
}
function loadPageAnd(page, callback) {
inspector.once("new-root", () => {
callback();
});
if (page) {
content.location = page;
} else {
content.location.reload();
}
}
function reloadAndReselect(id, callback) {
let div = content.document.getElementById(id);
inspector.once("inspector-updated", () => {
is(inspector.selection.node, div);
loadPageAnd(false, () => {
is(inspector.selection.node.id, id, "Node re-selected after reload");
callback();
});
});
inspector.selection.setNode(div);
}
// Test that nodes selected on the test page remain selected after reload
function testSameNodeSelectedOnPageReload()
// An array of test cases with following properties:
// - url: URL to navigate to. If URL == content.location, reload instead.
// - nodeToSelect: a selector for a node to select before navigation. If null,
// whatever is selected stays selected.
// - selectedNode: a selector for a node that is selected after navigation.
let TEST_DATA = [
{
// Select a few nodes and check they are re-selected after reload of the same
// page
reloadAndReselect("id1", () => {
reloadAndReselect("id2", () => {
reloadAndReselect("id3", () => {
reloadAndReselect("id4", testBodySelectedOnNavigate);
});
});
});
url: PAGE_1,
nodeToSelect: "#id1",
selectedNode: "#id1"
},
{
url: PAGE_1,
nodeToSelect: "#id2",
selectedNode: "#id2"
},
{
url: PAGE_1,
nodeToSelect: "#id3",
selectedNode: "#id3"
},
{
url: PAGE_1,
nodeToSelect: "#id4",
selectedNode: "#id4"
},
{
url: PAGE_2,
nodeToSelect: null,
selectedNode: "body"
},
{
url: PAGE_1,
nodeToSelect: "#id5",
selectedNode: "body"
},
{
url: PAGE_2,
nodeToSelect: null,
selectedNode: "body"
}
];
let test = asyncTest(function* () {
let { inspector } = yield openInspectorForURL(PAGE_1);
for (let { url, nodeToSelect, selectedNode } of TEST_DATA) {
if (nodeToSelect) {
info("Selecting node " + nodeToSelect + " before navigation.");
yield selectNode(nodeToSelect, inspector);
}
yield navigateToAndWaitForNewRoot(url);
info("Waiting for inspector to update after new-root event.");
yield inspector.once("inspector-updated");
is(inspector.selection.node, getNode(selectedNode),
selectedNode + " is selected after navigation.");
}
// Test that since the previously selected node doesn't exist on the new page
// the body is selected
function testBodySelectedOnNavigate() {
// Last node selected was id4, go to a different page and check body is
// selected
loadPageAnd(page2, () => {
is(
inspector.selection.node.tagName.toLowerCase(),
"body",
"Node not found, body selected"
);
testSameNodeSelectedOnNavigateAwayAndBack();
});
function navigateToAndWaitForNewRoot(url) {
info("Navigating and waiting for new-root event after navigation.");
let newRoot = inspector.once("new-root");
if (url == content.location) {
info("Reloading page.");
content.location.reload();
} else {
info("Navigating to " + url);
content.location = url;
}
return newRoot;
}
// Test that the node selected on page 1 gets selected again after a navigation
// is made to another page and back again
function testSameNodeSelectedOnNavigateAwayAndBack() {
// On page2, select id5
let id = "id5";
let div = content.document.getElementById(id);
inspector.once("inspector-updated", () => {
is(inspector.selection.node.id, id);
// go to page1 but do not select anything
loadPageAnd(page1, () => {
// go back to page2 and check id5 is still the current selection
loadPageAnd(page2, () => {
is(inspector.selection.node.id, id, "Node re-selected after navigation");
endTests();
});
});
});
inspector.selection.setNode(div);
}
}
});

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

@ -1,71 +1,34 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
let doc;
let inspector;
const TEST_URI = "data:text/html;charset=UTF-8," +
"<h1>browser_inspector_sidebarstate.js</h1>";
function createDocument()
{
doc.body.innerHTML = '<h1>Sidebar state test</h1>';
doc.title = "Sidebar State Test";
let test = asyncTest(function* () {
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
openInspector(function(panel) {
inspector = panel;
inspector.sidebar.select("ruleview");
inspectorRuleViewOpened();
});
}
info("Selecting ruleview.");
inspector.sidebar.select("ruleview");
function inspectorRuleViewOpened()
{
is(inspector.sidebar.getCurrentTabID(), "ruleview", "Rule View is selected by default");
is(inspector.sidebar.getCurrentTabID(), "ruleview",
"Rule View is selected by default");
// Select the computed view and turn off the inspector.
info("Selecting computed view.");
inspector.sidebar.select("computedview");
gDevTools.once("toolbox-destroyed", inspectorClosed);
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
}
info("Closing inspector.");
yield toolbox.destroy();
function inspectorClosed()
{
openInspector(function(panel) {
inspector = panel;
info("Re-opening inspector.");
inspector = (yield openInspector()).inspector;
if (inspector.sidebar.getCurrentTabID()) {
info("Default sidebar already selected.")
testNewDefaultTab();
} else {
info("Default sidebar still to be selected, adding select listener.");
inspector.sidebar.once("select", testNewDefaultTab);
}
});
}
if (!inspector.sidebar.getCurrentTabID()) {
info("Default sidebar still to be selected, adding select listener.");
yield inspector.sidebar.once("select");
}
function testNewDefaultTab()
{
is(inspector.sidebar.getCurrentTabID(), "computedview", "Computed view is selected by default.");
finishTest();
}
function finishTest()
{
doc = inspector = null;
gBrowser.removeCurrentTab();
finish();
}
function test()
{
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
waitForFocus(createDocument, content);
}, true);
content.location = "data:text/html;charset=utf-8,browser_inspector_sidebarstate.js";
}
is(inspector.sidebar.getCurrentTabID(), "computedview",
"Computed view is selected by default.");
});

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

@ -1,6 +1,8 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */
"use strict";
const Cu = Components.utils;
const Ci = Components.interfaces;
@ -13,8 +15,8 @@ const Cc = Components.classes;
//Services.prefs.setBoolPref("devtools.dump.emit", true);
const TEST_URL_ROOT = "http://example.com/browser/browser/devtools/inspector/test/";
const { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
// All test are asynchronous
waitForExplicitFinish();
@ -47,6 +49,22 @@ SimpleTest.registerCleanupFunction(() => {
Services.prefs.clearUserPref("devtools.inspector.activeSidebar");
});
registerCleanupFunction(() => {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
// Move the mouse outside inspector. If the test happened fake a mouse event
// somewhere over inspector the pointer is considered to be there when the
// next test begins. This might cause unexpected events to be emitted when
// another test moves the mouse.
EventUtils.synthesizeMouseAtPoint(1, 1, {type: "mousemove"}, window);
while (gBrowser.tabs.length > 1) {
gBrowser.removeCurrentTab();
}
});
/**
* Define an async test based on a generator function
*/
@ -59,32 +77,59 @@ function asyncTest(generator) {
* @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();
let addTab = Task.async(function* (url) {
info("Adding a new tab with URL: '" + url + "'");
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;
let loaded = once(gBrowser.selectedBrowser, "load", true);
return def.promise;
}
content.location = url;
yield loaded;
info("URL '" + url + "' loading complete");
let def = promise.defer();
let isBlank = url == "about:blank";
waitForFocus(def.resolve, content, isBlank);
yield def.promise;
return tab;
});
/**
* 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
* @param {Object} options
* An object containing any of the following options:
* - document: HTMLDocument that should be queried for the selector.
* Default: content.document.
* - expectNoMatch: If true and a node matches the given selector, a
* failure is logged for an unexpected match.
* If false and nothing matches the given selector, a
* failure is logged for a missing match.
* Default: false.
* @return {DOMNode}
*/
function getNode(nodeOrSelector) {
return typeof nodeOrSelector === "string" ?
content.document.querySelector(nodeOrSelector) :
nodeOrSelector;
function getNode(nodeOrSelector, options = {}) {
let document = options.document || content.document;
let noMatches = !!options.expectNoMatch;
if (typeof nodeOrSelector === "string") {
info("Looking for a node that matches selector " + nodeOrSelector);
let node = document.querySelector(nodeOrSelector);
if (noMatches) {
ok(!node, "Selector " + nodeOrSelector + " didn't match any nodes.");
}
else {
ok(node, "Selector " + nodeOrSelector + " matched a node.");
}
return node;
}
info("Looking for a node but selector was not a string.");
return nodeOrSelector;
}
/**
@ -102,11 +147,25 @@ function getNode(nodeOrSelector) {
function selectNode(nodeOrSelector, inspector, reason="test") {
info("Selecting the node " + nodeOrSelector);
let node = getNode(nodeOrSelector);
let updated = inspector.once("inspector-updated");
let updated = inspector.once("inspector-updated", () => {
is(inspector.selection.node, node, "Correct node was selected");
});
inspector.selection.setNode(node, reason);
return updated;
}
/**
* Open the inspector in a tab with given URL.
* @param {string} url The URL to open.
* @return A promise that is resolved once the tab and inspector have loaded
* with an object: { tab, toolbox, inspector }.
*/
let openInspectorForURL = Task.async(function* (url) {
let tab = yield addTab(url);
let { inspector, toolbox } = yield openInspector();
return { tab, inspector, toolbox };
});
/**
* Open the toolbox, with the inspector tool visible.
* @param {Function} cb Optional callback, if you don't want to use the returned
@ -169,61 +228,6 @@ function waitForToolboxFrameFocus(toolbox) {
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()
{
let target = TargetFactory.forTab(gBrowser.selectedTab);
@ -373,40 +377,8 @@ function getHighlitNode()
}
}
function computedView()
{
let sidebar = getActiveInspector().sidebar;
let iframe = sidebar.tabbox.querySelector(".iframe-computedview");
return iframe.contentWindow.computedView;
}
function computedViewTree()
{
return computedView().view;
}
function ruleView()
{
let sidebar = getActiveInspector().sidebar;
let iframe = sidebar.tabbox.querySelector(".iframe-ruleview");
return iframe.contentWindow.ruleView;
}
function getComputedView() {
let inspector = getActiveInspector();
return inspector.sidebar.getWindowForTab("computedview").computedview.view;
}
function waitForView(aName, aCallback) {
let inspector = getActiveInspector();
if (inspector.sidebar.getTab(aName)) {
aCallback();
} else {
inspector.sidebar.once(aName + "-ready", aCallback);
}
}
function synthesizeKeyFromKeyTag(aKeyId) {
function synthesizeKeyFromKeyTag(aKeyId, aDocument = null) {
let document = aDocument || document;
let key = document.getElementById(aKeyId);
isnot(key, null, "Successfully retrieved the <key> node");
@ -432,53 +404,20 @@ function synthesizeKeyFromKeyTag(aKeyId) {
EventUtils.synthesizeKey(name, modifiers);
}
function focusSearchBoxUsingShortcut(panelWin, callback) {
panelWin.focus();
let key = panelWin.document.getElementById("nodeSearchKey");
isnot(key, null, "Successfully retrieved the <key> node");
let modifiersAttr = key.getAttribute("modifiers");
let name = null;
if (key.getAttribute("keycode")) {
name = key.getAttribute("keycode");
} else if (key.getAttribute("key")) {
name = key.getAttribute("key");
}
isnot(name, null, "Successfully retrieved keycode/key");
let modifiers = {
shiftKey: modifiersAttr.match("shift"),
ctrlKey: modifiersAttr.match("ctrl"),
altKey: modifiersAttr.match("alt"),
metaKey: modifiersAttr.match("meta"),
accelKey: modifiersAttr.match("accel")
};
let focusSearchBoxUsingShortcut = Task.async(function* (panelWin, callback) {
info("Focusing search box");
let searchBox = panelWin.document.getElementById("inspector-searchbox");
searchBox.addEventListener("focus", function onFocus() {
searchBox.removeEventListener("focus", onFocus, false);
callback && callback();
}, false);
EventUtils.synthesizeKey(name, modifiers);
}
let focused = once(searchBox, "focus");
function getComputedPropertyValue(aName)
{
let computedview = getComputedView();
let props = computedview.styleDocument.querySelectorAll(".property-view");
panelWin.focus();
synthesizeKeyFromKeyTag("nodeSearchKey", panelWin.document);
for (let prop of props) {
let name = prop.querySelector(".property-name");
yield focused;
if (name.textContent === aName) {
let value = prop.querySelector(".property-value");
return value.textContent;
}
if (callback) {
callback();
}
}
});
function isNodeCorrectlyHighlighted(node, prefix="") {
let boxModel = getBoxModelStatus();
@ -507,36 +446,33 @@ function getContainerForRawNode(markupView, rawNode)
return container;
}
SimpleTest.registerCleanupFunction(function () {
let target = TargetFactory.forTab(gBrowser.selectedTab);
gDevTools.closeToolbox(target);
});
/**
* Define an async test based on a generator function
* 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 asyncTest(generator) {
return () => Task.spawn(generator).then(null, ok.bind(null, false)).then(finish);
}
/**
* 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) {
info("Adding a new tab with URL: '" + url + "'");
let def = promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function onload() {
gBrowser.selectedBrowser.removeEventListener("load", onload, true);
info("URL '" + url + "' loading complete");
waitForFocus(() => {
def.resolve(tab);
}, content);
}, true);
content.location = url;
return def.promise;
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) {
info("Got event: '" + eventName + "' on " + target + ".");
target[remove](eventName, onEvent, useCapture);
deferred.resolve.apply(deferred, aArgs);
}, useCapture);
break;
}
}
return deferred.promise;
}