mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 17:31:47 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
6
devtools/client/inspector/test/.eslintrc.js
Normal file
6
devtools/client/inspector/test/.eslintrc.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the shared list of defined globals for mochitests.
|
||||
"extends": "../../../.eslintrc.mochitests.js"
|
||||
};
|
||||
172
devtools/client/inspector/test/browser.ini
Normal file
172
devtools/client/inspector/test/browser.ini
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
[DEFAULT]
|
||||
tags = devtools
|
||||
subsuite = devtools
|
||||
support-files =
|
||||
doc_inspector_add_node.html
|
||||
doc_inspector_breadcrumbs.html
|
||||
doc_inspector_breadcrumbs_visibility.html
|
||||
doc_inspector_csp.html
|
||||
doc_inspector_csp.html^headers^
|
||||
doc_inspector_delete-selected-node-01.html
|
||||
doc_inspector_delete-selected-node-02.html
|
||||
doc_inspector_embed.html
|
||||
doc_inspector_gcli-inspect-command.html
|
||||
doc_inspector_highlight_after_transition.html
|
||||
doc_inspector_highlighter-comments.html
|
||||
doc_inspector_highlighter-geometry_01.html
|
||||
doc_inspector_highlighter-geometry_02.html
|
||||
doc_inspector_highlighter_csstransform.html
|
||||
doc_inspector_highlighter_dom.html
|
||||
doc_inspector_highlighter_inline.html
|
||||
doc_inspector_highlighter.html
|
||||
doc_inspector_highlighter_rect.html
|
||||
doc_inspector_highlighter_rect_iframe.html
|
||||
doc_inspector_highlighter_xbl.xul
|
||||
doc_inspector_infobar_01.html
|
||||
doc_inspector_infobar_02.html
|
||||
doc_inspector_infobar_03.html
|
||||
doc_inspector_infobar_textnode.html
|
||||
doc_inspector_long-divs.html
|
||||
doc_inspector_menu.html
|
||||
doc_inspector_outerhtml.html
|
||||
doc_inspector_remove-iframe-during-load.html
|
||||
doc_inspector_search.html
|
||||
doc_inspector_search-reserved.html
|
||||
doc_inspector_search-suggestions.html
|
||||
doc_inspector_search-svg.html
|
||||
doc_inspector_select-last-selected-01.html
|
||||
doc_inspector_select-last-selected-02.html
|
||||
doc_inspector_svg.svg
|
||||
head.js
|
||||
shared-head.js
|
||||
!/devtools/client/commandline/test/helpers.js
|
||||
!/devtools/client/framework/test/shared-head.js
|
||||
!/devtools/client/shared/test/test-actor.js
|
||||
!/devtools/client/shared/test/test-actor-registry.js
|
||||
|
||||
[browser_inspector_addNode_01.js]
|
||||
[browser_inspector_addNode_02.js]
|
||||
[browser_inspector_addNode_03.js]
|
||||
[browser_inspector_addSidebarTab.js]
|
||||
[browser_inspector_breadcrumbs.js]
|
||||
[browser_inspector_breadcrumbs_highlight_hover.js]
|
||||
[browser_inspector_breadcrumbs_keybinding.js]
|
||||
[browser_inspector_breadcrumbs_keyboard_trap.js]
|
||||
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard Preferences
|
||||
[browser_inspector_breadcrumbs_mutations.js]
|
||||
[browser_inspector_breadcrumbs_namespaced.js]
|
||||
[browser_inspector_breadcrumbs_visibility.js]
|
||||
[browser_inspector_delete-selected-node-01.js]
|
||||
[browser_inspector_delete-selected-node-02.js]
|
||||
[browser_inspector_delete-selected-node-03.js]
|
||||
[browser_inspector_destroy-after-navigation.js]
|
||||
[browser_inspector_destroy-before-ready.js]
|
||||
[browser_inspector_expand-collapse.js]
|
||||
[browser_inspector_gcli-inspect-command.js]
|
||||
[browser_inspector_highlighter-01.js]
|
||||
[browser_inspector_highlighter-02.js]
|
||||
[browser_inspector_highlighter-03.js]
|
||||
[browser_inspector_highlighter-04.js]
|
||||
[browser_inspector_highlighter-by-type.js]
|
||||
[browser_inspector_highlighter-cancel.js]
|
||||
[browser_inspector_highlighter-comments.js]
|
||||
[browser_inspector_highlighter-cssgrid_01.js]
|
||||
[browser_inspector_highlighter-csstransform_01.js]
|
||||
[browser_inspector_highlighter-csstransform_02.js]
|
||||
[browser_inspector_highlighter-embed.js]
|
||||
[browser_inspector_highlighter-eyedropper-clipboard.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_highlighter-eyedropper-csp.js]
|
||||
[browser_inspector_highlighter-eyedropper-events.js]
|
||||
[browser_inspector_highlighter-eyedropper-label.js]
|
||||
[browser_inspector_highlighter-eyedropper-show-hide.js]
|
||||
[browser_inspector_highlighter-eyedropper-xul.js]
|
||||
[browser_inspector_highlighter-geometry_01.js]
|
||||
[browser_inspector_highlighter-geometry_02.js]
|
||||
[browser_inspector_highlighter-geometry_03.js]
|
||||
[browser_inspector_highlighter-geometry_04.js]
|
||||
[browser_inspector_highlighter-geometry_05.js]
|
||||
[browser_inspector_highlighter-geometry_06.js]
|
||||
[browser_inspector_highlighter-hover_01.js]
|
||||
[browser_inspector_highlighter-hover_02.js]
|
||||
[browser_inspector_highlighter-hover_03.js]
|
||||
[browser_inspector_highlighter-iframes_01.js]
|
||||
[browser_inspector_highlighter-iframes_02.js]
|
||||
[browser_inspector_highlighter-inline.js]
|
||||
[browser_inspector_highlighter-keybinding_01.js]
|
||||
[browser_inspector_highlighter-keybinding_02.js]
|
||||
[browser_inspector_highlighter-keybinding_03.js]
|
||||
[browser_inspector_highlighter-keybinding_04.js]
|
||||
[browser_inspector_highlighter-measure_01.js]
|
||||
[browser_inspector_highlighter-measure_02.js]
|
||||
[browser_inspector_highlighter-options.js]
|
||||
[browser_inspector_highlighter-preview.js]
|
||||
[browser_inspector_highlighter-rect_01.js]
|
||||
[browser_inspector_highlighter-rect_02.js]
|
||||
[browser_inspector_highlighter-rulers_01.js]
|
||||
[browser_inspector_highlighter-rulers_02.js]
|
||||
[browser_inspector_highlighter-selector_01.js]
|
||||
[browser_inspector_highlighter-selector_02.js]
|
||||
[browser_inspector_highlighter-xbl.js]
|
||||
[browser_inspector_highlighter-zoom.js]
|
||||
[browser_inspector_iframe-navigation.js]
|
||||
[browser_inspector_infobar_01.js]
|
||||
[browser_inspector_infobar_02.js]
|
||||
[browser_inspector_infobar_03.js]
|
||||
[browser_inspector_infobar_textnode.js]
|
||||
[browser_inspector_initialization.js]
|
||||
skip-if = (e10s && debug) # Bug 1250058 - Docshell leak on debug e10s
|
||||
[browser_inspector_inspect-object-element.js]
|
||||
[browser_inspector_invalidate.js]
|
||||
[browser_inspector_keyboard-shortcuts-copy-outerhtml.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_keyboard-shortcuts.js]
|
||||
[browser_inspector_menu-01-sensitivity.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_menu-02-copy-items.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_menu-03-paste-items.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_menu-03-paste-items-svg.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_menu-04-use-in-console.js]
|
||||
[browser_inspector_menu-05-attribute-items.js]
|
||||
[browser_inspector_menu-06-other.js]
|
||||
[browser_inspector_navigation.js]
|
||||
[browser_inspector_navigate_to_errors.js]
|
||||
[browser_inspector_open_on_neterror.js]
|
||||
[browser_inspector_pane-toggle-01.js]
|
||||
[browser_inspector_pane-toggle-02.js]
|
||||
[browser_inspector_pane-toggle-03.js]
|
||||
[browser_inspector_pane-toggle-05.js]
|
||||
skip-if = os == "mac" # Full keyboard navigation on OSX only works if Full Keyboard Access setting is set to All Control in System Keyboard
|
||||
[browser_inspector_picker-stop-on-destroy.js]
|
||||
[browser_inspector_picker-stop-on-tool-change.js]
|
||||
[browser_inspector_portrait_mode.js]
|
||||
[browser_inspector_pseudoclass-lock.js]
|
||||
[browser_inspector_pseudoclass-menu.js]
|
||||
[browser_inspector_reload-01.js]
|
||||
[browser_inspector_reload-02.js]
|
||||
[browser_inspector_remove-iframe-during-load.js]
|
||||
[browser_inspector_search-01.js]
|
||||
[browser_inspector_search-02.js]
|
||||
[browser_inspector_search-03.js]
|
||||
[browser_inspector_search-04.js]
|
||||
[browser_inspector_search-05.js]
|
||||
[browser_inspector_search-06.js]
|
||||
[browser_inspector_search-07.js]
|
||||
[browser_inspector_search-08.js]
|
||||
[browser_inspector_search-clear.js]
|
||||
[browser_inspector_search-filter_context-menu.js]
|
||||
subsuite = clipboard
|
||||
[browser_inspector_search_keyboard_trap.js]
|
||||
[browser_inspector_search-label.js]
|
||||
[browser_inspector_search-reserved.js]
|
||||
[browser_inspector_search-selection.js]
|
||||
[browser_inspector_search-sidebar.js]
|
||||
[browser_inspector_select-docshell.js]
|
||||
[browser_inspector_select-last-selected.js]
|
||||
[browser_inspector_search-navigation.js]
|
||||
[browser_inspector_sidebarstate.js]
|
||||
[browser_inspector_switch-to-inspector-on-pick.js]
|
||||
[browser_inspector_textbox-menu.js]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* 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 add node button and context menu items are present in the UI.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,<h1>Add node</h1>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
let {panelDoc} = inspector;
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let menuItem = allMenuItems.find(item => item.id === "node-menu-add");
|
||||
ok(menuItem, "The item is in the menu");
|
||||
|
||||
let toolbarButton =
|
||||
panelDoc.querySelector("#inspector-toolbar #inspector-element-add-button");
|
||||
ok(toolbarButton, "The add button is in the toolbar");
|
||||
});
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 add node button and context menu items have the right state
|
||||
// depending on the current selection.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_add_node.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Select the DOCTYPE element");
|
||||
let {nodes} = yield inspector.walker.children(inspector.walker.rootNode);
|
||||
yield selectNode(nodes[0], inspector);
|
||||
assertState(false, inspector,
|
||||
"The button and item are disabled on DOCTYPE");
|
||||
|
||||
info("Select the ::before pseudo-element");
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
({nodes} = yield inspector.walker.children(body));
|
||||
yield selectNode(nodes[0], inspector);
|
||||
assertState(false, inspector,
|
||||
"The button and item are disabled on a pseudo-element");
|
||||
|
||||
info("Select the svg element");
|
||||
yield selectNode("svg", inspector);
|
||||
assertState(false, inspector,
|
||||
"The button and item are disabled on a SVG element");
|
||||
|
||||
info("Select the div#foo element");
|
||||
yield selectNode("#foo", inspector);
|
||||
assertState(true, inspector,
|
||||
"The button and item are enabled on a DIV element");
|
||||
|
||||
info("Select the documentElement element (html)");
|
||||
yield selectNode("html", inspector);
|
||||
assertState(false, inspector,
|
||||
"The button and item are disabled on the documentElement");
|
||||
|
||||
info("Select the iframe element");
|
||||
yield selectNode("iframe", inspector);
|
||||
assertState(false, inspector,
|
||||
"The button and item are disabled on an IFRAME element");
|
||||
});
|
||||
|
||||
function assertState(isEnabled, inspector, desc) {
|
||||
let doc = inspector.panelDoc;
|
||||
let btn = doc.querySelector("#inspector-element-add-button");
|
||||
|
||||
// Force an update of the context menu to make sure menu items are updated
|
||||
// according to the current selection. This normally happens when the menu is
|
||||
// opened, but for the sake of this test's simplicity, we directly call the
|
||||
// private update function instead.
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let menuItem = allMenuItems.find(item => item.id === "node-menu-add");
|
||||
ok(menuItem, "The item is in the menu");
|
||||
is(!menuItem.disabled, isEnabled, desc);
|
||||
|
||||
is(!btn.hasAttribute("disabled"), isEnabled, desc);
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* 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 adding nodes does work as expected: the parent gets expanded, the
|
||||
// new node gets selected.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_add_node.html";
|
||||
const PARENT_TREE_LEVEL = 3;
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Adding in element that has no children and is collapsed");
|
||||
let parentNode = yield getNodeFront("#foo", inspector);
|
||||
yield selectNode(parentNode, inspector);
|
||||
yield testAddNode(parentNode, inspector);
|
||||
|
||||
info("Adding in element with children but that has not been expanded yet");
|
||||
parentNode = yield getNodeFront("#bar", inspector);
|
||||
yield selectNode(parentNode, inspector);
|
||||
yield testAddNode(parentNode, inspector);
|
||||
|
||||
info("Adding in element with children that has been expanded then collapsed");
|
||||
// Select again #bar and collapse it.
|
||||
parentNode = yield getNodeFront("#bar", inspector);
|
||||
yield selectNode(parentNode, inspector);
|
||||
collapseNode(parentNode, inspector);
|
||||
yield testAddNode(parentNode, inspector);
|
||||
|
||||
info("Adding in element with children that is expanded");
|
||||
parentNode = yield getNodeFront("#bar", inspector);
|
||||
yield selectNode(parentNode, inspector);
|
||||
yield testAddNode(parentNode, inspector);
|
||||
});
|
||||
|
||||
function* testAddNode(parentNode, inspector) {
|
||||
let btn = inspector.panelDoc.querySelector("#inspector-element-add-button");
|
||||
let markupWindow = inspector.markup.win;
|
||||
let parentContainer = inspector.markup.getContainer(parentNode);
|
||||
|
||||
is(parentContainer.tagLine.getAttribute("aria-level"), PARENT_TREE_LEVEL,
|
||||
"Parent level should be up to date.");
|
||||
|
||||
info("Clicking 'add node' and expecting a markup mutation and focus event");
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
btn.click();
|
||||
let mutations = yield onMutation;
|
||||
|
||||
info("Expecting an inspector-updated event right after the mutation event " +
|
||||
"to wait for the new node selection");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
is(mutations.length, 1, "There is one mutation only");
|
||||
is(mutations[0].added.length, 1, "There is one new node only");
|
||||
|
||||
let newNode = mutations[0].added[0];
|
||||
|
||||
is(newNode, inspector.selection.nodeFront,
|
||||
"The new node is selected");
|
||||
|
||||
ok(parentContainer.expanded, "The parent node is now expanded");
|
||||
|
||||
is(inspector.selection.nodeFront.parentNode(), parentNode,
|
||||
"The new node is inside the right parent");
|
||||
|
||||
let focusedElement = markupWindow.document.activeElement;
|
||||
let focusedContainer = focusedElement.container;
|
||||
let selectedContainer = inspector.markup._selectedContainer;
|
||||
is(selectedContainer.tagLine.getAttribute("aria-level"),
|
||||
PARENT_TREE_LEVEL + 1, "Added container level should be up to date.");
|
||||
is(selectedContainer.node, inspector.selection.nodeFront,
|
||||
"The right container is selected in the markup-view");
|
||||
ok(selectedContainer.selected, "Selected container is set to selected");
|
||||
is(focusedContainer.toString(), "[root container]",
|
||||
"Root container is focused");
|
||||
}
|
||||
|
||||
function collapseNode(node, inspector) {
|
||||
let container = inspector.markup.getContainer(node);
|
||||
container.setExpanded(false);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/* 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";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=UTF-8," +
|
||||
"<h1>browser_inspector_addtabbar.js</h1>";
|
||||
|
||||
const CONTENT_TEXT = "Hello World!";
|
||||
|
||||
/**
|
||||
* Verify InspectorPanel.addSidebarTab() API that can be consumed
|
||||
* by DevTools extensions as well as DevTools code base.
|
||||
*/
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
const React = inspector.React;
|
||||
const { div } = React.DOM;
|
||||
|
||||
info("Adding custom panel.");
|
||||
|
||||
// Define custom side-panel.
|
||||
let tabPanel = React.createFactory(React.createClass({
|
||||
displayName: "myTabPanel",
|
||||
render: function () {
|
||||
return (
|
||||
div({className: "my-tab-panel"},
|
||||
CONTENT_TEXT
|
||||
)
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
// Append custom panel (tab) into the Inspector panel and
|
||||
// make sure it's selected by default (the last arg = true).
|
||||
inspector.addSidebarTab("myPanel", "My Panel", tabPanel, true);
|
||||
is(inspector.sidebar.getCurrentTabID(), "myPanel",
|
||||
"My Panel is selected by default");
|
||||
|
||||
// Define another custom side-panel.
|
||||
tabPanel = React.createFactory(React.createClass({
|
||||
displayName: "myTabPanel2",
|
||||
render: function () {
|
||||
return (
|
||||
div({className: "my-tab-panel2"},
|
||||
"Another Content"
|
||||
)
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
// Append second panel, but don't select it by default.
|
||||
inspector.addSidebarTab("myPanel", "My Panel", tabPanel, false);
|
||||
is(inspector.sidebar.getCurrentTabID(), "myPanel",
|
||||
"My Panel is selected by default");
|
||||
|
||||
// Check the the panel content is properly rendered.
|
||||
let tabPanelNode = inspector.panelDoc.querySelector(".my-tab-panel");
|
||||
is(tabPanelNode.textContent, CONTENT_TEXT,
|
||||
"Side panel content has been rendered.");
|
||||
});
|
||||
132
devtools/client/inspector/test/browser_inspector_breadcrumbs.js
Normal file
132
devtools/client/inspector/test/browser_inspector_breadcrumbs.js
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the breadcrumbs widget content is correct.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs.html";
|
||||
const NODES = [
|
||||
{selector: "#i1111", ids: "i1 i11 i111 i1111", nodeName: "div",
|
||||
title: "div#i1111"},
|
||||
{selector: "#i22", ids: "i2 i22", nodeName: "div",
|
||||
title: "div#i22"},
|
||||
{selector: "#i2111", ids: "i2 i21 i211 i2111", nodeName: "div",
|
||||
title: "div#i2111"},
|
||||
{selector: "#i21", ids: "i2 i21 i211 i2111", nodeName: "div",
|
||||
title: "div#i21"},
|
||||
{selector: "#i22211", ids: "i2 i22 i222 i2221 i22211", nodeName: "div",
|
||||
title: "div#i22211"},
|
||||
{selector: "#i22", ids: "i2 i22 i222 i2221 i22211", nodeName: "div",
|
||||
title: "div#i22"},
|
||||
{selector: "#i3", ids: "i3", nodeName: "article",
|
||||
title: "article#i3"},
|
||||
{selector: "clipPath", ids: "vector clip", nodeName: "clipPath",
|
||||
title: "clipPath#clip"},
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URI);
|
||||
let breadcrumbs = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
let container = breadcrumbs.querySelector(".html-arrowscrollbox-inner");
|
||||
|
||||
for (let node of NODES) {
|
||||
info("Testing node " + node.selector);
|
||||
|
||||
info("Selecting node and waiting for breadcrumbs to update");
|
||||
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
yield selectNode(node.selector, inspector);
|
||||
yield breadcrumbsUpdated;
|
||||
|
||||
info("Performing checks for node " + node.selector);
|
||||
let buttonsLabelIds = node.ids.split(" ");
|
||||
|
||||
// html > body > …
|
||||
is(container.childNodes.length, buttonsLabelIds.length + 2,
|
||||
"Node " + node.selector + ": 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 " + node.selector + ": button " + i + " matches");
|
||||
}
|
||||
|
||||
let checkedButton = container.querySelector("button[checked]");
|
||||
let labelId = checkedButton.querySelector(".breadcrumbs-widget-item-id");
|
||||
let id = inspector.selection.nodeFront.id;
|
||||
is(labelId.textContent, "#" + id,
|
||||
"Node " + node.selector + ": selection matches");
|
||||
|
||||
let labelTag = checkedButton.querySelector(".breadcrumbs-widget-item-tag");
|
||||
is(labelTag.textContent, node.nodeName,
|
||||
"Node " + node.selector + " has the expected tag name");
|
||||
|
||||
is(checkedButton.getAttribute("title"), node.title,
|
||||
"Node " + node.selector + " has the expected tooltip");
|
||||
}
|
||||
|
||||
yield testPseudoElements(inspector, container);
|
||||
yield testComments(inspector, container);
|
||||
});
|
||||
|
||||
function* testPseudoElements(inspector, container) {
|
||||
info("Checking for pseudo elements");
|
||||
|
||||
let pseudoParent = yield getNodeFront("#pseudo-container", inspector);
|
||||
let children = yield inspector.walker.children(pseudoParent);
|
||||
is(children.nodes.length, 2, "Pseudo children returned from walker");
|
||||
|
||||
let beforeElement = children.nodes[0];
|
||||
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
yield selectNode(beforeElement, inspector);
|
||||
yield breadcrumbsUpdated;
|
||||
is(container.childNodes[3].textContent, "::before",
|
||||
"::before shows up in breadcrumb");
|
||||
|
||||
let afterElement = children.nodes[1];
|
||||
breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
yield selectNode(afterElement, inspector);
|
||||
yield breadcrumbsUpdated;
|
||||
is(container.childNodes[3].textContent, "::after",
|
||||
"::before shows up in breadcrumb");
|
||||
}
|
||||
|
||||
function* testComments(inspector, container) {
|
||||
info("Checking for comment elements");
|
||||
|
||||
let breadcrumbs = inspector.breadcrumbs;
|
||||
let checkedButtonIndex = 2;
|
||||
let button = container.childNodes[checkedButtonIndex];
|
||||
|
||||
let onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
button.click();
|
||||
yield onBreadcrumbsUpdated;
|
||||
|
||||
is(breadcrumbs.currentIndex, checkedButtonIndex, "New button is selected");
|
||||
ok(breadcrumbs.outer.hasAttribute("aria-activedescendant"),
|
||||
"Active descendant must be set");
|
||||
|
||||
let comment = [...inspector.markup._containers].find(([node]) =>
|
||||
node.nodeType === Ci.nsIDOMNode.COMMENT_NODE)[0];
|
||||
|
||||
let onInspectorUpdated = inspector.once("inspector-updated");
|
||||
inspector.selection.setNodeFront(comment);
|
||||
yield onInspectorUpdated;
|
||||
|
||||
is(breadcrumbs.currentIndex, -1,
|
||||
"When comment is selected no breadcrumb should be checked");
|
||||
ok(!breadcrumbs.outer.hasAttribute("aria-activedescendant"),
|
||||
"Active descendant must not be set");
|
||||
|
||||
onInspectorUpdated = inspector.once("inspector-updated");
|
||||
onBreadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
button.click();
|
||||
yield Promise.all([onInspectorUpdated, onBreadcrumbsUpdated]);
|
||||
|
||||
is(breadcrumbs.currentIndex, checkedButtonIndex,
|
||||
"Same button is selected again");
|
||||
ok(breadcrumbs.outer.hasAttribute("aria-activedescendant"),
|
||||
"Active descendant must be set again");
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/* 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 nodes on the breadcrumb buttons in the inspector
|
||||
// shows the highlighter over those nodes
|
||||
add_task(function* () {
|
||||
info("Loading the test document and opening the inspector");
|
||||
let {toolbox, inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>");
|
||||
info("Selecting the test node");
|
||||
yield selectNode("span", inspector);
|
||||
let bcButtons = inspector.breadcrumbs.container;
|
||||
|
||||
let onNodeHighlighted = toolbox.once("node-highlight");
|
||||
let button = bcButtons.childNodes[1];
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousemove"},
|
||||
button.ownerDocument.defaultView);
|
||||
yield onNodeHighlighted;
|
||||
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown on a markup container hover");
|
||||
|
||||
ok((yield testActor.assertHighlightedNode("body")),
|
||||
"The highlighter highlights the right node");
|
||||
|
||||
let onNodeUnhighlighted = toolbox.once("node-unhighlight");
|
||||
// move outside of the breadcrumb trail to trigger unhighlight
|
||||
EventUtils.synthesizeMouseAtCenter(inspector.addNodeButton,
|
||||
{type: "mousemove"},
|
||||
inspector.addNodeButton.ownerDocument.defaultView);
|
||||
yield onNodeUnhighlighted;
|
||||
|
||||
onNodeHighlighted = toolbox.once("node-highlight");
|
||||
button = bcButtons.childNodes[2];
|
||||
EventUtils.synthesizeMouseAtCenter(button, {type: "mousemove"},
|
||||
button.ownerDocument.defaultView);
|
||||
yield onNodeHighlighted;
|
||||
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown on a markup container hover");
|
||||
|
||||
ok((yield testActor.assertHighlightedNode("span")),
|
||||
"The highlighter highlights the right node");
|
||||
});
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the breadcrumbs keybindings work.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs.html";
|
||||
const TEST_DATA = [{
|
||||
desc: "Pressing left should select the parent <body>",
|
||||
key: "VK_LEFT",
|
||||
newSelection: "body"
|
||||
}, {
|
||||
desc: "Pressing left again should select the parent <html>",
|
||||
key: "VK_LEFT",
|
||||
newSelection: "html"
|
||||
}, {
|
||||
desc: "Pressing left again should stay on <html>, it's the first element",
|
||||
key: "VK_LEFT",
|
||||
newSelection: "html"
|
||||
}, {
|
||||
desc: "Pressing right should go to <body>",
|
||||
key: "VK_RIGHT",
|
||||
newSelection: "body"
|
||||
}, {
|
||||
desc: "Pressing right again should go to #i2",
|
||||
key: "VK_RIGHT",
|
||||
newSelection: "#i2"
|
||||
}, {
|
||||
desc: "Pressing right again should stay on #i2, it's the last element",
|
||||
key: "VK_RIGHT",
|
||||
newSelection: "#i2"
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Selecting the test node");
|
||||
yield selectNode("#i2", inspector);
|
||||
|
||||
info("Clicking on the corresponding breadcrumbs node to focus it");
|
||||
let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
|
||||
let button = container.querySelector("button[checked]");
|
||||
button.click();
|
||||
|
||||
let currentSelection = "#id2";
|
||||
for (let {desc, key, newSelection} of TEST_DATA) {
|
||||
info(desc);
|
||||
|
||||
// If the selection will change, wait for the breadcrumb to update,
|
||||
// otherwise continue.
|
||||
let onUpdated = null;
|
||||
if (newSelection !== currentSelection) {
|
||||
info("Expecting a new node to be selected");
|
||||
onUpdated = inspector.once("breadcrumbs-updated");
|
||||
}
|
||||
|
||||
EventUtils.synthesizeKey(key, {});
|
||||
yield onUpdated;
|
||||
|
||||
let newNodeFront = yield getNodeFront(newSelection, inspector);
|
||||
is(newNodeFront, inspector.selection.nodeFront,
|
||||
"The current selection is correct");
|
||||
is(container.getAttribute("aria-activedescendant"),
|
||||
container.querySelector("button[checked]").id,
|
||||
"aria-activedescendant is set correctly");
|
||||
|
||||
currentSelection = newSelection;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test ability to tab to and away from breadcrumbs using keyboard.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_breadcrumbs.html";
|
||||
|
||||
/**
|
||||
* Test data has the format of:
|
||||
* {
|
||||
* desc {String} description for better logging
|
||||
* focused {Boolean} flag, indicating if breadcrumbs contain focus
|
||||
* key {String} key event's key
|
||||
* options {?Object} optional event data such as shiftKey, etc
|
||||
* }
|
||||
*/
|
||||
const TEST_DATA = [
|
||||
{
|
||||
desc: "Move the focus away from breadcrumbs to a next focusable element",
|
||||
focused: false,
|
||||
key: "VK_TAB",
|
||||
options: { }
|
||||
},
|
||||
{
|
||||
desc: "Move the focus back to the breadcrumbs",
|
||||
focused: true,
|
||||
key: "VK_TAB",
|
||||
options: { shiftKey: true }
|
||||
},
|
||||
{
|
||||
desc: "Move the focus back away from breadcrumbs to a previous focusable " +
|
||||
"element",
|
||||
focused: false,
|
||||
key: "VK_TAB",
|
||||
options: { shiftKey: true }
|
||||
},
|
||||
{
|
||||
desc: "Move the focus back to the breadcrumbs",
|
||||
focused: true,
|
||||
key: "VK_TAB",
|
||||
options: { }
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { toolbox, inspector } = yield openInspectorForURL(TEST_URL);
|
||||
let doc = inspector.panelDoc;
|
||||
let {breadcrumbs} = inspector;
|
||||
|
||||
yield selectNode("#i2", inspector);
|
||||
|
||||
info("Clicking on the corresponding breadcrumbs node to focus it");
|
||||
let container = doc.getElementById("inspector-breadcrumbs");
|
||||
|
||||
let button = container.querySelector("button[checked]");
|
||||
let onHighlight = toolbox.once("node-highlight");
|
||||
button.click();
|
||||
yield onHighlight;
|
||||
|
||||
// Ensure a breadcrumb is focused.
|
||||
is(doc.activeElement, container, "Focus is on selected breadcrumb");
|
||||
is(container.getAttribute("aria-activedescendant"), button.id,
|
||||
"aria-activedescendant is set correctly");
|
||||
|
||||
for (let { desc, focused, key, options } of TEST_DATA) {
|
||||
info(desc);
|
||||
|
||||
EventUtils.synthesizeKey(key, options);
|
||||
// Wait until the keyPromise promise resolves.
|
||||
yield breadcrumbs.keyPromise;
|
||||
|
||||
if (focused) {
|
||||
is(doc.activeElement, container, "Focus is on selected breadcrumb");
|
||||
} else {
|
||||
ok(!containsFocus(doc, container), "Focus is outside of breadcrumbs");
|
||||
}
|
||||
is(container.getAttribute("aria-activedescendant"), button.id,
|
||||
"aria-activedescendant is set correctly");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the breadcrumbs widget refreshes correctly when there are markup
|
||||
// mutations (and that it doesn't refresh when those mutations don't change its
|
||||
// output).
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs.html";
|
||||
|
||||
// Each item in the TEST_DATA array is a test case that should contain the
|
||||
// following properties:
|
||||
// - desc {String} A description of this test case (will be logged).
|
||||
// - setup {Function*} A generator function (can yield promises) that sets up
|
||||
// the test case. Useful for selecting a node before starting the test.
|
||||
// - run {Function*} A generator function (can yield promises) that runs the
|
||||
// actual test case, i.e, mutates the content DOM to cause the breadcrumbs
|
||||
// to refresh, or not.
|
||||
// - shouldRefresh {Boolean} Once the `run` function has completed, and the test
|
||||
// has detected that the page has changed, this boolean instructs the test to
|
||||
// verify if the breadcrumbs has refreshed or not.
|
||||
// - output {Array} A list of strings for the text that should be found in each
|
||||
// button after the test has run.
|
||||
const TEST_DATA = [{
|
||||
desc: "Adding a child at the end of the chain shouldn't change anything",
|
||||
setup: function* (inspector) {
|
||||
yield selectNode("#i1111", inspector);
|
||||
},
|
||||
run: function* ({walker, selection}) {
|
||||
yield walker.setInnerHTML(selection.nodeFront, "<b>test</b>");
|
||||
},
|
||||
shouldRefresh: false,
|
||||
output: ["html", "body", "article#i1", "div#i11", "div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Updating an ID to an displayed element should refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
let node = yield walker.querySelector(walker.rootNode, "#i1");
|
||||
yield node.modifyAttributes([{
|
||||
attributeName: "id",
|
||||
newValue: "i1-changed"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: true,
|
||||
output: ["html", "body", "article#i1-changed", "div#i11", "div#i111",
|
||||
"div#i1111"]
|
||||
}, {
|
||||
desc: "Updating an class to a displayed element should refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
let node = yield walker.querySelector(walker.rootNode, "body");
|
||||
yield node.modifyAttributes([{
|
||||
attributeName: "class",
|
||||
newValue: "test-class"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: true,
|
||||
output: ["html", "body.test-class", "article#i1-changed", "div#i11",
|
||||
"div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Updating a non id/class attribute to a displayed element should not " +
|
||||
"refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
let node = yield walker.querySelector(walker.rootNode, "#i11");
|
||||
yield node.modifyAttributes([{
|
||||
attributeName: "name",
|
||||
newValue: "value"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: false,
|
||||
output: ["html", "body.test-class", "article#i1-changed", "div#i11",
|
||||
"div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Moving a child in an element that's not displayed should not refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
// Re-append #i1211 as a last child of #i2.
|
||||
let parent = yield walker.querySelector(walker.rootNode, "#i2");
|
||||
let child = yield walker.querySelector(walker.rootNode, "#i211");
|
||||
yield walker.insertBefore(child, parent);
|
||||
},
|
||||
shouldRefresh: false,
|
||||
output: ["html", "body.test-class", "article#i1-changed", "div#i11",
|
||||
"div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Moving an undisplayed child in a displayed element should not refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
// Re-append #i2 in body (move it to the end).
|
||||
let parent = yield walker.querySelector(walker.rootNode, "body");
|
||||
let child = yield walker.querySelector(walker.rootNode, "#i2");
|
||||
yield walker.insertBefore(child, parent);
|
||||
},
|
||||
shouldRefresh: false,
|
||||
output: ["html", "body.test-class", "article#i1-changed", "div#i11",
|
||||
"div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Updating attributes on an element that's not displayed should not " +
|
||||
"refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({walker}) {
|
||||
let node = yield walker.querySelector(walker.rootNode, "#i2");
|
||||
yield node.modifyAttributes([{
|
||||
attributeName: "id",
|
||||
newValue: "i2-changed"
|
||||
}, {
|
||||
attributeName: "class",
|
||||
newValue: "test-class"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: false,
|
||||
output: ["html", "body.test-class", "article#i1-changed", "div#i11",
|
||||
"div#i111", "div#i1111"]
|
||||
}, {
|
||||
desc: "Removing the currently selected node should refresh",
|
||||
setup: function* (inspector) {
|
||||
yield selectNode("#i2-changed", inspector);
|
||||
},
|
||||
run: function* ({walker, selection}) {
|
||||
yield walker.removeNode(selection.nodeFront);
|
||||
},
|
||||
shouldRefresh: true,
|
||||
output: ["html", "body.test-class"]
|
||||
}, {
|
||||
desc: "Changing the class of the currently selected node should refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({selection}) {
|
||||
yield selection.nodeFront.modifyAttributes([{
|
||||
attributeName: "class",
|
||||
newValue: "test-class-changed"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: true,
|
||||
output: ["html", "body.test-class-changed"]
|
||||
}, {
|
||||
desc: "Changing the id of the currently selected node should refresh",
|
||||
setup: function* () {},
|
||||
run: function* ({selection}) {
|
||||
yield selection.nodeFront.modifyAttributes([{
|
||||
attributeName: "id",
|
||||
newValue: "new-id"
|
||||
}]);
|
||||
},
|
||||
shouldRefresh: true,
|
||||
output: ["html", "body#new-id.test-class-changed"]
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URI);
|
||||
let breadcrumbs = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
let container = breadcrumbs.querySelector(".html-arrowscrollbox-inner");
|
||||
let win = container.ownerDocument.defaultView;
|
||||
|
||||
for (let {desc, setup, run, shouldRefresh, output} of TEST_DATA) {
|
||||
info("Running test case: " + desc);
|
||||
|
||||
info("Listen to markupmutation events from the inspector to know when a " +
|
||||
"test case has completed");
|
||||
let onContentMutation = inspector.once("markupmutation");
|
||||
|
||||
info("Running setup");
|
||||
yield setup(inspector);
|
||||
|
||||
info("Listen to mutations on the breadcrumbs container");
|
||||
let hasBreadcrumbsMutated = false;
|
||||
let observer = new win.MutationObserver(mutations => {
|
||||
// Only consider childList changes or tooltiptext/checked attributes
|
||||
// changes. The rest may be mutations caused by the overflowing arrowbox.
|
||||
for (let {type, attributeName} of mutations) {
|
||||
let isChildList = type === "childList";
|
||||
let isAttributes = type === "attributes" &&
|
||||
(attributeName === "checked" ||
|
||||
attributeName === "tooltiptext");
|
||||
if (isChildList || isAttributes) {
|
||||
hasBreadcrumbsMutated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(container, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
info("Running the test case");
|
||||
yield run(inspector);
|
||||
|
||||
info("Wait until the page has mutated");
|
||||
yield onContentMutation;
|
||||
|
||||
if (shouldRefresh) {
|
||||
info("The breadcrumbs is expected to refresh, so wait for it");
|
||||
yield inspector.once("inspector-updated");
|
||||
} else {
|
||||
ok(!inspector._updateProgress,
|
||||
"The breadcrumbs widget is not currently updating");
|
||||
}
|
||||
|
||||
is(shouldRefresh, hasBreadcrumbsMutated, "Has the breadcrumbs refreshed?");
|
||||
observer.disconnect();
|
||||
|
||||
info("Check the output of the breadcrumbs widget");
|
||||
is(container.childNodes.length, output.length, "Correct number of buttons");
|
||||
for (let i = 0; i < container.childNodes.length; i++) {
|
||||
is(output[i], container.childNodes[i].textContent,
|
||||
"Text content for button " + i + " is correct");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the breadcrumbs widget content for namespaced elements is correct.
|
||||
|
||||
const XHTML = `
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<body>
|
||||
<svg:svg width="100" height="100">
|
||||
<svg:clipPath id="clip">
|
||||
<svg:rect id="rectangle" x="0" y="0" width="10" height="5"></svg:rect>
|
||||
</svg:clipPath>
|
||||
<svg:circle cx="0" cy="0" r="5"></svg:circle>
|
||||
</svg:svg>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
|
||||
|
||||
const NODES = [
|
||||
{selector: "clipPath", nodes: ["svg:svg", "svg:clipPath"],
|
||||
nodeName: "svg:clipPath", title: "svg:clipPath#clip"},
|
||||
{selector: "circle", nodes: ["svg:svg", "svg:circle"],
|
||||
nodeName: "svg:circle", title: "svg:circle"},
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URI);
|
||||
let container = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
|
||||
for (let node of NODES) {
|
||||
info("Testing node " + node.selector);
|
||||
|
||||
info("Selecting node and waiting for breadcrumbs to update");
|
||||
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
yield selectNode(node.selector, inspector);
|
||||
yield breadcrumbsUpdated;
|
||||
|
||||
info("Performing checks for node " + node.selector);
|
||||
|
||||
let checkedButton = container.querySelector("button[checked]");
|
||||
|
||||
let labelTag = checkedButton.querySelector(".breadcrumbs-widget-item-tag");
|
||||
is(labelTag.textContent, node.nodeName,
|
||||
"Node " + node.selector + " has the expected tag name");
|
||||
|
||||
is(checkedButton.getAttribute("title"), node.title,
|
||||
"Node " + node.selector + " has the expected tooltip");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the start and end buttons on the breadcrumb trail bring the right
|
||||
// crumbs into the visible area, for both LTR and RTL
|
||||
|
||||
let { Toolbox } = require("devtools/client/framework/toolbox");
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_breadcrumbs_visibility.html";
|
||||
const NODE_ONE = "div#aVeryLongIdToExceedTheBreadcrumbTruncationLimit";
|
||||
const NODE_TWO = "div#anotherVeryLongIdToExceedTheBreadcrumbTruncationLimit";
|
||||
const NODE_THREE = "div#aThirdVeryLongIdToExceedTheTruncationLimit";
|
||||
const NODE_FOUR = "div#aFourthOneToExceedTheTruncationLimit";
|
||||
const NODE_FIVE = "div#aFifthOneToExceedTheTruncationLimit";
|
||||
const NODE_SIX = "div#aSixthOneToExceedTheTruncationLimit";
|
||||
const NODE_SEVEN = "div#aSeventhOneToExceedTheTruncationLimit";
|
||||
|
||||
const NODES = [
|
||||
{ action: "start", title: NODE_SIX },
|
||||
{ action: "start", title: NODE_FIVE },
|
||||
{ action: "start", title: NODE_FOUR },
|
||||
{ action: "start", title: NODE_THREE },
|
||||
{ action: "start", title: NODE_TWO },
|
||||
{ action: "start", title: NODE_ONE },
|
||||
{ action: "end", title: NODE_TWO },
|
||||
{ action: "end", title: NODE_THREE },
|
||||
{ action: "end", title: NODE_FOUR },
|
||||
{ action: "end", title: NODE_FIVE },
|
||||
{ action: "end", title: NODE_SIX }
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
// This test needs specific initial size of the sidebar.
|
||||
yield pushPref("devtools.toolsidebar-width.inspector", 350);
|
||||
yield pushPref("devtools.toolsidebar-height.inspector", 150);
|
||||
|
||||
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
// No way to wait for scrolling to end (Bug 1172171)
|
||||
// Rather than wait a max time; limit test to instant scroll behavior
|
||||
inspector.breadcrumbs.arrowScrollBox.scrollBehavior = "instant";
|
||||
|
||||
yield toolbox.switchHost(Toolbox.HostType.WINDOW);
|
||||
let hostWindow = toolbox.win.parent;
|
||||
let originalWidth = hostWindow.outerWidth;
|
||||
let originalHeight = hostWindow.outerHeight;
|
||||
hostWindow.resizeTo(640, 300);
|
||||
|
||||
info("Testing transitions ltr");
|
||||
yield pushPref("intl.uidirection.en-US", "ltr");
|
||||
yield testBreadcrumbTransitions(hostWindow, inspector);
|
||||
|
||||
info("Testing transitions rtl");
|
||||
yield pushPref("intl.uidirection.en-US", "rtl");
|
||||
yield testBreadcrumbTransitions(hostWindow, inspector);
|
||||
|
||||
hostWindow.resizeTo(originalWidth, originalHeight);
|
||||
});
|
||||
|
||||
function* testBreadcrumbTransitions(hostWindow, inspector) {
|
||||
let breadcrumbs = inspector.panelDoc.getElementById("inspector-breadcrumbs");
|
||||
let startBtn = breadcrumbs.querySelector(".scrollbutton-up");
|
||||
let endBtn = breadcrumbs.querySelector(".scrollbutton-down");
|
||||
let container = breadcrumbs.querySelector(".html-arrowscrollbox-inner");
|
||||
let breadcrumbsUpdated = inspector.once("breadcrumbs-updated");
|
||||
|
||||
info("Selecting initial node");
|
||||
yield selectNode(NODE_SEVEN, inspector);
|
||||
|
||||
// So just need to wait for a duration
|
||||
yield breadcrumbsUpdated;
|
||||
let initialCrumb = container.querySelector("button[checked]");
|
||||
is(isElementInViewport(hostWindow, initialCrumb), true,
|
||||
"initial element was visible");
|
||||
|
||||
for (let node of NODES) {
|
||||
info("Checking for visibility of crumb " + node.title);
|
||||
if (node.action === "end") {
|
||||
info("Simulating click of end button");
|
||||
EventUtils.synthesizeMouseAtCenter(endBtn, {}, inspector.panelWin);
|
||||
} else if (node.action === "start") {
|
||||
info("Simulating click of start button");
|
||||
EventUtils.synthesizeMouseAtCenter(startBtn, {}, inspector.panelWin);
|
||||
}
|
||||
|
||||
yield breadcrumbsUpdated;
|
||||
let selector = "button[title=\"" + node.title + "\"]";
|
||||
let relevantCrumb = container.querySelector(selector);
|
||||
is(isElementInViewport(hostWindow, relevantCrumb), true,
|
||||
node.title + " crumb is visible");
|
||||
}
|
||||
}
|
||||
|
||||
function isElementInViewport(window, el) {
|
||||
let rect = el.getBoundingClientRect();
|
||||
|
||||
return (
|
||||
rect.top >= 0 &&
|
||||
rect.left >= 0 &&
|
||||
rect.bottom <= window.innerHeight &&
|
||||
rect.right <= window.innerWidth
|
||||
);
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
// Restore the host type for other tests.
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
});
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test to ensure inspector handles deletion of selected node correctly.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_delete-selected-node-01.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let span = yield getNodeFrontInFrame("span", "iframe", inspector);
|
||||
yield selectNode(span, inspector);
|
||||
|
||||
info("Removing selected <span> element.");
|
||||
let parentNode = span.parentNode();
|
||||
yield inspector.walker.removeNode(span);
|
||||
|
||||
// Wait for the inspector to process the mutation
|
||||
yield inspector.once("inspector-updated");
|
||||
is(inspector.selection.nodeFront, parentNode,
|
||||
"Parent node of selected <span> got selected.");
|
||||
});
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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 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 = URL_ROOT +
|
||||
"doc_inspector_delete-selected-node-02.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_PAGE);
|
||||
|
||||
yield testManuallyDeleteSelectedNode();
|
||||
yield testAutomaticallyDeleteSelectedNode();
|
||||
yield testDeleteSelectedNodeContainerFrame();
|
||||
yield testDeleteWithNonElementNode();
|
||||
|
||||
function* testManuallyDeleteSelectedNode() {
|
||||
info("Selecting a node, deleting it via context menu and checking that " +
|
||||
"its parent node is selected and breadcrumbs are updated.");
|
||||
|
||||
yield deleteNodeWithContextMenu("#deleteManually");
|
||||
|
||||
info("Performing checks.");
|
||||
yield assertNodeSelectedAndPanelsUpdated("#selectedAfterDelete",
|
||||
"li#selectedAfterDelete");
|
||||
}
|
||||
|
||||
function* testAutomaticallyDeleteSelectedNode() {
|
||||
info("Selecting a node, deleting it via javascript and checking that " +
|
||||
"its parent node is selected and breadcrumbs are updated.");
|
||||
|
||||
let div = yield getNodeFront("#deleteAutomatically", inspector);
|
||||
yield selectNode(div, inspector);
|
||||
|
||||
info("Deleting selected node via javascript.");
|
||||
yield inspector.walker.removeNode(div);
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
info("Inspector updated, performing checks.");
|
||||
yield assertNodeSelectedAndPanelsUpdated("#deleteChildren",
|
||||
"ul#deleteChildren");
|
||||
}
|
||||
|
||||
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.");
|
||||
|
||||
info("Selecting an element inside iframe.");
|
||||
let iframe = yield getNodeFront("#deleteIframe", inspector);
|
||||
let div = yield getNodeFrontInFrame("#deleteInIframe", iframe, inspector);
|
||||
yield selectNode(div, inspector);
|
||||
|
||||
info("Deleting selected node via javascript.");
|
||||
yield inspector.walker.removeNode(iframe);
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
info("Inspector updated, performing checks.");
|
||||
yield assertNodeSelectedAndPanelsUpdated("body", "body");
|
||||
}
|
||||
|
||||
function* testDeleteWithNonElementNode() {
|
||||
info("Selecting a node, deleting it via context menu and checking that " +
|
||||
"its parent node is selected and breadcrumbs are updated " +
|
||||
"when the node is followed by a non-element node");
|
||||
|
||||
yield deleteNodeWithContextMenu("#deleteWithNonElement");
|
||||
|
||||
let expectedCrumbs = ["html", "body", "div#deleteToMakeSingleTextNode"];
|
||||
yield assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
Node.TEXT_NODE);
|
||||
|
||||
// Delete node with key, as cannot delete text node with
|
||||
// context menu at this time.
|
||||
inspector.markup._frame.focus();
|
||||
EventUtils.synthesizeKey("VK_DELETE", {});
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
expectedCrumbs = ["html", "body", "div#deleteToMakeSingleTextNode"];
|
||||
yield assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
Node.ELEMENT_NODE);
|
||||
}
|
||||
|
||||
function* deleteNodeWithContextMenu(selector) {
|
||||
yield selectNode(selector, inspector);
|
||||
let nodeToBeDeleted = inspector.selection.nodeFront;
|
||||
|
||||
info("Getting the node container in the markup view.");
|
||||
let container = yield getContainerForSelector(selector, inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: container.tagLine,
|
||||
});
|
||||
let menuItem = allMenuItems.find(item => item.id === "node-menu-delete");
|
||||
|
||||
info("Clicking 'Delete Node' in the context menu.");
|
||||
is(menuItem.disabled, false, "delete menu item is enabled");
|
||||
menuItem.click();
|
||||
|
||||
// close the open context menu
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
|
||||
info("Waiting for inspector to update.");
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
// Since the mutations are sent asynchronously from the server, the
|
||||
// inspector-updated event triggered by the deletion might happen before
|
||||
// the mutation is received and the element is removed from the
|
||||
// breadcrumbs. See bug 1284125.
|
||||
if (inspector.breadcrumbs.indexOf(nodeToBeDeleted) > -1) {
|
||||
info("Crumbs haven't seen deletion. Waiting for breadcrumbs-updated.");
|
||||
yield inspector.once("breadcrumbs-updated");
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
function* assertNodeSelectedAndCrumbsUpdated(expectedCrumbs,
|
||||
expectedNodeType) {
|
||||
info("Performing checks");
|
||||
let actualNodeType = inspector.selection.nodeFront.nodeType;
|
||||
is(actualNodeType, expectedNodeType, "The node has the right type");
|
||||
|
||||
let breadcrumbs = inspector.panelDoc.querySelectorAll(
|
||||
"#inspector-breadcrumbs .html-arrowscrollbox-inner > *");
|
||||
is(breadcrumbs.length, expectedCrumbs.length,
|
||||
"Have the correct number of breadcrumbs");
|
||||
for (let i = 0; i < breadcrumbs.length; i++) {
|
||||
is(breadcrumbs[i].textContent, expectedCrumbs[i],
|
||||
"Text content for button " + i + " is correct");
|
||||
}
|
||||
}
|
||||
|
||||
function* assertNodeSelectedAndPanelsUpdated(selector, crumbLabel) {
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
is(inspector.selection.nodeFront, nodeFront, "The right node is selected");
|
||||
|
||||
let breadcrumbs = inspector.panelDoc.querySelector(
|
||||
"#inspector-breadcrumbs .html-arrowscrollbox-inner");
|
||||
is(breadcrumbs.querySelector("button[checked=true]").textContent,
|
||||
crumbLabel,
|
||||
"The right breadcrumb is selected");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* 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 to ensure inspector can handle destruction of selected node inside an
|
||||
// iframe.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_delete-selected-node-01.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let iframe = yield getNodeFront("iframe", inspector);
|
||||
let node = yield getNodeFrontInFrame("span", iframe, inspector);
|
||||
yield selectNode(node, inspector);
|
||||
|
||||
info("Removing iframe.");
|
||||
yield inspector.walker.removeNode(iframe);
|
||||
yield inspector.selection.once("detached-front");
|
||||
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
|
||||
is(inspector.selection.nodeFront, body, "Selection is now the body node");
|
||||
|
||||
yield inspector.once("inspector-updated");
|
||||
});
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/* 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";
|
||||
|
||||
// Testing that closing the inspector after navigating to a page doesn't fail.
|
||||
|
||||
const URL_1 = "data:text/plain;charset=UTF-8,abcde";
|
||||
const URL_2 = "data:text/plain;charset=UTF-8,12345";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox } = yield openInspectorForURL(URL_1);
|
||||
|
||||
yield navigateTo(inspector, URL_2);
|
||||
|
||||
info("Destroying toolbox");
|
||||
try {
|
||||
yield toolbox.destroy();
|
||||
ok(true, "Toolbox destroyed");
|
||||
} catch (e) {
|
||||
ok(false, "An exception occured while destroying toolbox");
|
||||
console.error(e);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that switching to the inspector panel and not waiting for it to be fully
|
||||
// loaded doesn't fail the test with unhandled rejected promises.
|
||||
|
||||
add_task(function* () {
|
||||
// At least one assertion is needed to avoid failing the test, but really,
|
||||
// what we're interested in is just having the test pass when switching to the
|
||||
// inspector.
|
||||
ok(true);
|
||||
|
||||
yield addTab("data:text/html;charset=utf-8,test inspector destroy");
|
||||
|
||||
info("Open the toolbox on the debugger panel");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
let toolbox = yield gDevTools.showToolbox(target, "jsdebugger");
|
||||
|
||||
info("Switch to the inspector panel and immediately end the test");
|
||||
let onInspectorSelected = toolbox.once("inspector-selected");
|
||||
toolbox.selectTool("inspector");
|
||||
yield onInspectorSelected;
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* 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 context menu items exapnd all and collapse are shown properly.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<div id='parent-node'><div id='child-node'></div></div>";
|
||||
|
||||
add_task(function* () {
|
||||
// Test is often exceeding time-out threshold, similar to Bug 1137765
|
||||
requestLongerTimeout(2);
|
||||
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Selecting the parent node");
|
||||
|
||||
let front = yield getNodeFrontForSelector("#parent-node", inspector);
|
||||
|
||||
yield selectNode(front, inspector);
|
||||
|
||||
info("Simulating context menu click on the selected node container.");
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: getContainerForNodeFront(front, inspector).tagLine,
|
||||
});
|
||||
let nodeMenuCollapseElement =
|
||||
allMenuItems.find(item => item.id === "node-menu-collapse");
|
||||
let nodeMenuExpandElement =
|
||||
allMenuItems.find(item => item.id === "node-menu-expand");
|
||||
|
||||
ok(nodeMenuCollapseElement.disabled, "Collapse option is disabled");
|
||||
ok(!nodeMenuExpandElement.disabled, "ExpandAll option is enabled");
|
||||
|
||||
info("Testing whether expansion works properly");
|
||||
nodeMenuExpandElement.click();
|
||||
|
||||
info("Waiting for expansion to occur");
|
||||
yield waitForMultipleChildrenUpdates(inspector);
|
||||
let markUpContainer = getContainerForNodeFront(front, inspector);
|
||||
ok(markUpContainer.expanded, "node has been successfully expanded");
|
||||
|
||||
// reselecting node after expansion
|
||||
yield selectNode(front, inspector);
|
||||
|
||||
info("Testing whether collapse works properly");
|
||||
info("Simulating context menu click on the selected node container.");
|
||||
allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: getContainerForNodeFront(front, inspector).tagLine,
|
||||
});
|
||||
nodeMenuCollapseElement =
|
||||
allMenuItems.find(item => item.id === "node-menu-collapse");
|
||||
nodeMenuExpandElement =
|
||||
allMenuItems.find(item => item.id === "node-menu-expand");
|
||||
|
||||
ok(!nodeMenuCollapseElement.disabled, "Collapse option is enabled");
|
||||
ok(!nodeMenuExpandElement.disabled, "ExpandAll option is enabled");
|
||||
nodeMenuCollapseElement.click();
|
||||
|
||||
info("Waiting for collapse to occur");
|
||||
yield waitForMultipleChildrenUpdates(inspector);
|
||||
ok(!markUpContainer.expanded, "node has been successfully collapsed");
|
||||
});
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* eslint key-spacing: 0 */
|
||||
"use strict";
|
||||
|
||||
// Testing that the gcli 'inspect' command works as it should.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_gcli-inspect-command.html";
|
||||
|
||||
add_task(function* () {
|
||||
return helpers.addTabWithToolbar(TEST_URI, Task.async(function* (options) {
|
||||
let {inspector} = yield openInspector();
|
||||
|
||||
let checkSelection = Task.async(function* (selector) {
|
||||
let node = yield getNodeFront(selector, inspector);
|
||||
is(inspector.selection.nodeFront, node, "the current selection is correct");
|
||||
});
|
||||
|
||||
yield helpers.audit(options, [
|
||||
{
|
||||
setup: "inspect",
|
||||
check: {
|
||||
input: "inspect",
|
||||
hints: " <selector>",
|
||||
markup: "VVVVVVV",
|
||||
status: "ERROR",
|
||||
args: {
|
||||
selector: {
|
||||
message: "Value required for \u2018selector\u2019."
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
setup: "inspect div",
|
||||
check: {
|
||||
input: "inspect div",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
selector: { message: "" },
|
||||
}
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection("div"),
|
||||
},
|
||||
{
|
||||
setup: "inspect .someclass",
|
||||
check: {
|
||||
input: "inspect .someclass",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
selector: { message: "" },
|
||||
}
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection(".someclass"),
|
||||
},
|
||||
{
|
||||
setup: "inspect #someid",
|
||||
check: {
|
||||
input: "inspect #someid",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
selector: { message: "" },
|
||||
}
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection("#someid"),
|
||||
},
|
||||
{
|
||||
setup: "inspect button[disabled]",
|
||||
check: {
|
||||
input: "inspect button[disabled]",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
selector: { message: "" },
|
||||
}
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection("button[disabled]"),
|
||||
},
|
||||
{
|
||||
setup: "inspect p>strong",
|
||||
check: {
|
||||
input: "inspect p>strong",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVVVVV",
|
||||
status: "VALID",
|
||||
args: {
|
||||
selector: { message: "" },
|
||||
}
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection("p>strong"),
|
||||
},
|
||||
{
|
||||
setup: "inspect :root",
|
||||
check: {
|
||||
input: "inspect :root",
|
||||
hints: "",
|
||||
markup: "VVVVVVVVVVVVV",
|
||||
status: "VALID"
|
||||
},
|
||||
exec: {},
|
||||
post: () => checkSelection(":root"),
|
||||
},
|
||||
]);
|
||||
}));
|
||||
});
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/* 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 nodes in the markup-view shows the highlighter over
|
||||
// those nodes
|
||||
add_task(function* () {
|
||||
info("Loading the test document and opening the inspector");
|
||||
let {toolbox, inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>");
|
||||
|
||||
let isVisible = yield testActor.isHighlighting(toolbox);
|
||||
ok(!isVisible, "The highlighter is hidden by default");
|
||||
|
||||
info("Selecting the test node");
|
||||
yield selectNode("span", inspector);
|
||||
let container = yield getContainerForSelector("h1", inspector);
|
||||
|
||||
let onHighlighterReady = toolbox.once("highlighter-ready");
|
||||
EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"},
|
||||
inspector.markup.doc.defaultView);
|
||||
yield onHighlighterReady;
|
||||
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown on a markup container hover");
|
||||
|
||||
ok((yield testActor.assertHighlightedNode("h1")),
|
||||
"The highlighter highlights the right node");
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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 is correctly displayed over a variety of elements
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_highlighter.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Selecting the simple, non-transformed DIV");
|
||||
yield selectAndHighlightNode("#simple-div", inspector);
|
||||
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown");
|
||||
ok((yield testActor.assertHighlightedNode("#simple-div")),
|
||||
"The highlighter's outline corresponds to the simple div");
|
||||
yield testActor.isNodeCorrectlyHighlighted("#simple-div", is, "non-zoomed");
|
||||
|
||||
info("Selecting the rotated DIV");
|
||||
yield selectAndHighlightNode("#rotated-div", inspector);
|
||||
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown");
|
||||
yield testActor.isNodeCorrectlyHighlighted("#rotated-div", is, "rotated");
|
||||
|
||||
info("Selecting the zero width height DIV");
|
||||
yield selectAndHighlightNode("#widthHeightZero-div", inspector);
|
||||
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is shown");
|
||||
yield testActor.isNodeCorrectlyHighlighted("#widthHeightZero-div", is,
|
||||
"zero width height");
|
||||
});
|
||||
|
|
@ -0,0 +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";
|
||||
|
||||
// Test that iframes are correctly highlighted.
|
||||
|
||||
const IFRAME_SRC = "<style>" +
|
||||
"body {" +
|
||||
"margin:0;" +
|
||||
"height:100%;" +
|
||||
"background-color:red" +
|
||||
"}" +
|
||||
"</style><body>hello from iframe</body>";
|
||||
|
||||
const DOCUMENT_SRC = "<style>" +
|
||||
"iframe {" +
|
||||
"height:200px;" +
|
||||
"border: 11px solid black;" +
|
||||
"padding: 13px;" +
|
||||
"}" +
|
||||
"body,iframe {" +
|
||||
"margin:0" +
|
||||
"}" +
|
||||
"</style>" +
|
||||
"<body>" +
|
||||
"<iframe src='data:text/html;charset=utf-8," + IFRAME_SRC + "'></iframe>" +
|
||||
"</body>";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," + DOCUMENT_SRC;
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox, testActor } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Waiting for box mode to show.");
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
yield inspector.highlighter.showBoxModel(body);
|
||||
|
||||
info("Waiting for element picker to become active.");
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Moving mouse over iframe padding.");
|
||||
yield moveMouseOver("iframe", 1, 1);
|
||||
|
||||
info("Performing checks");
|
||||
yield testActor.isNodeCorrectlyHighlighted("iframe", is);
|
||||
|
||||
info("Scrolling the document");
|
||||
yield testActor.setProperty("iframe", "style", "margin-bottom: 2000px");
|
||||
yield testActor.eval("window.scrollBy(0, 40);");
|
||||
|
||||
// target the body within the iframe
|
||||
let iframeBodySelector = ["iframe", "body"];
|
||||
|
||||
info("Moving mouse over iframe body");
|
||||
yield moveMouseOver("iframe", 40, 40);
|
||||
|
||||
ok((yield testActor.assertHighlightedNode(iframeBodySelector)),
|
||||
"highlighter shows the right node");
|
||||
yield testActor.isNodeCorrectlyHighlighted(iframeBodySelector, is);
|
||||
|
||||
info("Waiting for the element picker to deactivate.");
|
||||
yield inspector.toolbox.highlighterUtils.stopPicker();
|
||||
|
||||
function moveMouseOver(selector, x, y) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
testActor.synthesizeMouse({selector, x, y, options: {type: "mousemove"}});
|
||||
return inspector.toolbox.once("picker-node-hovered");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* 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";
|
||||
|
||||
// Check that various highlighter elements exist.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,<div>test</div>";
|
||||
|
||||
// IDs of all highlighter elements that we expect to find in the canvasFrame.
|
||||
const ELEMENTS = ["box-model-root",
|
||||
"box-model-elements",
|
||||
"box-model-margin",
|
||||
"box-model-border",
|
||||
"box-model-padding",
|
||||
"box-model-content",
|
||||
"box-model-guide-top",
|
||||
"box-model-guide-right",
|
||||
"box-model-guide-bottom",
|
||||
"box-model-guide-left",
|
||||
"box-model-infobar-container",
|
||||
"box-model-infobar-tagname",
|
||||
"box-model-infobar-id",
|
||||
"box-model-infobar-classes",
|
||||
"box-model-infobar-pseudo-classes",
|
||||
"box-model-infobar-dimensions"];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Show the box-model highlighter");
|
||||
let divFront = yield getNodeFront("div", inspector);
|
||||
yield inspector.highlighter.showBoxModel(divFront);
|
||||
|
||||
for (let id of ELEMENTS) {
|
||||
let foundId = yield testActor.getHighlighterNodeAttribute(id, "id");
|
||||
is(foundId, id, "Element " + id + " found");
|
||||
}
|
||||
|
||||
info("Hide the box-model highlighter");
|
||||
yield inspector.highlighter.hideBoxModel();
|
||||
});
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
/* 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";
|
||||
|
||||
// Check that custom highlighters can be retrieved by type and that they expose
|
||||
// the expected API.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,custom highlighters";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield onlyOneInstanceOfMainHighlighter(inspector);
|
||||
yield manyInstancesOfCustomHighlighters(inspector);
|
||||
yield showHideMethodsAreAvailable(inspector);
|
||||
yield unknownHighlighterTypeShouldntBeAccepted(inspector);
|
||||
});
|
||||
|
||||
function* onlyOneInstanceOfMainHighlighter({inspector}) {
|
||||
info("Check that the inspector always sends back the same main highlighter");
|
||||
|
||||
let h1 = yield inspector.getHighlighter(false);
|
||||
let h2 = yield inspector.getHighlighter(false);
|
||||
is(h1, h2, "The same highlighter front was returned");
|
||||
|
||||
is(h1.typeName, "highlighter", "The right front type was returned");
|
||||
}
|
||||
|
||||
function* manyInstancesOfCustomHighlighters({inspector}) {
|
||||
let h1 = yield inspector.getHighlighterByType("BoxModelHighlighter");
|
||||
let h2 = yield inspector.getHighlighterByType("BoxModelHighlighter");
|
||||
ok(h1 !== h2, "getHighlighterByType returns new instances every time (1)");
|
||||
|
||||
let h3 = yield inspector.getHighlighterByType("CssTransformHighlighter");
|
||||
let h4 = yield inspector.getHighlighterByType("CssTransformHighlighter");
|
||||
ok(h3 !== h4, "getHighlighterByType returns new instances every time (2)");
|
||||
ok(h3 !== h1 && h3 !== h2,
|
||||
"getHighlighterByType returns new instances every time (3)");
|
||||
ok(h4 !== h1 && h4 !== h2,
|
||||
"getHighlighterByType returns new instances every time (4)");
|
||||
|
||||
yield h1.finalize();
|
||||
yield h2.finalize();
|
||||
yield h3.finalize();
|
||||
yield h4.finalize();
|
||||
}
|
||||
|
||||
function* showHideMethodsAreAvailable({inspector}) {
|
||||
let h1 = yield inspector.getHighlighterByType("BoxModelHighlighter");
|
||||
let h2 = yield inspector.getHighlighterByType("CssTransformHighlighter");
|
||||
|
||||
ok("show" in h1, "Show method is present on the front API");
|
||||
ok("show" in h2, "Show method is present on the front API");
|
||||
ok("hide" in h1, "Hide method is present on the front API");
|
||||
ok("hide" in h2, "Hide method is present on the front API");
|
||||
|
||||
yield h1.finalize();
|
||||
yield h2.finalize();
|
||||
}
|
||||
|
||||
function* unknownHighlighterTypeShouldntBeAccepted({inspector}) {
|
||||
let h = yield inspector.getHighlighterByType("whatever");
|
||||
ok(!h, "No highlighter was returned for the invalid type");
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* 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 canceling the element picker zooms back on the focused element. Bug 1224304.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_long-divs.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield selectAndHighlightNode("#focus-here", inspector);
|
||||
ok((yield testActor.assertHighlightedNode("#focus-here")),
|
||||
"The highlighter focuses on div#focus-here");
|
||||
ok(isSelectedMarkupNodeInView(),
|
||||
"The currently selected node is on the screen.");
|
||||
|
||||
// Start the picker but skip focusing manually focusing on the target, let the element
|
||||
// picker do the focusing.
|
||||
yield startPicker(toolbox, true);
|
||||
yield moveMouseOver("#zoom-here");
|
||||
ok(!isSelectedMarkupNodeInView(),
|
||||
"The currently selected node is off the screen.");
|
||||
|
||||
yield cancelPickerByShortcut();
|
||||
ok(isSelectedMarkupNodeInView(),
|
||||
"The currently selected node is focused back on the screen.");
|
||||
|
||||
function cancelPickerByShortcut() {
|
||||
info("Key pressed. Waiting for picker to be canceled.");
|
||||
testActor.synthesizeKey({key: "VK_ESCAPE", options: {}});
|
||||
return inspector.toolbox.once("picker-canceled");
|
||||
}
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info(`Waiting for element ${selector} to be hovered in the markup view`);
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: selector
|
||||
});
|
||||
return inspector.markup.once("showcontainerhovered");
|
||||
}
|
||||
|
||||
function isSelectedMarkupNodeInView() {
|
||||
const selectedNodeContainer = inspector.markup._selectedContainer.elt;
|
||||
const bounds = selectedNodeContainer.getBoundingClientRect();
|
||||
return bounds.top > 0 && bounds.bottom > 0;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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";
|
||||
|
||||
//
|
||||
// Whitelisting this test.
|
||||
// As part of bug 1077403, the leaking uncaught rejection should be fixed.
|
||||
//
|
||||
thisTestLeaksUncaughtRejectionsAndShouldBeFixed("false");
|
||||
|
||||
// Test that hovering over the markup-view's containers doesn't always show the
|
||||
// highlighter, depending on the type of node hovered over.
|
||||
|
||||
const TEST_PAGE = URL_ROOT +
|
||||
"doc_inspector_highlighter-comments.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_PAGE);
|
||||
let markupView = inspector.markup;
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Hovering over #id1 and waiting for highlighter to appear.");
|
||||
yield hoverElement("#id1");
|
||||
yield assertHighlighterShownOn("#id1");
|
||||
|
||||
info("Hovering over comment node and ensuring highlighter doesn't appear.");
|
||||
yield hoverComment();
|
||||
yield assertHighlighterHidden();
|
||||
|
||||
info("Hovering over #id1 again and waiting for highlighter to appear.");
|
||||
yield hoverElement("#id1");
|
||||
yield assertHighlighterShownOn("#id1");
|
||||
|
||||
info("Hovering over #id2 and waiting for highlighter to appear.");
|
||||
yield hoverElement("#id2");
|
||||
yield assertHighlighterShownOn("#id2");
|
||||
|
||||
info("Hovering over <script> and ensuring highlighter doesn't appear.");
|
||||
yield hoverElement("script");
|
||||
yield assertHighlighterHidden();
|
||||
|
||||
info("Hovering over #id3 and waiting for highlighter to appear.");
|
||||
yield hoverElement("#id3");
|
||||
yield assertHighlighterShownOn("#id3");
|
||||
|
||||
info("Hovering over hidden #id4 and ensuring highlighter doesn't appear.");
|
||||
yield hoverElement("#id4");
|
||||
yield assertHighlighterHidden();
|
||||
|
||||
info("Hovering over a text node and waiting for highlighter to appear.");
|
||||
yield hoverTextNode("Visible text node");
|
||||
yield assertHighlighterShownOnTextNode("body", 14);
|
||||
|
||||
function hoverContainer(container) {
|
||||
let promise = inspector.toolbox.once("node-highlight");
|
||||
|
||||
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
|
||||
markupView.doc.defaultView);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
function* hoverElement(selector) {
|
||||
info(`Hovering node ${selector} in the markup view`);
|
||||
let container = yield getContainerForSelector(selector, inspector);
|
||||
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);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function hoverTextNode(text) {
|
||||
info(`Hovering the text node "${text}" in the markup view`);
|
||||
let container = [...markupView._containers].filter(([nodeFront]) => {
|
||||
return nodeFront.nodeType === Ci.nsIDOMNode.TEXT_NODE &&
|
||||
nodeFront._form.nodeValue.trim() === text.trim();
|
||||
})[0][1];
|
||||
return hoverContainer(container);
|
||||
}
|
||||
|
||||
function* assertHighlighterShownOn(selector) {
|
||||
ok((yield testActor.assertHighlightedNode(selector)),
|
||||
"Highlighter is shown on the right node: " + selector);
|
||||
}
|
||||
|
||||
function* assertHighlighterShownOnTextNode(parentSelector, childNodeIndex) {
|
||||
ok((yield testActor.assertHighlightedTextNode(parentSelector, childNodeIndex)),
|
||||
"Highlighter is shown on the right text node");
|
||||
}
|
||||
|
||||
function* assertHighlighterHidden() {
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(!isVisible, "Highlighter is hidden");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,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 the creation of the canvas highlighter element of the css grid highlighter.
|
||||
|
||||
const TEST_URL = `
|
||||
<style type='text/css'>
|
||||
#grid {
|
||||
display: grid;
|
||||
}
|
||||
#cell1 {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
}
|
||||
#cell2 {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
}
|
||||
#cell3 {
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
}
|
||||
#cell4 {
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
}
|
||||
</style>
|
||||
<div id="grid">
|
||||
<div id="cell1">cell1</div>
|
||||
<div id="cell2">cell2</div>
|
||||
<div id="cell3">cell3</div>
|
||||
<div id="cell4">cell4</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const HIGHLIGHTER_TYPE = "CssGridHighlighter";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URL));
|
||||
let front = inspector.inspector;
|
||||
let highlighter = yield front.getHighlighterByType(HIGHLIGHTER_TYPE);
|
||||
|
||||
yield isHiddenByDefault(testActor, highlighter);
|
||||
yield isVisibleWhenShown(testActor, inspector, highlighter);
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
||||
function* isHiddenByDefault(testActor, highlighterFront) {
|
||||
info("Checking that the highlighter is hidden by default");
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-grid-canvas", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is hidden by default");
|
||||
}
|
||||
|
||||
function* isVisibleWhenShown(testActor, inspector, highlighterFront) {
|
||||
info("Asking to show the highlighter on the test node");
|
||||
|
||||
let node = yield getNodeFront("#grid", inspector);
|
||||
yield highlighterFront.show(node);
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-grid-canvas", "hidden", highlighterFront);
|
||||
ok(!hidden, "The highlighter is visible");
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield highlighterFront.hide();
|
||||
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-grid-canvas", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is hidden");
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/* 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 the creation of the SVG highlighter elements of the css transform
|
||||
// highlighter.
|
||||
|
||||
const TEST_URL = `
|
||||
<div id="transformed"
|
||||
style="border:1px solid red;width:100px;height:100px;transform:skew(13deg);">
|
||||
</div>
|
||||
<div id="untransformed"
|
||||
style="border:1px solid blue;width:100px;height:100px;">
|
||||
</div>
|
||||
<span id="inline"
|
||||
style="transform:rotate(90deg);">this is an inline transformed element
|
||||
</span>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8," + encodeURI(TEST_URL));
|
||||
let front = inspector.inspector;
|
||||
|
||||
let highlighter = yield front.getHighlighterByType("CssTransformHighlighter");
|
||||
|
||||
yield isHiddenByDefault(testActor, highlighter);
|
||||
yield has2PolygonsAnd4Lines(testActor, highlighter);
|
||||
yield isNotShownForUntransformed(testActor, inspector, highlighter);
|
||||
yield isNotShownForInline(testActor, inspector, highlighter);
|
||||
yield isVisibleWhenShown(testActor, inspector, highlighter);
|
||||
yield linesLinkThePolygons(testActor, inspector, highlighter);
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
||||
function* isHiddenByDefault(testActor, highlighterFront) {
|
||||
info("Checking that the highlighter is hidden by default");
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-elements", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is hidden by default");
|
||||
}
|
||||
|
||||
function* has2PolygonsAnd4Lines(testActor, highlighterFront) {
|
||||
info("Checking that the highlighter is made up of 4 lines and 2 polygons");
|
||||
|
||||
let value = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-untransformed", "class", highlighterFront);
|
||||
is(value, "css-transform-untransformed", "The untransformed polygon exists");
|
||||
|
||||
value = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-transformed", "class", highlighterFront);
|
||||
is(value, "css-transform-transformed", "The transformed polygon exists");
|
||||
|
||||
for (let nb of ["1", "2", "3", "4"]) {
|
||||
value = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-line" + nb, "class", highlighterFront);
|
||||
is(value, "css-transform-line", "The line " + nb + " exists");
|
||||
}
|
||||
}
|
||||
|
||||
function* isNotShownForUntransformed(testActor, inspector, highlighterFront) {
|
||||
info("Asking to show the highlighter on the untransformed test node");
|
||||
|
||||
let node = yield getNodeFront("#untransformed", inspector);
|
||||
yield highlighterFront.show(node);
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-elements", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is still hidden");
|
||||
}
|
||||
|
||||
function* isNotShownForInline(testActor, inspector, highlighterFront) {
|
||||
info("Asking to show the highlighter on the inline test node");
|
||||
|
||||
let node = yield getNodeFront("#inline", inspector);
|
||||
yield highlighterFront.show(node);
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-elements", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is still hidden");
|
||||
}
|
||||
|
||||
function* isVisibleWhenShown(testActor, inspector, highlighterFront) {
|
||||
info("Asking to show the highlighter on the test node");
|
||||
|
||||
let node = yield getNodeFront("#transformed", inspector);
|
||||
yield highlighterFront.show(node);
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-elements", "hidden", highlighterFront);
|
||||
ok(!hidden, "The highlighter is visible");
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield highlighterFront.hide();
|
||||
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-elements", "hidden", highlighterFront);
|
||||
ok(hidden, "The highlighter is hidden");
|
||||
}
|
||||
|
||||
function* linesLinkThePolygons(testActor, inspector, highlighterFront) {
|
||||
info("Showing the highlighter on the transformed node");
|
||||
|
||||
let node = yield getNodeFront("#transformed", inspector);
|
||||
yield highlighterFront.show(node);
|
||||
|
||||
info("Checking that the 4 lines do link the 2 shape's corners");
|
||||
|
||||
let lines = [];
|
||||
for (let nb of ["1", "2", "3", "4"]) {
|
||||
let x1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-line" + nb, "x1", highlighterFront);
|
||||
let y1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-line" + nb, "y1", highlighterFront);
|
||||
let x2 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-line" + nb, "x2", highlighterFront);
|
||||
let y2 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-line" + nb, "y2", highlighterFront);
|
||||
lines.push({x1, y1, x2, y2});
|
||||
}
|
||||
|
||||
let points1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-untransformed", "points", highlighterFront);
|
||||
points1 = points1.split(" ");
|
||||
|
||||
let points2 = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-transformed", "points", highlighterFront);
|
||||
points2 = points2.split(" ");
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
info("Checking line nb " + i);
|
||||
let line = lines[i];
|
||||
|
||||
let p1 = points1[i].split(",");
|
||||
is(p1[0], line.x1,
|
||||
"line " + i + "'s first point matches the untransformed x coordinate");
|
||||
is(p1[1], line.y1,
|
||||
"line " + i + "'s first point matches the untransformed y coordinate");
|
||||
|
||||
let p2 = points2[i].split(",");
|
||||
is(p2[0], line.x2,
|
||||
"line " + i + "'s first point matches the transformed x coordinate");
|
||||
is(p2[1], line.y2,
|
||||
"line " + i + "'s first point matches the transformed y coordinate");
|
||||
}
|
||||
|
||||
yield highlighterFront.hide();
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* 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";
|
||||
|
||||
/*
|
||||
Bug 1014547 - CSS transforms highlighter
|
||||
Test that the highlighter elements created have the right size and coordinates.
|
||||
|
||||
Note that instead of hard-coding values here, the assertions are made by
|
||||
comparing with the result of getAdjustedQuads.
|
||||
|
||||
There's a separate test for checking that getAdjustedQuads actually returns
|
||||
sensible values
|
||||
(devtools/client/shared/test/browser_layoutHelpers-getBoxQuads.js),
|
||||
so the present test doesn't care about that, it just verifies that the css
|
||||
transform highlighter applies those values correctly to the SVG elements
|
||||
*/
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_csstransform.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
|
||||
let highlighter = yield front.getHighlighterByType("CssTransformHighlighter");
|
||||
|
||||
let nodeFront = yield getNodeFront("#test-node", inspector);
|
||||
|
||||
info("Displaying the transform highlighter on test node");
|
||||
yield highlighter.show(nodeFront);
|
||||
|
||||
let data = yield testActor.getAllAdjustedQuads("#test-node");
|
||||
let [expected] = data.border;
|
||||
|
||||
let points = yield testActor.getHighlighterNodeAttribute(
|
||||
"css-transform-transformed", "points", highlighter);
|
||||
let polygonPoints = points.split(" ").map(p => {
|
||||
return {
|
||||
x: +p.substring(0, p.indexOf(",")),
|
||||
y: +p.substring(p.indexOf(",") + 1)
|
||||
};
|
||||
});
|
||||
|
||||
for (let i = 1; i < 5; i++) {
|
||||
is(polygonPoints[i - 1].x, expected["p" + i].x,
|
||||
"p" + i + " x coordinate is correct");
|
||||
is(polygonPoints[i - 1].y, expected["p" + i].y,
|
||||
"p" + i + " y coordinate is correct");
|
||||
}
|
||||
|
||||
info("Hiding the transform highlighter");
|
||||
yield highlighter.hide();
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* 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 can go inside <embed> elements
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_embed.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Get a node inside the <embed> element and select/highlight it");
|
||||
let body = yield getEmbeddedBody(inspector);
|
||||
yield selectAndHighlightNode(body, inspector);
|
||||
|
||||
let selectedNode = inspector.selection.nodeFront;
|
||||
is(selectedNode.tagName.toLowerCase(), "body", "The selected node is <body>");
|
||||
ok(selectedNode.baseURI.endsWith("doc_inspector_menu.html"),
|
||||
"The selected node is the <body> node inside the <embed> element");
|
||||
});
|
||||
|
||||
function* getEmbeddedBody({walker}) {
|
||||
let embed = yield walker.querySelector(walker.rootNode, "embed");
|
||||
let {nodes} = yield walker.children(embed);
|
||||
let contentDoc = nodes[0];
|
||||
let body = yield walker.querySelector(contentDoc, "body");
|
||||
return body;
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* 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 eyedropper can copy colors to the clipboard
|
||||
|
||||
const HIGHLIGHTER_TYPE = "EyeDropper";
|
||||
const ID = "eye-dropper-";
|
||||
const TEST_URI = "data:text/html;charset=utf-8,<style>html{background:red}</style>";
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URI)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
helper.prefix = ID;
|
||||
|
||||
let {show, finalize,
|
||||
waitForElementAttributeSet, waitForElementAttributeRemoved} = helper;
|
||||
|
||||
info("Show the eyedropper with the copyOnSelect option");
|
||||
yield show("html", {copyOnSelect: true});
|
||||
|
||||
info("Make sure to wait until the eyedropper is done taking a screenshot of the page");
|
||||
yield waitForElementAttributeSet("root", "drawn", helper);
|
||||
|
||||
yield waitForClipboardPromise(() => {
|
||||
info("Activate the eyedropper so the background color is copied");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
}, "#FF0000");
|
||||
|
||||
ok(true, "The clipboard contains the right value");
|
||||
|
||||
yield waitForElementAttributeRemoved("root", "drawn", helper);
|
||||
yield waitForElementAttributeSet("root", "hidden", helper);
|
||||
ok(true, "The eyedropper is now hidden");
|
||||
|
||||
finalize();
|
||||
});
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/* 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 eyedropper opens correctly even when the page defines CSP headers.
|
||||
|
||||
const HIGHLIGHTER_TYPE = "EyeDropper";
|
||||
const ID = "eye-dropper-";
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_csp.html";
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URI)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
helper.prefix = ID;
|
||||
let {show, hide, finalize, isElementHidden, waitForElementAttributeSet} = helper;
|
||||
|
||||
info("Try to display the eyedropper");
|
||||
yield show("html");
|
||||
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(!hidden, "The eyedropper is now shown");
|
||||
|
||||
info("Wait until the eyedropper is done taking a screenshot of the page");
|
||||
yield waitForElementAttributeSet("root", "drawn", helper);
|
||||
ok(true, "The image data was retrieved successfully from the window");
|
||||
|
||||
yield hide();
|
||||
finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
/* 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 the eyedropper mouse and keyboard handling.
|
||||
|
||||
const HIGHLIGHTER_TYPE = "EyeDropper";
|
||||
const ID = "eye-dropper-";
|
||||
const TEST_URI = `
|
||||
<style>
|
||||
html{width:100%;height:100%;}
|
||||
</style>
|
||||
<body>eye-dropper test</body>`;
|
||||
|
||||
const MOVE_EVENTS_DATA = [
|
||||
{type: "mouse", x: 200, y: 100, expected: {x: 200, y: 100}},
|
||||
{type: "mouse", x: 100, y: 200, expected: {x: 100, y: 200}},
|
||||
{type: "keyboard", key: "VK_LEFT", expected: {x: 99, y: 200}},
|
||||
{type: "keyboard", key: "VK_LEFT", shift: true, expected: {x: 89, y: 200}},
|
||||
{type: "keyboard", key: "VK_RIGHT", expected: {x: 90, y: 200}},
|
||||
{type: "keyboard", key: "VK_RIGHT", shift: true, expected: {x: 100, y: 200}},
|
||||
{type: "keyboard", key: "VK_DOWN", expected: {x: 100, y: 201}},
|
||||
{type: "keyboard", key: "VK_DOWN", shift: true, expected: {x: 100, y: 211}},
|
||||
{type: "keyboard", key: "VK_UP", expected: {x: 100, y: 210}},
|
||||
{type: "keyboard", key: "VK_UP", shift: true, expected: {x: 100, y: 200}},
|
||||
// Mouse initialization for left and top snapping
|
||||
{type: "mouse", x: 7, y: 7, expected: {x: 7, y: 7}},
|
||||
// Left Snapping
|
||||
{type: "keyboard", key: "VK_LEFT", shift: true, expected: {x: 0, y: 7},
|
||||
desc: "Left Snapping to x=0"},
|
||||
// Top Snapping
|
||||
{type: "keyboard", key: "VK_UP", shift: true, expected: {x: 0, y: 0},
|
||||
desc: "Top Snapping to y=0"},
|
||||
// Mouse initialization for right snapping
|
||||
{
|
||||
type: "mouse",
|
||||
x: (width, height) => width - 5,
|
||||
y: 0,
|
||||
expected: {
|
||||
x: (width, height) => width - 5,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
// Right snapping
|
||||
{
|
||||
type: "keyboard",
|
||||
key: "VK_RIGHT",
|
||||
shift: true,
|
||||
expected: {
|
||||
x: (width, height) => width,
|
||||
y: 0
|
||||
},
|
||||
desc: "Right snapping to x=max window width available"
|
||||
},
|
||||
// Mouse initialization for bottom snapping
|
||||
{
|
||||
type: "mouse",
|
||||
x: 0,
|
||||
y: (width, height) => height - 5,
|
||||
expected: {
|
||||
x: 0,
|
||||
y: (width, height) => height - 5
|
||||
}
|
||||
},
|
||||
// Bottom snapping
|
||||
{
|
||||
type: "keyboard",
|
||||
key: "VK_DOWN",
|
||||
shift: true,
|
||||
expected: {
|
||||
x: 0,
|
||||
y: (width, height) => height
|
||||
},
|
||||
desc: "Bottom snapping to y=max window height available"
|
||||
},
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
|
||||
let helper = yield getHighlighterHelperFor(HIGHLIGHTER_TYPE)({inspector, testActor});
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
yield helper.show("html");
|
||||
yield respondsToMoveEvents(helper, testActor);
|
||||
yield respondsToReturnAndEscape(helper);
|
||||
|
||||
helper.finalize();
|
||||
});
|
||||
|
||||
function* respondsToMoveEvents(helper, testActor) {
|
||||
info("Checking that the eyedropper responds to events from the mouse and keyboard");
|
||||
let {mouse} = helper;
|
||||
let {width, height} = yield testActor.getBoundingClientRect("html");
|
||||
|
||||
for (let {type, x, y, key, shift, expected, desc} of MOVE_EVENTS_DATA) {
|
||||
x = typeof x === "function" ? x(width, height) : x;
|
||||
y = typeof y === "function" ? y(width, height) : y;
|
||||
expected.x = typeof expected.x === "function" ?
|
||||
expected.x(width, height) : expected.x;
|
||||
expected.y = typeof expected.y === "function" ?
|
||||
expected.y(width, height) : expected.y;
|
||||
|
||||
if (typeof desc === "undefined") {
|
||||
info(`Simulating a ${type} event to move to ${expected.x} ${expected.y}`);
|
||||
} else {
|
||||
info(`Simulating ${type} event: ${desc}`);
|
||||
}
|
||||
|
||||
if (type === "mouse") {
|
||||
yield mouse.move(x, y);
|
||||
} else if (type === "keyboard") {
|
||||
let options = shift ? {shiftKey: true} : {};
|
||||
yield EventUtils.synthesizeKey(key, options);
|
||||
}
|
||||
yield checkPosition(expected, helper);
|
||||
}
|
||||
}
|
||||
|
||||
function* checkPosition({x, y}, {getElementAttribute}) {
|
||||
let style = yield getElementAttribute("root", "style");
|
||||
is(style, `top:${y}px;left:${x}px;`,
|
||||
`The eyedropper is at the expected ${x} ${y} position`);
|
||||
}
|
||||
|
||||
function* respondsToReturnAndEscape({isElementHidden, show}) {
|
||||
info("Simulating return to select the color and hide the eyedropper");
|
||||
|
||||
yield EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden");
|
||||
|
||||
info("Showing the eyedropper again and simulating escape to hide it");
|
||||
|
||||
yield show("html");
|
||||
yield EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper has been hidden again");
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/* 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 the position of the eyedropper label.
|
||||
// It should move around when the eyedropper is close to the edges of the viewport so as
|
||||
// to always stay visible.
|
||||
|
||||
const HIGHLIGHTER_TYPE = "EyeDropper";
|
||||
const ID = "eye-dropper-";
|
||||
|
||||
const HTML = `
|
||||
<style>
|
||||
html, body {height: 100%; margin: 0;}
|
||||
body {background: linear-gradient(red, gold); display: flex; justify-content: center;
|
||||
align-items: center;}
|
||||
</style>
|
||||
Eyedropper label position test
|
||||
`;
|
||||
const TEST_PAGE = "data:text/html;charset=utf-8," + encodeURI(HTML);
|
||||
|
||||
const TEST_DATA = [{
|
||||
desc: "Move the mouse to the center of the screen",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: width / 2, y: height / 2};
|
||||
},
|
||||
expectedPositions: {top: false, right: false, left: false}
|
||||
}, {
|
||||
desc: "Move the mouse to the center left",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: 0, y: height / 2};
|
||||
},
|
||||
expectedPositions: {top: false, right: true, left: false}
|
||||
}, {
|
||||
desc: "Move the mouse to the center right",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: width, y: height / 2};
|
||||
},
|
||||
expectedPositions: {top: false, right: false, left: true}
|
||||
}, {
|
||||
desc: "Move the mouse to the bottom center",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: width / 2, y: height};
|
||||
},
|
||||
expectedPositions: {top: true, right: false, left: false}
|
||||
}, {
|
||||
desc: "Move the mouse to the bottom left",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: 0, y: height};
|
||||
},
|
||||
expectedPositions: {top: true, right: true, left: false}
|
||||
}, {
|
||||
desc: "Move the mouse to the bottom right",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: width, y: height};
|
||||
},
|
||||
expectedPositions: {top: true, right: false, left: true}
|
||||
}, {
|
||||
desc: "Move the mouse to the top left",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: 0, y: 0};
|
||||
},
|
||||
expectedPositions: {top: false, right: true, left: false}
|
||||
}, {
|
||||
desc: "Move the mouse to the top right",
|
||||
getCoordinates: (width, height) => {
|
||||
return {x: width, y: 0};
|
||||
},
|
||||
expectedPositions: {top: false, right: false, left: true}
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_PAGE);
|
||||
let helper = yield getHighlighterHelperFor(HIGHLIGHTER_TYPE)({inspector, testActor});
|
||||
helper.prefix = ID;
|
||||
|
||||
let {mouse, show, hide, finalize} = helper;
|
||||
let {width, height} = yield testActor.getBoundingClientRect("html");
|
||||
|
||||
// This test fails in non-e10s windows if we use width and height. For some reasons, the
|
||||
// mouse events can't be dispatched/handled properly when we try to move the eyedropper
|
||||
// to the far right and/or bottom of the screen. So just removing 10px from each side
|
||||
// fixes it.
|
||||
width -= 10;
|
||||
height -= 10;
|
||||
|
||||
info("Show the eyedropper on the page");
|
||||
yield show("html");
|
||||
|
||||
info("Move the eyedropper around and check that the label appears at the right place");
|
||||
for (let {desc, getCoordinates, expectedPositions} of TEST_DATA) {
|
||||
info(desc);
|
||||
let {x, y} = getCoordinates(width, height);
|
||||
info(`Moving the mouse to ${x} ${y}`);
|
||||
yield mouse.move(x, y);
|
||||
yield checkLabelPositionAttributes(helper, expectedPositions);
|
||||
}
|
||||
|
||||
info("Hide the eyedropper");
|
||||
yield hide();
|
||||
finalize();
|
||||
});
|
||||
|
||||
function* checkLabelPositionAttributes(helper, positions) {
|
||||
for (let position in positions) {
|
||||
is((yield hasAttribute(helper, position)), positions[position],
|
||||
`The label was ${positions[position] ? "" : "not "}moved to the ${position}`);
|
||||
}
|
||||
}
|
||||
|
||||
function* hasAttribute({getElementAttribute}, name) {
|
||||
let value = yield getElementAttribute("root", name);
|
||||
return value !== null;
|
||||
}
|
||||
|
|
@ -0,0 +1,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";
|
||||
|
||||
// Test the basic structure of the eye-dropper highlighter.
|
||||
|
||||
const HIGHLIGHTER_TYPE = "EyeDropper";
|
||||
const ID = "eye-dropper-";
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL("data:text/html;charset=utf-8,eye-dropper test")
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
helper.prefix = ID;
|
||||
|
||||
yield isInitiallyHidden(helper);
|
||||
yield canBeShownAndHidden(helper);
|
||||
|
||||
helper.finalize();
|
||||
});
|
||||
|
||||
function* isInitiallyHidden({isElementHidden}) {
|
||||
info("Checking that the eyedropper is hidden by default");
|
||||
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper is hidden by default");
|
||||
}
|
||||
|
||||
function* canBeShownAndHidden({show, hide, isElementHidden, getElementAttribute}) {
|
||||
info("Asking to show and hide the highlighter actually works");
|
||||
|
||||
yield show("html");
|
||||
let hidden = yield isElementHidden("root");
|
||||
ok(!hidden, "The eyedropper is now shown");
|
||||
|
||||
let style = yield getElementAttribute("root", "style");
|
||||
is(style, "top:100px;left:100px;", "The eyedropper is correctly positioned");
|
||||
|
||||
yield hide();
|
||||
hidden = yield isElementHidden("root");
|
||||
ok(hidden, "The eyedropper is now hidden again");
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the eyedropper icons in the toolbar and in the color picker aren't displayed
|
||||
// when the page isn't an HTML one.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_xbl.xul";
|
||||
const TEST_URL_2 =
|
||||
"data:text/html;charset=utf-8,<h1 style='color:red'>HTML test page</h1>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Check the inspector toolbar");
|
||||
let button = inspector.panelDoc.querySelector("#inspector-eyedropper-toggle");
|
||||
ok(isDisabled(button), "The button is hidden in the toolbar");
|
||||
|
||||
info("Check the color picker");
|
||||
yield selectNode("#scale", inspector);
|
||||
|
||||
// Find the color swatch in the rule-view.
|
||||
let ruleView = inspector.ruleview.view;
|
||||
let ruleViewDocument = ruleView.styleDocument;
|
||||
let swatchEl = ruleViewDocument.querySelector(".ruleview-colorswatch");
|
||||
|
||||
info("Open the color picker");
|
||||
let cPicker = ruleView.tooltips.colorPicker;
|
||||
let onColorPickerReady = cPicker.once("ready");
|
||||
swatchEl.click();
|
||||
yield onColorPickerReady;
|
||||
|
||||
button = cPicker.tooltip.doc.querySelector("#eyedropper-button");
|
||||
ok(isDisabled(button), "The button is disabled in the color picker");
|
||||
|
||||
info("Navigate to a HTML document");
|
||||
yield navigateTo(inspector, TEST_URL_2);
|
||||
|
||||
info("Check the inspector toolbar in HTML document");
|
||||
button = inspector.panelDoc.querySelector("#inspector-eyedropper-toggle");
|
||||
ok(!isDisabled(button), "The button is enabled in the toolbar");
|
||||
|
||||
info("Check the color picker in HTML document");
|
||||
// Find the color swatch in the rule-view.
|
||||
yield selectNode("h1", inspector);
|
||||
|
||||
ruleView = inspector.ruleview.view;
|
||||
ruleViewDocument = ruleView.styleDocument;
|
||||
swatchEl = ruleViewDocument.querySelector(".ruleview-colorswatch");
|
||||
|
||||
info("Open the color picker in HTML document");
|
||||
cPicker = ruleView.tooltips.colorPicker;
|
||||
onColorPickerReady = cPicker.once("ready");
|
||||
swatchEl.click();
|
||||
yield onColorPickerReady;
|
||||
|
||||
button = cPicker.tooltip.doc.querySelector("#eyedropper-button");
|
||||
ok(!isDisabled(button), "The button is enabled in the color picker");
|
||||
});
|
||||
|
||||
function isDisabled(button) {
|
||||
return button.disabled;
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/* 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 the creation of the geometry highlighter elements.
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf-8,
|
||||
<span id='inline'></span>
|
||||
<div id='positioned' style='
|
||||
background:yellow;
|
||||
position:absolute;
|
||||
left:5rem;
|
||||
top:30px;
|
||||
right:300px;
|
||||
bottom:10em;'></div>
|
||||
<div id='sized' style='
|
||||
background:red;
|
||||
width:5em;
|
||||
height:50%;'></div>`;
|
||||
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
|
||||
const ID = "geometry-editor-";
|
||||
const SIDES = ["left", "right", "top", "bottom"];
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
let { finalize } = helper;
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
yield hasArrowsAndLabelsAndHandlers(helper);
|
||||
yield isHiddenForNonPositionedNonSizedElement(helper);
|
||||
yield sideArrowsAreDisplayedForPositionedNode(helper);
|
||||
|
||||
finalize();
|
||||
});
|
||||
|
||||
function* hasArrowsAndLabelsAndHandlers({getElementAttribute}) {
|
||||
info("Checking that the highlighter has the expected arrows and labels");
|
||||
|
||||
for (let name of [...SIDES]) {
|
||||
let value = yield getElementAttribute("arrow-" + name, "class");
|
||||
is(value, ID + "arrow " + name, "The " + name + " arrow exists");
|
||||
|
||||
value = yield getElementAttribute("label-text-" + name, "class");
|
||||
is(value, ID + "label-text", "The " + name + " label exists");
|
||||
|
||||
value = yield getElementAttribute("handler-" + name, "class");
|
||||
is(value, ID + "handler-" + name, "The " + name + " handler exists");
|
||||
}
|
||||
}
|
||||
|
||||
function* isHiddenForNonPositionedNonSizedElement(
|
||||
{show, hide, isElementHidden}) {
|
||||
info("Asking to show the highlighter on an inline, non p ositioned element");
|
||||
|
||||
yield show("#inline");
|
||||
|
||||
for (let name of [...SIDES]) {
|
||||
let hidden = yield isElementHidden("arrow-" + name);
|
||||
ok(hidden, "The " + name + " arrow is hidden");
|
||||
|
||||
hidden = yield isElementHidden("handler-" + name);
|
||||
ok(hidden, "The " + name + " handler is hidden");
|
||||
}
|
||||
}
|
||||
|
||||
function* sideArrowsAreDisplayedForPositionedNode(
|
||||
{show, hide, isElementHidden}) {
|
||||
info("Asking to show the highlighter on the positioned node");
|
||||
|
||||
yield show("#positioned");
|
||||
|
||||
for (let name of SIDES) {
|
||||
let hidden = yield isElementHidden("arrow-" + name);
|
||||
ok(!hidden, "The " + name + " arrow is visible for the positioned node");
|
||||
|
||||
hidden = yield isElementHidden("handler-" + name);
|
||||
ok(!hidden, "The " + name + " handler is visible for the positioned node");
|
||||
}
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Globals defined in: devtools/client/inspector/test/head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the geometry highlighter labels are correct.
|
||||
|
||||
const TEST_URL = `data:text/html;charset=utf-8,
|
||||
<div id='positioned' style='
|
||||
background:yellow;
|
||||
position:absolute;
|
||||
left:5rem;
|
||||
top:30px;
|
||||
right:300px;
|
||||
bottom:10em;'></div>
|
||||
<div id='positioned2' style='
|
||||
background:blue;
|
||||
position:absolute;
|
||||
right:10%;
|
||||
top:5vmin;'>test element</div>
|
||||
<div id='relative' style='
|
||||
background:green;
|
||||
position:relative;
|
||||
top:10px;
|
||||
left:20px;
|
||||
bottom:30px;
|
||||
right:40px;
|
||||
width:100px;
|
||||
height:100px;'></div>
|
||||
<div id='relative2' style='
|
||||
background:grey;
|
||||
position:relative;
|
||||
top:0;bottom:-50px;
|
||||
height:3em;'>relative</div>`;
|
||||
|
||||
const ID = "geometry-editor-";
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
|
||||
const POSITIONED_ELEMENT_TESTS = [{
|
||||
selector: "#positioned",
|
||||
expectedLabels: [
|
||||
{side: "left", visible: true, label: "5rem"},
|
||||
{side: "top", visible: true, label: "30px"},
|
||||
{side: "right", visible: true, label: "300px"},
|
||||
{side: "bottom", visible: true, label: "10em"}
|
||||
]
|
||||
}, {
|
||||
selector: "#positioned2",
|
||||
expectedLabels: [
|
||||
{side: "left", visible: false},
|
||||
{side: "top", visible: true, label: "5vmin"},
|
||||
{side: "right", visible: true, label: "10%"},
|
||||
{side: "bottom", visible: false}
|
||||
]
|
||||
}, {
|
||||
selector: "#relative",
|
||||
expectedLabels: [
|
||||
{side: "left", visible: true, label: "20px"},
|
||||
{side: "top", visible: true, label: "10px"},
|
||||
{side: "right", visible: false},
|
||||
{side: "bottom", visible: false}
|
||||
]
|
||||
}, {
|
||||
selector: "#relative2",
|
||||
expectedLabels: [
|
||||
{side: "left", visible: false},
|
||||
{side: "top", visible: true, label: "0px"},
|
||||
{side: "right", visible: false},
|
||||
{side: "bottom", visible: false}
|
||||
]
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
let { finalize } = helper;
|
||||
|
||||
yield positionLabelsAreCorrect(helper);
|
||||
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* positionLabelsAreCorrect(
|
||||
{show, hide, isElementHidden, getElementTextContent}
|
||||
) {
|
||||
info("Highlight nodes and check position labels");
|
||||
|
||||
for (let {selector, expectedLabels} of POSITIONED_ELEMENT_TESTS) {
|
||||
info("Testing node " + selector);
|
||||
|
||||
yield show(selector);
|
||||
|
||||
for (let {side, visible, label} of expectedLabels) {
|
||||
let id = "label-" + side;
|
||||
|
||||
let hidden = yield isElementHidden(id);
|
||||
if (visible) {
|
||||
ok(!hidden, "The " + side + " label is visible");
|
||||
|
||||
let value = yield getElementTextContent(id);
|
||||
is(value, label, "The " + side + " label textcontent is correct");
|
||||
} else {
|
||||
ok(hidden, "The " + side + " label is hidden");
|
||||
}
|
||||
}
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Globals defined in: devtools/client/inspector/test/head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the right arrows/labels are shown even when the css properties are
|
||||
// in several different css rules.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html";
|
||||
const ID = "geometry-editor-";
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
const PROPS = ["left", "right", "top", "bottom"];
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
let { finalize } = helper;
|
||||
|
||||
yield checkArrowsLabelsAndHandlers(
|
||||
"#node2", ["top", "left", "bottom", "right"],
|
||||
helper);
|
||||
|
||||
yield checkArrowsLabelsAndHandlers("#node3", ["top", "left"], helper);
|
||||
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* checkArrowsLabelsAndHandlers(selector, expectedProperties,
|
||||
{show, hide, isElementHidden}
|
||||
) {
|
||||
info("Getting node " + selector + " from the page");
|
||||
|
||||
yield show(selector);
|
||||
|
||||
for (let name of expectedProperties) {
|
||||
let hidden = (yield isElementHidden("arrow-" + name)) &&
|
||||
(yield isElementHidden("handler-" + name));
|
||||
ok(!hidden,
|
||||
"The " + name + " label/arrow & handler is visible for node " + selector);
|
||||
}
|
||||
|
||||
// Testing that the other arrows are hidden
|
||||
for (let name of PROPS) {
|
||||
if (expectedProperties.indexOf(name) !== -1) {
|
||||
continue;
|
||||
}
|
||||
let hidden = (yield isElementHidden("arrow-" + name)) &&
|
||||
(yield isElementHidden("handler-" + name));
|
||||
ok(hidden,
|
||||
"The " + name + " arrow & handler is hidden for node " + selector);
|
||||
}
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Globals defined in: devtools/client/inspector/test/head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the arrows and handlers are positioned correctly and have the right
|
||||
// size.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html";
|
||||
const ID = "geometry-editor-";
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
|
||||
const handlerMap = {
|
||||
"top": {"cx": "x2", "cy": "y2"},
|
||||
"bottom": {"cx": "x2", "cy": "y2"},
|
||||
"left": {"cx": "x2", "cy": "y2"},
|
||||
"right": {"cx": "x2", "cy": "y2"}
|
||||
};
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
let { hide, finalize } = helper;
|
||||
|
||||
yield checkArrowsAndHandlers(helper, ".absolute-all-4", {
|
||||
"top": {x1: 506, y1: 51, x2: 506, y2: 61},
|
||||
"bottom": {x1: 506, y1: 451, x2: 506, y2: 251},
|
||||
"left": {x1: 401, y1: 156, x2: 411, y2: 156},
|
||||
"right": {x1: 901, y1: 156, x2: 601, y2: 156}
|
||||
});
|
||||
|
||||
yield checkArrowsAndHandlers(helper, ".relative", {
|
||||
"top": {x1: 901, y1: 51, x2: 901, y2: 91},
|
||||
"left": {x1: 401, y1: 97, x2: 651, y2: 97}
|
||||
});
|
||||
|
||||
yield checkArrowsAndHandlers(helper, ".fixed", {
|
||||
"top": {x1: 25, y1: 0, x2: 25, y2: 400},
|
||||
"left": {x1: 0, y1: 425, x2: 0, y2: 425}
|
||||
});
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* checkArrowsAndHandlers(helper, selector, arrows) {
|
||||
info("Highlighting the test node " + selector);
|
||||
|
||||
yield helper.show(selector);
|
||||
|
||||
for (let side in arrows) {
|
||||
yield checkArrowAndHandler(helper, side, arrows[side]);
|
||||
}
|
||||
}
|
||||
|
||||
function* checkArrowAndHandler({getElementAttribute}, name, expectedCoords) {
|
||||
info("Checking " + name + "arrow and handler coordinates are correct");
|
||||
|
||||
let handlerX = yield getElementAttribute("handler-" + name, "cx");
|
||||
let handlerY = yield getElementAttribute("handler-" + name, "cy");
|
||||
|
||||
let expectedHandlerX = yield getElementAttribute("arrow-" + name,
|
||||
handlerMap[name].cx);
|
||||
let expectedHandlerY = yield getElementAttribute("arrow-" + name,
|
||||
handlerMap[name].cy);
|
||||
|
||||
is(handlerX, expectedHandlerX,
|
||||
"coordinate X for handler " + name + " is correct.");
|
||||
is(handlerY, expectedHandlerY,
|
||||
"coordinate Y for handler " + name + " is correct.");
|
||||
|
||||
for (let coordinate in expectedCoords) {
|
||||
let value = yield getElementAttribute("arrow-" + name, coordinate);
|
||||
|
||||
is(Math.floor(value), expectedCoords[coordinate],
|
||||
coordinate + " coordinate for arrow " + name + " is correct");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/* 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/. */
|
||||
|
||||
/* Globals defined in: devtools/client/inspector/test/head.js */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the arrows/handlers and offsetparent and currentnode elements of
|
||||
// the geometry highlighter only appear when needed.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_02.html";
|
||||
const ID = "geometry-editor-";
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
|
||||
const TEST_DATA = [{
|
||||
selector: "body",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: false,
|
||||
hasVisibleArrowsAndHandlers: false
|
||||
}, {
|
||||
selector: "h1",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: false,
|
||||
hasVisibleArrowsAndHandlers: false
|
||||
}, {
|
||||
selector: ".absolute",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}, {
|
||||
selector: "#absolute-container",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: false
|
||||
}, {
|
||||
selector: ".absolute-bottom-right",
|
||||
isOffsetParentVisible: true,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}, {
|
||||
selector: ".absolute-width-margin",
|
||||
isOffsetParentVisible: true,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}, {
|
||||
selector: ".absolute-all-4",
|
||||
isOffsetParentVisible: true,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}, {
|
||||
selector: ".relative",
|
||||
isOffsetParentVisible: true,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}, {
|
||||
selector: ".static",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: false,
|
||||
hasVisibleArrowsAndHandlers: false
|
||||
}, {
|
||||
selector: ".static-size",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: false
|
||||
}, {
|
||||
selector: ".fixed",
|
||||
isOffsetParentVisible: false,
|
||||
isCurrentNodeVisible: true,
|
||||
hasVisibleArrowsAndHandlers: true
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
let { hide, finalize } = helper;
|
||||
|
||||
for (let data of TEST_DATA) {
|
||||
yield testNode(helper, data);
|
||||
}
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* testNode(helper, data) {
|
||||
let { selector } = data;
|
||||
yield helper.show(data.selector);
|
||||
|
||||
is((yield isOffsetParentVisible(helper)), data.isOffsetParentVisible,
|
||||
"The offset-parent highlighter visibility is correct for node " + selector);
|
||||
is((yield isCurrentNodeVisible(helper)), data.isCurrentNodeVisible,
|
||||
"The current-node highlighter visibility is correct for node " + selector);
|
||||
is((yield hasVisibleArrowsAndHandlers(helper)),
|
||||
data.hasVisibleArrowsAndHandlers,
|
||||
"The arrows visibility is correct for node " + selector);
|
||||
}
|
||||
|
||||
function* isOffsetParentVisible({isElementHidden}) {
|
||||
return !(yield isElementHidden("offset-parent"));
|
||||
}
|
||||
|
||||
function* isCurrentNodeVisible({isElementHidden}) {
|
||||
return !(yield isElementHidden("current-node"));
|
||||
}
|
||||
|
||||
function* hasVisibleArrowsAndHandlers({isElementHidden}) {
|
||||
for (let side of ["top", "left", "bottom", "right"]) {
|
||||
let hidden = yield isElementHidden("arrow-" + side);
|
||||
if (!hidden) {
|
||||
return !(yield isElementHidden("handler-" + side));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,166 @@
|
|||
/* 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 geometry editor resizes properly an element on all sides,
|
||||
// with different unit measures, and that arrow/handlers are updated correctly.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter-geometry_01.html";
|
||||
const ID = "geometry-editor-";
|
||||
const HIGHLIGHTER_TYPE = "GeometryEditorHighlighter";
|
||||
|
||||
const SIDES = ["top", "right", "bottom", "left"];
|
||||
|
||||
// The object below contains all the tests for this unit test.
|
||||
// The property's name is the test's description, that points to an
|
||||
// object contains the steps (what side of the geometry editor to drag,
|
||||
// the amount of pixels) and the expectation.
|
||||
const TESTS = {
|
||||
"Drag top's handler along x and y, south-east direction": {
|
||||
"expects": "Only y axis is used to updated the top's element value",
|
||||
"drag": "top",
|
||||
"by": {x: 10, y: 10}
|
||||
},
|
||||
"Drag right's handler along x and y, south-east direction": {
|
||||
"expects": "Only x axis is used to updated the right's element value",
|
||||
"drag": "right",
|
||||
"by": {x: 10, y: 10}
|
||||
},
|
||||
"Drag bottom's handler along x and y, south-east direction": {
|
||||
"expects": "Only y axis is used to updated the bottom's element value",
|
||||
"drag": "bottom",
|
||||
"by": {x: 10, y: 10}
|
||||
},
|
||||
"Drag left's handler along x and y, south-east direction": {
|
||||
"expects": "Only y axis is used to updated the left's element value",
|
||||
"drag": "left",
|
||||
"by": {x: 10, y: 10}
|
||||
},
|
||||
"Drag top's handler along x and y, north-west direction": {
|
||||
"expects": "Only y axis is used to updated the top's element value",
|
||||
"drag": "top",
|
||||
"by": {x: -20, y: -20}
|
||||
},
|
||||
"Drag right's handler along x and y, north-west direction": {
|
||||
"expects": "Only x axis is used to updated the right's element value",
|
||||
"drag": "right",
|
||||
"by": {x: -20, y: -20}
|
||||
},
|
||||
"Drag bottom's handler along x and y, north-west direction": {
|
||||
"expects": "Only y axis is used to updated the bottom's element value",
|
||||
"drag": "bottom",
|
||||
"by": {x: -20, y: -20}
|
||||
},
|
||||
"Drag left's handler along x and y, north-west direction": {
|
||||
"expects": "Only y axis is used to updated the left's element value",
|
||||
"drag": "left",
|
||||
"by": {x: -20, y: -20}
|
||||
}
|
||||
};
|
||||
|
||||
add_task(function* () {
|
||||
let inspector = yield openInspectorForURL(TEST_URL);
|
||||
let helper = yield getHighlighterHelperFor(HIGHLIGHTER_TYPE)(inspector);
|
||||
|
||||
helper.prefix = ID;
|
||||
|
||||
let { show, hide, finalize } = helper;
|
||||
|
||||
info("Showing the highlighter");
|
||||
yield show("#node2");
|
||||
|
||||
for (let desc in TESTS) {
|
||||
yield executeTest(helper, desc, TESTS[desc]);
|
||||
}
|
||||
|
||||
info("Hiding the highlighter");
|
||||
yield hide();
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* executeTest(helper, desc, data) {
|
||||
info(desc);
|
||||
|
||||
ok((yield areElementAndHighlighterMovedCorrectly(
|
||||
helper, data.drag, data.by)), data.expects);
|
||||
}
|
||||
|
||||
function* areElementAndHighlighterMovedCorrectly(helper, side, by) {
|
||||
let { mouse, reflow, highlightedNode } = helper;
|
||||
|
||||
let {x, y} = yield getHandlerCoords(helper, side);
|
||||
|
||||
let dx = x + by.x;
|
||||
let dy = y + by.y;
|
||||
|
||||
let beforeDragStyle = yield highlightedNode.getComputedStyle();
|
||||
|
||||
// simulate drag & drop
|
||||
yield mouse.down(x, y);
|
||||
yield mouse.move(dx, dy);
|
||||
yield mouse.up();
|
||||
|
||||
yield reflow();
|
||||
|
||||
info(`Checking ${side} handler is moved correctly`);
|
||||
yield isHandlerPositionUpdated(helper, side, x, y, by);
|
||||
|
||||
let delta = (side === "left" || side === "right") ? by.x : by.y;
|
||||
delta = delta * ((side === "right" || side === "bottom") ? -1 : 1);
|
||||
|
||||
info("Checking element's sides are correct after drag & drop");
|
||||
return yield areElementSideValuesCorrect(highlightedNode, beforeDragStyle,
|
||||
side, delta);
|
||||
}
|
||||
|
||||
function* isHandlerPositionUpdated(helper, name, x, y, by) {
|
||||
let {x: afterDragX, y: afterDragY} = yield getHandlerCoords(helper, name);
|
||||
|
||||
if (name === "left" || name === "right") {
|
||||
is(afterDragX, x + by.x,
|
||||
`${name} handler's x axis updated.`);
|
||||
is(afterDragY, y,
|
||||
`${name} handler's y axis unchanged.`);
|
||||
} else {
|
||||
is(afterDragX, x,
|
||||
`${name} handler's x axis unchanged.`);
|
||||
is(afterDragY, y + by.y,
|
||||
`${name} handler's y axis updated.`);
|
||||
}
|
||||
}
|
||||
|
||||
function* areElementSideValuesCorrect(node, beforeDragStyle, name, delta) {
|
||||
let afterDragStyle = yield node.getComputedStyle();
|
||||
let isSideCorrect = true;
|
||||
|
||||
for (let side of SIDES) {
|
||||
let afterValue = Math.round(parseFloat(afterDragStyle[side].value));
|
||||
let beforeValue = Math.round(parseFloat(beforeDragStyle[side].value));
|
||||
|
||||
if (side === name) {
|
||||
// `isSideCorrect` is used only as test's return value, not to perform
|
||||
// the actual test, because with `is` instead of `ok` we gather more
|
||||
// information in case of failure
|
||||
isSideCorrect = isSideCorrect && (afterValue === beforeValue + delta);
|
||||
|
||||
is(afterValue, beforeValue + delta,
|
||||
`${side} is updated.`);
|
||||
} else {
|
||||
isSideCorrect = isSideCorrect && (afterValue === beforeValue);
|
||||
|
||||
is(afterValue, beforeValue,
|
||||
`${side} is unchaged.`);
|
||||
}
|
||||
}
|
||||
|
||||
return isSideCorrect;
|
||||
}
|
||||
|
||||
function* getHandlerCoords({getElementAttribute}, side) {
|
||||
return {
|
||||
x: Math.round(yield getElementAttribute("handler-" + side, "cx")),
|
||||
y: Math.round(yield getElementAttribute("handler-" + side, "cy"))
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +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";
|
||||
|
||||
// Test that when first hovering over a node and immediately after selecting it
|
||||
// by clicking on it leaves the highlighter visible for as long as the mouse is
|
||||
// over the node
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<p>It's going to be legen....</p>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("hovering over the <p> line in the markup-view");
|
||||
yield hoverContainer("p", inspector);
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "the highlighter is still visible");
|
||||
|
||||
info("selecting the <p> line by clicking in the markup-view");
|
||||
yield clickContainer("p", inspector);
|
||||
|
||||
yield testActor.setProperty("p", "textContent", "wait for it ....");
|
||||
info("wait and see if the highlighter stays visible even after the node " +
|
||||
"was selected");
|
||||
yield waitForTheBrieflyShowBoxModelTimeout();
|
||||
|
||||
yield testActor.setProperty("p", "textContent", "dary!!!!");
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "the highlighter is still visible");
|
||||
});
|
||||
|
||||
function waitForTheBrieflyShowBoxModelTimeout() {
|
||||
let deferred = defer();
|
||||
// Note that the current timeout is 1 sec and is neither configurable nor
|
||||
// exported anywhere we can access, so hard-coding the timeout
|
||||
setTimeout(deferred.resolve, 1500);
|
||||
return deferred.promise;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* 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 when after an element is selected and highlighted on hover, if the
|
||||
// mouse leaves the markup-view and comes back again on the same element, that
|
||||
// the highlighter is shown again on the node
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,<p>Select me!</p>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("hover over the <p> line in the markup-view so that it's the " +
|
||||
"currently hovered node");
|
||||
yield hoverContainer("p", inspector);
|
||||
|
||||
info("select the <p> markup-container line by clicking");
|
||||
yield clickContainer("p", inspector);
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "the highlighter is shown");
|
||||
|
||||
info("listen to the highlighter's hidden event");
|
||||
let onHidden = testActor.waitForHighlighterEvent("hidden",
|
||||
inspector.highlighter);
|
||||
info("mouse-leave the markup-view");
|
||||
yield mouseLeaveMarkupView(inspector);
|
||||
yield onHidden;
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(!isVisible, "the highlighter is hidden after mouseleave");
|
||||
|
||||
info("hover over the <p> line again, which is still selected");
|
||||
yield hoverContainer("p", inspector);
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "the highlighter is visible again");
|
||||
});
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
/* 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 once a node has been hovered over and marked as such, if it is
|
||||
// navigated away using the keyboard, the highlighter moves to the new node, and
|
||||
// if it is then navigated back to, it is briefly highlighted again
|
||||
|
||||
const TEST_PAGE = "data:text/html;charset=utf-8," +
|
||||
"<p id=\"one\">one</p><p id=\"two\">two</p>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL(TEST_PAGE);
|
||||
|
||||
info("Making sure the markup-view frame is focused");
|
||||
inspector.markup._frame.focus();
|
||||
|
||||
// Mock the highlighter to easily track which node gets highlighted.
|
||||
// We don't need to test here that the highlighter is actually visible, we
|
||||
// just care about whether the markup-view asks it to be shown
|
||||
let highlightedNode = null;
|
||||
inspector.toolbox._highlighter.showBoxModel = function (nodeFront) {
|
||||
highlightedNode = nodeFront;
|
||||
return promise.resolve();
|
||||
};
|
||||
inspector.toolbox._highlighter.hideBoxModel = function () {
|
||||
return promise.resolve();
|
||||
};
|
||||
|
||||
function* isHighlighting(selector, desc) {
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
is(highlightedNode, nodeFront, desc);
|
||||
}
|
||||
|
||||
info("Hover over <p#one> line in the markup-view");
|
||||
yield hoverContainer("#one", inspector);
|
||||
yield isHighlighting("#one", "<p#one> is highlighted");
|
||||
|
||||
info("Navigate to <p#two> with the keyboard");
|
||||
let onUpdated = inspector.once("inspector-updated");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, inspector.panelWin);
|
||||
yield onUpdated;
|
||||
onUpdated = inspector.once("inspector-updated");
|
||||
EventUtils.synthesizeKey("VK_DOWN", {}, inspector.panelWin);
|
||||
yield onUpdated;
|
||||
yield isHighlighting("#two", "<p#two> is highlighted");
|
||||
|
||||
info("Navigate back to <p#one> with the keyboard");
|
||||
onUpdated = inspector.once("inspector-updated");
|
||||
EventUtils.synthesizeKey("VK_UP", {}, inspector.panelWin);
|
||||
yield onUpdated;
|
||||
yield isHighlighting("#one", "<p#one> is highlighted again");
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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";
|
||||
|
||||
// Testing that moving the mouse over the document with the element picker
|
||||
// started highlights nodes
|
||||
|
||||
const NESTED_FRAME_SRC = "data:text/html;charset=utf-8," +
|
||||
"nested iframe<div>nested div</div>";
|
||||
|
||||
const OUTER_FRAME_SRC = "data:text/html;charset=utf-8," +
|
||||
"little frame<div>little div</div>" +
|
||||
"<iframe src='" + NESTED_FRAME_SRC + "' />";
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"iframe tests for inspector" +
|
||||
"<iframe src=\"" + OUTER_FRAME_SRC + "\" />";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
let outerFrameDiv = ["iframe", "div"];
|
||||
let innerFrameDiv = ["iframe", "iframe", "div"];
|
||||
|
||||
info("Waiting for element picker to activate.");
|
||||
yield startPicker(inspector.toolbox);
|
||||
|
||||
info("Moving mouse over outerFrameDiv");
|
||||
yield moveMouseOver(outerFrameDiv);
|
||||
ok((yield testActor.assertHighlightedNode(outerFrameDiv)),
|
||||
"outerFrameDiv is highlighted.");
|
||||
|
||||
info("Moving mouse over innerFrameDiv");
|
||||
yield moveMouseOver(innerFrameDiv);
|
||||
ok((yield testActor.assertHighlightedNode(innerFrameDiv)),
|
||||
"innerFrameDiv is highlighted.");
|
||||
|
||||
info("Selecting root node");
|
||||
yield selectNode(inspector.walker.rootNode, inspector);
|
||||
|
||||
info("Selecting an element from the nested iframe directly");
|
||||
let innerFrameFront = yield getNodeFrontInFrame("iframe", "iframe",
|
||||
inspector);
|
||||
let innerFrameDivFront = yield getNodeFrontInFrame("div", innerFrameFront,
|
||||
inspector);
|
||||
yield selectNode(innerFrameDivFront, inspector);
|
||||
|
||||
is(inspector.breadcrumbs.nodeHierarchy.length, 9,
|
||||
"Breadcrumbs have 9 items.");
|
||||
|
||||
info("Waiting for element picker to deactivate.");
|
||||
yield inspector.toolbox.highlighterUtils.stopPicker();
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
testActor.synthesizeMouse({
|
||||
selector: selector,
|
||||
options: {type: "mousemove"},
|
||||
center: true
|
||||
}).then(() => inspector.toolbox.once("picker-node-hovered"));
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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 is correctly positioned when switching context
|
||||
// to an iframe that has an offset from the parent viewport (eg. 100px margin)
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"<div id=\"outer\"></div>" +
|
||||
"<iframe style='margin:100px' src='data:text/html," +
|
||||
"<div id=\"inner\">Look I am here!</div>'>";
|
||||
|
||||
add_task(function* () {
|
||||
info("Enable command-button-frames preference setting");
|
||||
Services.prefs.setBoolPref("devtools.command-button-frames.enabled", true);
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Switch to the iframe context.");
|
||||
yield switchToFrameContext(1, toolbox, inspector);
|
||||
|
||||
info("Check navigation was successful.");
|
||||
let hasOuterNode = yield testActor.hasNode("#outer");
|
||||
ok(!hasOuterNode, "Check testActor has no access to outer element");
|
||||
let hasTestNode = yield testActor.hasNode("#inner");
|
||||
ok(hasTestNode, "Check testActor has access to inner element");
|
||||
|
||||
info("Check highlighting is correct after switching iframe context");
|
||||
yield selectAndHighlightNode("#inner", inspector);
|
||||
let isHighlightCorrect = yield testActor.assertHighlightedNode("#inner");
|
||||
ok(isHighlightCorrect, "The selected node is properly highlighted.");
|
||||
|
||||
info("Cleanup command-button-frames preferences.");
|
||||
Services.prefs.clearUserPref("devtools.command-button-frames.enabled");
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper designed to switch context to another frame at the provided index.
|
||||
* Returns a promise that will resolve when the navigation is complete.
|
||||
* @return {Promise}
|
||||
*/
|
||||
function* switchToFrameContext(frameIndex, toolbox, inspector) {
|
||||
// Open frame menu and wait till it's available on the screen.
|
||||
let btn = toolbox.doc.getElementById("command-button-frames");
|
||||
let menu = toolbox.showFramesMenu({target: btn});
|
||||
yield once(menu, "open");
|
||||
|
||||
info("Select the iframe in the frame list.");
|
||||
let newRoot = inspector.once("new-root");
|
||||
|
||||
menu.items[frameIndex].click();
|
||||
|
||||
yield newRoot;
|
||||
yield inspector.once("inspector-updated");
|
||||
|
||||
info("Navigation to the iframe is done.");
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* 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";
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// Test that highlighting various inline boxes displays the right number of
|
||||
// polygons in the page.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_inline.html";
|
||||
const TEST_DATA = [
|
||||
"body",
|
||||
"h1",
|
||||
"h2",
|
||||
"h2 em",
|
||||
"p",
|
||||
"p span",
|
||||
// The following test case used to fail. See bug 1139925.
|
||||
"[dir=rtl] > span"
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
info("Loading the test document and opening the inspector");
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
for (let selector of TEST_DATA) {
|
||||
info("Selecting and highlighting node " + selector);
|
||||
yield selectAndHighlightNode(selector, inspector);
|
||||
|
||||
info("Get all quads for this node");
|
||||
let data = yield testActor.getAllAdjustedQuads(selector);
|
||||
|
||||
info("Iterate over the box-model regions and verify that the highlighter " +
|
||||
"is correct");
|
||||
for (let region of ["margin", "border", "padding", "content"]) {
|
||||
let {points} = yield testActor.getHighlighterRegionPath(region);
|
||||
is(points.length, data[region].length, "The highlighter's " + region +
|
||||
" path defines the correct number of boxes");
|
||||
}
|
||||
|
||||
info("Verify that the guides define a rectangle that contains all " +
|
||||
"content boxes");
|
||||
|
||||
let expectedContentRect = {
|
||||
p1: {x: Infinity, y: Infinity},
|
||||
p2: {x: -Infinity, y: Infinity},
|
||||
p3: {x: -Infinity, y: -Infinity},
|
||||
p4: {x: Infinity, y: -Infinity}
|
||||
};
|
||||
for (let {p1, p2, p3, p4} of data.content) {
|
||||
expectedContentRect.p1.x = Math.min(expectedContentRect.p1.x, p1.x);
|
||||
expectedContentRect.p1.y = Math.min(expectedContentRect.p1.y, p1.y);
|
||||
expectedContentRect.p2.x = Math.max(expectedContentRect.p2.x, p2.x);
|
||||
expectedContentRect.p2.y = Math.min(expectedContentRect.p2.y, p2.y);
|
||||
expectedContentRect.p3.x = Math.max(expectedContentRect.p3.x, p3.x);
|
||||
expectedContentRect.p3.y = Math.max(expectedContentRect.p3.y, p3.y);
|
||||
expectedContentRect.p4.x = Math.min(expectedContentRect.p4.x, p4.x);
|
||||
expectedContentRect.p4.y = Math.max(expectedContentRect.p4.y, p4.y);
|
||||
}
|
||||
|
||||
let contentRect = yield testActor.getGuidesRectangle();
|
||||
|
||||
for (let point of ["p1", "p2", "p3", "p4"]) {
|
||||
is((contentRect[point].x),
|
||||
(expectedContentRect[point].x),
|
||||
"x coordinate of point " + point +
|
||||
" of the content rectangle defined by the outer guides is correct");
|
||||
is((contentRect[point].y),
|
||||
(expectedContentRect[point].y),
|
||||
"y coordinate of point " + point +
|
||||
" of the content rectangle defined by the outer guides is correct");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* 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 keybindings for Picker work alright
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_dom.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Selecting the simple-div1 DIV");
|
||||
yield moveMouseOver("#simple-div1");
|
||||
|
||||
ok((yield testActor.assertHighlightedNode("#simple-div1")),
|
||||
"The highlighter shows #simple-div1. OK.");
|
||||
|
||||
// First Child selection
|
||||
info("Testing first-child selection.");
|
||||
|
||||
yield doKeyHover({key: "VK_RIGHT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#useless-para")),
|
||||
"The highlighter shows #useless-para. OK.");
|
||||
|
||||
info("Selecting the useful-para paragraph DIV");
|
||||
yield moveMouseOver("#useful-para");
|
||||
ok((yield testActor.assertHighlightedNode("#useful-para")),
|
||||
"The highlighter shows #useful-para. OK.");
|
||||
|
||||
yield doKeyHover({key: "VK_RIGHT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#bold")),
|
||||
"The highlighter shows #bold. OK.");
|
||||
|
||||
info("Going back up to the simple-div1 DIV");
|
||||
yield doKeyHover({key: "VK_LEFT", options: {}});
|
||||
yield doKeyHover({key: "VK_LEFT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#simple-div1")),
|
||||
"The highlighter shows #simple-div1. OK.");
|
||||
|
||||
info("First child selection test Passed.");
|
||||
|
||||
info("Stopping the picker");
|
||||
yield toolbox.highlighterUtils.stopPicker();
|
||||
|
||||
function doKeyHover(args) {
|
||||
info("Key pressed. Waiting for element to be highlighted/hovered");
|
||||
testActor.synthesizeKey(args);
|
||||
return inspector.toolbox.once("picker-node-hovered");
|
||||
}
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: selector
|
||||
});
|
||||
return inspector.toolbox.once("picker-node-hovered");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/* 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 keybindings for Picker work alright
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_dom.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield startPicker(toolbox);
|
||||
|
||||
// Previously chosen child memory
|
||||
info("Testing whether previously chosen child is remembered");
|
||||
|
||||
info("Selecting the ahoy paragraph DIV");
|
||||
yield moveMouseOver("#ahoy");
|
||||
|
||||
yield doKeyHover({key: "VK_LEFT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#simple-div2")),
|
||||
"The highlighter shows #simple-div2. OK.");
|
||||
|
||||
yield doKeyHover({key: "VK_RIGHT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#ahoy")),
|
||||
"The highlighter shows #ahoy. OK.");
|
||||
|
||||
info("Going back up to the complex-div DIV");
|
||||
yield doKeyHover({key: "VK_LEFT", options: {}});
|
||||
yield doKeyHover({key: "VK_LEFT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#complex-div")),
|
||||
"The highlighter shows #complex-div. OK.");
|
||||
|
||||
yield doKeyHover({key: "VK_RIGHT", options: {}});
|
||||
ok((yield testActor.assertHighlightedNode("#simple-div2")),
|
||||
"The highlighter shows #simple-div2. OK.");
|
||||
|
||||
info("Previously chosen child is remembered. Passed.");
|
||||
|
||||
info("Stopping the picker");
|
||||
yield toolbox.highlighterUtils.stopPicker();
|
||||
|
||||
function doKeyHover(args) {
|
||||
info("Key pressed. Waiting for element to be highlighted/hovered");
|
||||
let onHighlighterReady = toolbox.once("highlighter-ready");
|
||||
let onPickerNodeHovered = inspector.toolbox.once("picker-node-hovered");
|
||||
testActor.synthesizeKey(args);
|
||||
return promise.all([onHighlighterReady, onPickerNodeHovered]);
|
||||
}
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
let onHighlighterReady = toolbox.once("highlighter-ready");
|
||||
let onPickerNodeHovered = inspector.toolbox.once("picker-node-hovered");
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: selector
|
||||
});
|
||||
return promise.all([onHighlighterReady, onPickerNodeHovered]);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* 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 keybindings for Picker work alright
|
||||
|
||||
const IS_OSX = Services.appinfo.OS === "Darwin";
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_dom.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield startPicker(toolbox);
|
||||
yield moveMouseOver("#another");
|
||||
|
||||
info("Testing enter/return key as pick-node command");
|
||||
yield doKeyPick({key: "VK_RETURN", options: {}});
|
||||
is(inspector.selection.nodeFront.id, "another",
|
||||
"The #another node was selected. Passed.");
|
||||
|
||||
info("Testing escape key as cancel-picker command");
|
||||
yield startPicker(toolbox);
|
||||
yield moveMouseOver("#ahoy");
|
||||
yield doKeyStop({key: "VK_ESCAPE", options: {}});
|
||||
is(inspector.selection.nodeFront.id, "another",
|
||||
"The #another DIV is still selected. Passed.");
|
||||
|
||||
info("Testing Ctrl+Shift+C shortcut as cancel-picker command");
|
||||
yield startPicker(toolbox);
|
||||
yield moveMouseOver("#ahoy");
|
||||
let shortcutOpts = {key: "VK_C", options: {}};
|
||||
if (IS_OSX) {
|
||||
shortcutOpts.options.metaKey = true;
|
||||
shortcutOpts.options.altKey = true;
|
||||
} else {
|
||||
shortcutOpts.options.ctrlKey = true;
|
||||
shortcutOpts.options.shiftKey = true;
|
||||
}
|
||||
yield doKeyStop(shortcutOpts);
|
||||
is(inspector.selection.nodeFront.id, "another",
|
||||
"The #another DIV is still selected. Passed.");
|
||||
|
||||
function doKeyPick(args) {
|
||||
info("Key pressed. Waiting for element to be picked");
|
||||
testActor.synthesizeKey(args);
|
||||
return promise.all([
|
||||
inspector.selection.once("new-node-front"),
|
||||
inspector.once("inspector-updated")
|
||||
]);
|
||||
}
|
||||
|
||||
function doKeyStop(args) {
|
||||
info("Key pressed. Waiting for picker to be canceled");
|
||||
testActor.synthesizeKey(args);
|
||||
return inspector.toolbox.once("picker-stopped");
|
||||
}
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
let onHighlighterReady = toolbox.once("highlighter-ready");
|
||||
let onPickerNodeHovered = inspector.toolbox.once("picker-node-hovered");
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: selector
|
||||
});
|
||||
return promise.all([onHighlighterReady, onPickerNodeHovered]);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* 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 pressing ESC twice while in picker mode first stops the picker and
|
||||
// then opens the split-console (see bug 988278).
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf8,<div></div>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Start using the picker by hovering over nodes");
|
||||
let onHover = toolbox.once("picker-node-hovered");
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: "div"
|
||||
});
|
||||
yield onHover;
|
||||
|
||||
info("Press escape and wait for the picker to stop");
|
||||
let onPickerStopped = toolbox.once("picker-stopped");
|
||||
testActor.synthesizeKey({
|
||||
key: "VK_ESCAPE",
|
||||
options: {}
|
||||
});
|
||||
yield onPickerStopped;
|
||||
|
||||
info("Press escape again and wait for the split console to open");
|
||||
let onSplitConsole = toolbox.once("split-console");
|
||||
let onConsoleReady = toolbox.once("webconsole-ready");
|
||||
// The escape key is synthesized in the main process, which is where the focus
|
||||
// should be after the picker was stopped.
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {}, inspector.panelWin);
|
||||
yield onSplitConsole;
|
||||
yield onConsoleReady;
|
||||
ok(toolbox.splitConsole, "The split console is shown.");
|
||||
|
||||
// Hide the split console.
|
||||
yield toolbox.toggleSplitConsole();
|
||||
});
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/* 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 TEST_URL = `data:text/html;charset=utf-8,
|
||||
<div style='
|
||||
position:absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 40000px;
|
||||
height: 8000px'>
|
||||
</div>`;
|
||||
|
||||
const PREFIX = "measuring-tool-highlighter-";
|
||||
const HIGHLIGHTER_TYPE = "MeasuringToolHighlighter";
|
||||
|
||||
const X = 32;
|
||||
const Y = 20;
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
let { finalize } = helper;
|
||||
|
||||
helper.prefix = PREFIX;
|
||||
|
||||
yield isHiddenByDefault(helper);
|
||||
yield areLabelsHiddenByDefaultWhenShows(helper);
|
||||
yield areLabelsProperlyDisplayedWhenMouseMoved(helper);
|
||||
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* isHiddenByDefault({isElementHidden}) {
|
||||
info("Checking the highlighter is hidden by default");
|
||||
|
||||
let hidden = yield isElementHidden("elements");
|
||||
ok(hidden, "highlighter's root is hidden by default");
|
||||
|
||||
hidden = yield isElementHidden("label-size");
|
||||
ok(hidden, "highlighter's label size is hidden by default");
|
||||
|
||||
hidden = yield isElementHidden("label-position");
|
||||
ok(hidden, "highlighter's label position is hidden by default");
|
||||
}
|
||||
|
||||
function* areLabelsHiddenByDefaultWhenShows({isElementHidden, show}) {
|
||||
info("Checking the highlighter is displayed when asked");
|
||||
|
||||
yield show();
|
||||
|
||||
let hidden = yield isElementHidden("elements");
|
||||
is(hidden, false, "highlighter is visible after show");
|
||||
|
||||
hidden = yield isElementHidden("label-size");
|
||||
ok(hidden, "label's size still hidden");
|
||||
|
||||
hidden = yield isElementHidden("label-position");
|
||||
ok(hidden, "label's position still hidden");
|
||||
}
|
||||
|
||||
function* areLabelsProperlyDisplayedWhenMouseMoved({isElementHidden,
|
||||
synthesizeMouse, getElementTextContent}) {
|
||||
info("Checking labels are properly displayed when mouse moved");
|
||||
|
||||
yield synthesizeMouse({
|
||||
selector: ":root",
|
||||
options: {type: "mousemove"},
|
||||
x: X,
|
||||
y: Y
|
||||
});
|
||||
|
||||
let hidden = yield isElementHidden("label-position");
|
||||
is(hidden, false, "label's position is displayed after the mouse is moved");
|
||||
|
||||
hidden = yield isElementHidden("label-size");
|
||||
ok(hidden, "label's size still hidden");
|
||||
|
||||
let text = yield getElementTextContent("label-position");
|
||||
|
||||
let [x, y] = text.replace(/ /g, "").split(/\n/);
|
||||
|
||||
is(+x, X, "label's position shows the proper X coord");
|
||||
is(+y, Y, "label's position shows the proper Y coord");
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
/* 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 TEST_URL = `data:text/html;charset=utf-8,
|
||||
<div style='
|
||||
position:absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 40000px;
|
||||
height: 8000px'>
|
||||
</div>`;
|
||||
|
||||
const PREFIX = "measuring-tool-highlighter-";
|
||||
const HIGHLIGHTER_TYPE = "MeasuringToolHighlighter";
|
||||
|
||||
const SIDES = ["top", "right", "bottom", "left"];
|
||||
|
||||
const X = 32;
|
||||
const Y = 20;
|
||||
const WIDTH = 160;
|
||||
const HEIGHT = 100;
|
||||
const HYPOTENUSE = Math.hypot(WIDTH, HEIGHT).toFixed(2);
|
||||
|
||||
add_task(function* () {
|
||||
let helper = yield openInspectorForURL(TEST_URL)
|
||||
.then(getHighlighterHelperFor(HIGHLIGHTER_TYPE));
|
||||
|
||||
let { show, finalize } = helper;
|
||||
|
||||
helper.prefix = PREFIX;
|
||||
|
||||
yield show();
|
||||
|
||||
yield hasNoLabelsWhenStarts(helper);
|
||||
yield hasSizeLabelWhenMoved(helper);
|
||||
yield hasCorrectSizeLabelValue(helper);
|
||||
yield hasSizeLabelAndGuidesWhenStops(helper);
|
||||
yield hasCorrectSizeLabelValue(helper);
|
||||
|
||||
yield finalize();
|
||||
});
|
||||
|
||||
function* hasNoLabelsWhenStarts({isElementHidden, synthesizeMouse}) {
|
||||
info("Checking highlighter has no labels when we start to select");
|
||||
|
||||
yield synthesizeMouse({
|
||||
selector: ":root",
|
||||
options: {type: "mousedown"},
|
||||
x: X,
|
||||
y: Y
|
||||
});
|
||||
|
||||
let hidden = yield isElementHidden("label-size");
|
||||
ok(hidden, "label's size still hidden");
|
||||
|
||||
hidden = yield isElementHidden("label-position");
|
||||
ok(hidden, "label's position still hidden");
|
||||
|
||||
info("Checking highlighter has no guides when we start to select");
|
||||
|
||||
let guidesHidden = true;
|
||||
for (let side of SIDES) {
|
||||
guidesHidden = guidesHidden && (yield isElementHidden("guide-" + side));
|
||||
}
|
||||
|
||||
ok(guidesHidden, "guides are hidden during dragging");
|
||||
}
|
||||
|
||||
function* hasSizeLabelWhenMoved({isElementHidden, synthesizeMouse}) {
|
||||
info("Checking highlighter has size label when we select the area");
|
||||
|
||||
yield synthesizeMouse({
|
||||
selector: ":root",
|
||||
options: {type: "mousemove"},
|
||||
x: X + WIDTH,
|
||||
y: Y + HEIGHT
|
||||
});
|
||||
|
||||
let hidden = yield isElementHidden("label-size");
|
||||
is(hidden, false, "label's size is visible during selection");
|
||||
|
||||
hidden = yield isElementHidden("label-position");
|
||||
ok(hidden, "label's position still hidden");
|
||||
|
||||
info("Checking highlighter has no guides when we select the area");
|
||||
|
||||
let guidesHidden = true;
|
||||
for (let side of SIDES) {
|
||||
guidesHidden = guidesHidden && (yield isElementHidden("guide-" + side));
|
||||
}
|
||||
|
||||
ok(guidesHidden, "guides are hidden during selection");
|
||||
}
|
||||
|
||||
function* hasSizeLabelAndGuidesWhenStops({isElementHidden, synthesizeMouse}) {
|
||||
info("Checking highlighter has size label and guides when we stop");
|
||||
|
||||
yield synthesizeMouse({
|
||||
selector: ":root",
|
||||
options: {type: "mouseup"},
|
||||
x: X + WIDTH,
|
||||
y: Y + HEIGHT
|
||||
});
|
||||
|
||||
let hidden = yield isElementHidden("label-size");
|
||||
is(hidden, false, "label's size is visible when the selection is done");
|
||||
|
||||
hidden = yield isElementHidden("label-position");
|
||||
ok(hidden, "label's position still hidden");
|
||||
|
||||
let guidesVisible = true;
|
||||
for (let side of SIDES) {
|
||||
guidesVisible = guidesVisible && !(yield isElementHidden("guide-" + side));
|
||||
}
|
||||
|
||||
ok(guidesVisible, "guides are visible when the selection is done");
|
||||
}
|
||||
|
||||
function* hasCorrectSizeLabelValue({getElementTextContent}) {
|
||||
let text = yield getElementTextContent("label-size");
|
||||
|
||||
let [width, height, hypot] = text.match(/\d.*px/g);
|
||||
|
||||
is(parseFloat(width), WIDTH, "width on label's size is correct");
|
||||
is(parseFloat(height), HEIGHT, "height on label's size is correct");
|
||||
is(parseFloat(hypot), HYPOTENUSE, "hypotenuse on label's size is correct");
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
/* 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";
|
||||
|
||||
// Check that the box-model highlighter supports configuration options
|
||||
|
||||
const TEST_URL = `
|
||||
<body style="padding:2em;">
|
||||
<div style="width:100px;height:100px;padding:2em;
|
||||
border:.5em solid black;margin:1em;">test</div>
|
||||
</body>
|
||||
`;
|
||||
|
||||
// Test data format:
|
||||
// - desc: a string that will be output to the console.
|
||||
// - options: json object to be passed as options to the highlighter.
|
||||
// - checkHighlighter: a generator (async) function that should check the
|
||||
// highlighter is correct.
|
||||
const TEST_DATA = [
|
||||
{
|
||||
desc: "Guides and infobar should be shown by default",
|
||||
options: {},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-infobar-container", "hidden");
|
||||
ok(!hidden, "Node infobar is visible");
|
||||
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-elements", "hidden");
|
||||
ok(!hidden, "SVG container is visible");
|
||||
|
||||
for (let side of ["top", "right", "bottom", "left"]) {
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-" + side, "hidden");
|
||||
ok(!hidden, side + " guide is visible");
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "All regions should be shown by default",
|
||||
options: {},
|
||||
checkHighlighter: function* (testActor) {
|
||||
for (let region of ["margin", "border", "padding", "content"]) {
|
||||
let {d} = yield testActor.getHighlighterRegionPath(region);
|
||||
ok(d, "Region " + region + " has set coordinates");
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Guides can be hidden",
|
||||
options: {hideGuides: true},
|
||||
checkHighlighter: function* (testActor) {
|
||||
for (let side of ["top", "right", "bottom", "left"]) {
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-" + side, "hidden");
|
||||
is(hidden, "true", side + " guide has been hidden");
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Infobar can be hidden",
|
||||
options: {hideInfoBar: true},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-infobar-container", "hidden");
|
||||
is(hidden, "true", "infobar has been hidden");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "One region only can be shown (1)",
|
||||
options: {showOnly: "content"},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let {d} = yield testActor.getHighlighterRegionPath("margin");
|
||||
ok(!d, "margin region is hidden");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("border"));
|
||||
ok(!d, "border region is hidden");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("padding"));
|
||||
ok(!d, "padding region is hidden");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("content"));
|
||||
ok(d, "content region is shown");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "One region only can be shown (2)",
|
||||
options: {showOnly: "margin"},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let {d} = yield testActor.getHighlighterRegionPath("margin");
|
||||
ok(d, "margin region is shown");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("border"));
|
||||
ok(!d, "border region is hidden");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("padding"));
|
||||
ok(!d, "padding region is hidden");
|
||||
|
||||
({d} = yield testActor.getHighlighterRegionPath("content"));
|
||||
ok(!d, "content region is hidden");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Guides can be drawn around a given region (1)",
|
||||
options: {region: "padding"},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let topY1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-top", "y1");
|
||||
let rightX1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-right", "x1");
|
||||
let bottomY1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-bottom", "y1");
|
||||
let leftX1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-left", "x1");
|
||||
|
||||
let {points} = yield testActor.getHighlighterRegionPath("padding");
|
||||
points = points[0];
|
||||
|
||||
is(Math.ceil(topY1), points[0][1], "Top guide's y1 is correct");
|
||||
is(Math.floor(rightX1), points[1][0], "Right guide's x1 is correct");
|
||||
is(Math.floor(bottomY1), points[2][1], "Bottom guide's y1 is correct");
|
||||
is(Math.ceil(leftX1), points[3][0], "Left guide's x1 is correct");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "Guides can be drawn around a given region (2)",
|
||||
options: {region: "margin"},
|
||||
checkHighlighter: function* (testActor) {
|
||||
let topY1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-top", "y1");
|
||||
let rightX1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-right", "x1");
|
||||
let bottomY1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-bottom", "y1");
|
||||
let leftX1 = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-guide-left", "x1");
|
||||
|
||||
let {points} = yield testActor.getHighlighterRegionPath("margin");
|
||||
points = points[0];
|
||||
|
||||
is(Math.ceil(topY1), points[0][1], "Top guide's y1 is correct");
|
||||
is(Math.floor(rightX1), points[1][0], "Right guide's x1 is correct");
|
||||
is(Math.floor(bottomY1), points[2][1], "Bottom guide's y1 is correct");
|
||||
is(Math.ceil(leftX1), points[3][0], "Left guide's x1 is correct");
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "When showOnly is used, other regions can be faded",
|
||||
options: {showOnly: "margin", onlyRegionArea: true},
|
||||
checkHighlighter: function* (testActor) {
|
||||
for (let region of ["margin", "border", "padding", "content"]) {
|
||||
let {d} = yield testActor.getHighlighterRegionPath(region);
|
||||
ok(d, "Region " + region + " is shown (it has a d attribute)");
|
||||
|
||||
let faded = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-" + region, "faded");
|
||||
if (region === "margin") {
|
||||
ok(!faded, "The margin region is not faded");
|
||||
} else {
|
||||
is(faded, "true", "Region " + region + " is faded");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
desc: "When showOnly is used, other regions can be faded (2)",
|
||||
options: {showOnly: "padding", onlyRegionArea: true},
|
||||
checkHighlighter: function* (testActor) {
|
||||
for (let region of ["margin", "border", "padding", "content"]) {
|
||||
let {d} = yield testActor.getHighlighterRegionPath(region);
|
||||
ok(d, "Region " + region + " is shown (it has a d attribute)");
|
||||
|
||||
let faded = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-" + region, "faded");
|
||||
if (region === "padding") {
|
||||
ok(!faded, "The padding region is not faded");
|
||||
} else {
|
||||
is(faded, "true", "Region " + region + " is faded");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8," + encodeURI(TEST_URL));
|
||||
|
||||
let divFront = yield getNodeFront("div", inspector);
|
||||
|
||||
for (let {desc, options, checkHighlighter} of TEST_DATA) {
|
||||
info("Running test: " + desc);
|
||||
|
||||
info("Show the box-model highlighter with options " + options);
|
||||
yield inspector.highlighter.showBoxModel(divFront, options);
|
||||
|
||||
yield checkHighlighter(testActor);
|
||||
|
||||
info("Hide the box-model highlighter");
|
||||
yield inspector.highlighter.hideBoxModel();
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* 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 is correctly displayed and picker mode is not stopped after
|
||||
// a shift-click (preview)
|
||||
|
||||
const TEST_URI = `data:text/html;charset=utf-8,
|
||||
<p id="one">one</p><p id="two">two</p><p id="three">three</p>`;
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
is(inspector.selection.nodeFront, body, "By default the body node is selected");
|
||||
|
||||
info("Start the element picker");
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Shift-clicking element #one should select it but keep the picker ON");
|
||||
yield clickElement("#one", testActor, inspector, true);
|
||||
yield checkElementSelected("#one", inspector);
|
||||
checkPickerMode(toolbox, true);
|
||||
|
||||
info("Shift-clicking element #two should select it but keep the picker ON");
|
||||
yield clickElement("#two", testActor, inspector, true);
|
||||
yield checkElementSelected("#two", inspector);
|
||||
checkPickerMode(toolbox, true);
|
||||
|
||||
info("Clicking element #three should select it and turn the picker OFF");
|
||||
yield clickElement("#three", testActor, inspector, false);
|
||||
yield checkElementSelected("#three", inspector);
|
||||
checkPickerMode(toolbox, false);
|
||||
});
|
||||
|
||||
function* clickElement(selector, testActor, inspector, isShift) {
|
||||
let onSelectionChanged = inspector.once("inspector-updated");
|
||||
yield testActor.synthesizeMouse({
|
||||
selector: selector,
|
||||
center: true,
|
||||
options: { shiftKey: isShift }
|
||||
});
|
||||
yield onSelectionChanged;
|
||||
}
|
||||
|
||||
function* checkElementSelected(selector, inspector) {
|
||||
let el = yield getNodeFront(selector, inspector);
|
||||
is(inspector.selection.nodeFront, el, `The element ${selector} is now selected`);
|
||||
}
|
||||
|
||||
function checkPickerMode(toolbox, isOn) {
|
||||
let pickerButton = toolbox.doc.querySelector("#command-button-pick");
|
||||
is(pickerButton.hasAttribute("checked"), isOn, "The picker mode is correct");
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
/* 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 custom rect highlighter provides the right API, ensures that
|
||||
// the input is valid and that it does create a box with the right dimensions,
|
||||
// at the right position.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,Rect Highlighter Test";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
let highlighter = yield front.getHighlighterByType("RectHighlighter");
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
|
||||
info("Make sure the highlighter returned is correct");
|
||||
|
||||
ok(highlighter, "The RectHighlighter custom type was created");
|
||||
is(highlighter.typeName, "customhighlighter",
|
||||
"The RectHighlighter has the right type");
|
||||
ok(highlighter.show && highlighter.hide,
|
||||
"The RectHighlighter has the expected show/hide methods");
|
||||
|
||||
info("Check that the highlighter is hidden by default");
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden by default");
|
||||
|
||||
info("Check that nothing is shown if no rect is passed");
|
||||
|
||||
yield highlighter.show(body);
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden when no rect is passed");
|
||||
|
||||
info("Check that nothing is shown if rect is incomplete or invalid");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 0, y: 0}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden when the rect is incomplete");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 0, y: 0, width: -Infinity, height: 0}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden when the rect is invalid (1)");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 0, y: 0, width: 5, height: -45}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden when the rect is invalid (2)");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: "test", y: 0, width: 5, height: 5}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden when the rect is invalid (3)");
|
||||
|
||||
info("Check that the highlighter is displayed when valid options are passed");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 5, y: 5, width: 50, height: 50}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
ok(!hidden, "The highlighter is displayed");
|
||||
let style = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "style", highlighter);
|
||||
is(style, "left:5px;top:5px;width:50px;height:50px;",
|
||||
"The highlighter is positioned correctly");
|
||||
|
||||
info("Check that the highlighter can be displayed at x=0 y=0");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 0, y: 0, width: 50, height: 50}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
ok(!hidden, "The highlighter is displayed when x=0 and y=0");
|
||||
style = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "style", highlighter);
|
||||
is(style, "left:0px;top:0px;width:50px;height:50px;",
|
||||
"The highlighter is positioned correctly");
|
||||
|
||||
info("Check that the highlighter is hidden when dimensions are 0");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 0, y: 0, width: 0, height: 0}
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
is(hidden, "true", "The highlighter is hidden width and height are 0");
|
||||
|
||||
info("Check that a fill color can be passed");
|
||||
|
||||
yield highlighter.show(body, {
|
||||
rect: {x: 100, y: 200, width: 500, height: 200},
|
||||
fill: "red"
|
||||
});
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "hidden", highlighter);
|
||||
ok(!hidden, "The highlighter is displayed");
|
||||
style = yield testActor.getHighlighterNodeAttribute(
|
||||
"highlighted-rect", "style", highlighter);
|
||||
is(style, "left:100px;top:200px;width:500px;height:200px;background:red;",
|
||||
"The highlighter has the right background color");
|
||||
|
||||
yield highlighter.hide();
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* 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 custom rect highlighter positions the rectangle relative to the
|
||||
// viewport of the context node we pass to it.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_rect.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
let highlighter = yield front.getHighlighterByType("RectHighlighter");
|
||||
|
||||
info("Showing the rect highlighter in the context of the iframe");
|
||||
|
||||
// Get the reference to a context node inside the iframe
|
||||
let childBody = yield getNodeFrontInFrame("body", "iframe", inspector);
|
||||
yield highlighter.show(childBody, {
|
||||
rect: {x: 50, y: 50, width: 100, height: 100}
|
||||
});
|
||||
|
||||
let style = yield testActor.getHighlighterNodeAttribute("highlighted-rect",
|
||||
"style", highlighter);
|
||||
|
||||
// The parent body has margin=50px and border=10px
|
||||
// The parent iframe also has margin=50px and border=10px
|
||||
// = 50 + 10 + 50 + 10 = 120px
|
||||
// The rect is aat x=50 and y=50, so left and top should be 170px
|
||||
is(style, "left:170px;top:170px;width:100px;height:100px;",
|
||||
"The highlighter is correctly positioned");
|
||||
|
||||
yield highlighter.hide();
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
/* 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 the creation of the geometry highlighter elements.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<div style='position:absolute;left: 0; top: 0; " +
|
||||
"width: 40000px; height: 8000px'></div>";
|
||||
|
||||
const ID = "rulers-highlighter-";
|
||||
|
||||
// Maximum size, in pixel, for the horizontal ruler and vertical ruler
|
||||
// used by RulersHighlighter
|
||||
const RULERS_MAX_X_AXIS = 10000;
|
||||
const RULERS_MAX_Y_AXIS = 15000;
|
||||
// Number of steps after we add a text in RulersHighliter;
|
||||
// currently the unit is in pixel.
|
||||
const RULERS_TEXT_STEP = 100;
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
|
||||
let highlighter = yield front.getHighlighterByType("RulersHighlighter");
|
||||
|
||||
yield isHiddenByDefault(highlighter, inspector, testActor);
|
||||
yield hasRightLabelsContent(highlighter, inspector, testActor);
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
||||
function* isHiddenByDefault(highlighterFront, inspector, testActor) {
|
||||
info("Checking the highlighter is hidden by default");
|
||||
|
||||
let hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
ID + "elements", "hidden", highlighterFront);
|
||||
|
||||
is(hidden, "true", "highlighter is hidden by default");
|
||||
|
||||
info("Checking the highlighter is displayed when asked");
|
||||
// the rulers doesn't need any node, but as highligher it seems mandatory
|
||||
// ones, so the body is given
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
yield highlighterFront.show(body);
|
||||
|
||||
hidden = yield testActor.getHighlighterNodeAttribute(
|
||||
ID + "elements", "hidden", highlighterFront);
|
||||
|
||||
isnot(hidden, "true", "highlighter is visible after show");
|
||||
}
|
||||
|
||||
function* hasRightLabelsContent(highlighterFront, inspector, testActor) {
|
||||
info("Checking the rulers have the proper text, based on rulers' size");
|
||||
|
||||
let contentX = yield testActor.getHighlighterNodeTextContent(
|
||||
`${ID}x-axis-text`, highlighterFront);
|
||||
let contentY = yield testActor.getHighlighterNodeTextContent(
|
||||
`${ID}y-axis-text`, highlighterFront);
|
||||
|
||||
let expectedX = "";
|
||||
for (let i = RULERS_TEXT_STEP; i < RULERS_MAX_X_AXIS; i += RULERS_TEXT_STEP) {
|
||||
expectedX += i;
|
||||
}
|
||||
|
||||
is(contentX, expectedX, "x axis text content is correct");
|
||||
|
||||
let expectedY = "";
|
||||
for (let i = RULERS_TEXT_STEP; i < RULERS_MAX_Y_AXIS; i += RULERS_TEXT_STEP) {
|
||||
expectedY += i;
|
||||
}
|
||||
|
||||
is(contentY, expectedY, "y axis text content is correct");
|
||||
}
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/* 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 the creation of the geometry highlighter elements.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<div style='position:absolute;left: 0; top: 0; " +
|
||||
"width: 40000px; height: 8000px'></div>";
|
||||
|
||||
const ID = "rulers-highlighter-";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
|
||||
let highlighter = yield front.getHighlighterByType("RulersHighlighter");
|
||||
|
||||
// the rulers doesn't need any node, but as highligher it seems mandatory
|
||||
// ones, so the body is given
|
||||
let body = yield getNodeFront("body", inspector);
|
||||
yield highlighter.show(body);
|
||||
|
||||
yield isUpdatedAfterScroll(highlighter, inspector, testActor);
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
||||
function* isUpdatedAfterScroll(highlighterFront, inspector, testActor) {
|
||||
info("Check the rulers' position by default");
|
||||
|
||||
let xAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-ruler`, "transform", highlighterFront);
|
||||
let xAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-text`, "transform", highlighterFront);
|
||||
let yAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-ruler`, "transform", highlighterFront);
|
||||
let yAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-text`, "transform", highlighterFront);
|
||||
|
||||
is(xAxisRulerTransform, null, "x axis ruler is positioned properly");
|
||||
is(xAxisTextTransform, null, "x axis text are positioned properly");
|
||||
is(yAxisRulerTransform, null, "y axis ruler is positioned properly");
|
||||
is(yAxisTextTransform, null, "y axis text are positioned properly");
|
||||
|
||||
info("Ask the content window to scroll to specific coords");
|
||||
|
||||
let x = 200, y = 300;
|
||||
|
||||
let data = yield testActor.scrollWindow(x, y);
|
||||
|
||||
is(data.x, x, "window scrolled properly horizontally");
|
||||
is(data.y, y, "window scrolled properly vertically");
|
||||
|
||||
info("Check the rulers are properly positioned after the scrolling");
|
||||
|
||||
xAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-ruler`, "transform", highlighterFront);
|
||||
xAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-text`, "transform", highlighterFront);
|
||||
yAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-ruler`, "transform", highlighterFront);
|
||||
yAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-text`, "transform", highlighterFront);
|
||||
|
||||
is(xAxisRulerTransform, `translate(-${x})`,
|
||||
"x axis ruler is positioned properly");
|
||||
is(xAxisTextTransform, `translate(-${x})`,
|
||||
"x axis text are positioned properly");
|
||||
is(yAxisRulerTransform, `translate(0, -${y})`,
|
||||
"y axis ruler is positioned properly");
|
||||
is(yAxisTextTransform, `translate(0, -${y})`,
|
||||
"y axis text are positioned properly");
|
||||
|
||||
info("Ask the content window to scroll relative to the current position");
|
||||
|
||||
data = yield testActor.scrollWindow(-50, -60, true);
|
||||
|
||||
is(data.x, x - 50, "window scrolled properly horizontally");
|
||||
is(data.y, y - 60, "window scrolled properly vertically");
|
||||
|
||||
info("Check the rulers are properly positioned after the relative scrolling");
|
||||
|
||||
xAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-ruler`, "transform", highlighterFront);
|
||||
xAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}x-axis-text`, "transform", highlighterFront);
|
||||
yAxisRulerTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-ruler`, "transform", highlighterFront);
|
||||
yAxisTextTransform = yield testActor.getHighlighterNodeAttribute(
|
||||
`${ID}y-axis-text`, "transform", highlighterFront);
|
||||
|
||||
is(xAxisRulerTransform, `translate(-${x - 50})`,
|
||||
"x axis ruler is positioned properly");
|
||||
is(xAxisTextTransform, `translate(-${x - 50})`,
|
||||
"x axis text are positioned properly");
|
||||
is(yAxisRulerTransform, `translate(0, -${y - 60})`,
|
||||
"y axis ruler is positioned properly");
|
||||
is(yAxisTextTransform, `translate(0, -${y - 60})`,
|
||||
"y axis text are positioned properly");
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/* 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 custom selector highlighter creates as many box-model
|
||||
// highlighters as there are nodes that match the given selector
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<div id='test-node'>test node</div>" +
|
||||
"<ul>" +
|
||||
" <li class='item'>item</li>" +
|
||||
" <li class='item'>item</li>" +
|
||||
" <li class='item'>item</li>" +
|
||||
" <li class='item'>item</li>" +
|
||||
" <li class='item'>item</li>" +
|
||||
"</ul>";
|
||||
|
||||
const TEST_DATA = [{
|
||||
selector: "#test-node",
|
||||
containerCount: 1
|
||||
}, {
|
||||
selector: null,
|
||||
containerCount: 0,
|
||||
}, {
|
||||
selector: undefined,
|
||||
containerCount: 0,
|
||||
}, {
|
||||
selector: ".invalid-class",
|
||||
containerCount: 0
|
||||
}, {
|
||||
selector: ".item",
|
||||
containerCount: 5
|
||||
}, {
|
||||
selector: "#test-node, ul, .item",
|
||||
containerCount: 7
|
||||
}];
|
||||
|
||||
requestLongerTimeout(5);
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
let highlighter = yield front.getHighlighterByType("SelectorHighlighter");
|
||||
|
||||
let contextNode = yield getNodeFront("body", inspector);
|
||||
|
||||
for (let {selector, containerCount} of TEST_DATA) {
|
||||
info("Showing the highlighter on " + selector + ". Expecting " +
|
||||
containerCount + " highlighter containers");
|
||||
|
||||
yield highlighter.show(contextNode, {selector});
|
||||
|
||||
let nb = yield testActor.getSelectorHighlighterBoxNb(highlighter.actorID);
|
||||
ok(nb !== null, "The number of highlighters was retrieved");
|
||||
|
||||
is(nb, containerCount, "The correct number of highlighers were created");
|
||||
yield highlighter.hide();
|
||||
}
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* 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 custom selector highlighter creates highlighters for nodes in
|
||||
// the right frame.
|
||||
|
||||
const FRAME_SRC = "data:text/html;charset=utf-8," +
|
||||
"<div class=sub-level-node></div>";
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8," +
|
||||
"<div class=root-level-node></div>" +
|
||||
"<iframe src=\"" + FRAME_SRC + "\" />";
|
||||
|
||||
const TEST_DATA = [{
|
||||
selector: ".root-level-node",
|
||||
containerCount: 1
|
||||
}, {
|
||||
selector: ".sub-level-node",
|
||||
containerCount: 0
|
||||
}, {
|
||||
inIframe: true,
|
||||
selector: ".root-level-node",
|
||||
containerCount: 0
|
||||
}, {
|
||||
inIframe: true,
|
||||
selector: ".sub-level-node",
|
||||
containerCount: 1
|
||||
}];
|
||||
|
||||
requestLongerTimeout(5);
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
let front = inspector.inspector;
|
||||
let highlighter = yield front.getHighlighterByType("SelectorHighlighter");
|
||||
|
||||
for (let {inIframe, selector, containerCount} of TEST_DATA) {
|
||||
info("Showing the highlighter on " + selector + ". Expecting " +
|
||||
containerCount + " highlighter containers");
|
||||
|
||||
let contextNode;
|
||||
if (inIframe) {
|
||||
contextNode = yield getNodeFrontInFrame("body", "iframe", inspector);
|
||||
} else {
|
||||
contextNode = yield getNodeFront("body", inspector);
|
||||
}
|
||||
|
||||
yield highlighter.show(contextNode, {selector});
|
||||
|
||||
let nb = yield testActor.getSelectorHighlighterBoxNb(highlighter.actorID);
|
||||
ok(nb !== null, "The number of highlighters was retrieved");
|
||||
|
||||
is(nb, containerCount, "The correct number of highlighers were created");
|
||||
yield highlighter.hide();
|
||||
}
|
||||
|
||||
yield highlighter.finalize();
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// Test that the picker works correctly with XBL anonymous nodes
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_highlighter_xbl.xul";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, toolbox, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Selecting the scale");
|
||||
yield moveMouseOver("#scale");
|
||||
yield doKeyPick({key: "VK_RETURN", options: {}});
|
||||
is(inspector.selection.nodeFront.className, "scale-slider",
|
||||
"The .scale-slider inside the scale was selected");
|
||||
|
||||
function doKeyPick(msg) {
|
||||
info("Key pressed. Waiting for element to be picked");
|
||||
testActor.synthesizeKey(msg);
|
||||
return promise.all([
|
||||
inspector.selection.once("new-node-front"),
|
||||
inspector.once("inspector-updated")
|
||||
]);
|
||||
}
|
||||
|
||||
function moveMouseOver(selector) {
|
||||
info("Waiting for element " + selector + " to be highlighted");
|
||||
testActor.synthesizeMouse({
|
||||
options: {type: "mousemove"},
|
||||
center: true,
|
||||
selector: selector
|
||||
});
|
||||
return inspector.toolbox.once("picker-node-hovered");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/* 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 stays correctly positioned and has the right aspect
|
||||
// ratio even when the page is zoomed in or out.
|
||||
|
||||
const TEST_URL = "data:text/html;charset=utf-8,<div>zoom me</div>";
|
||||
|
||||
// TEST_LEVELS entries should contain the following properties:
|
||||
// - level: the zoom level to test
|
||||
// - expected: the style attribute value to check for on the root highlighter
|
||||
// element.
|
||||
const TEST_LEVELS = [{
|
||||
level: 2,
|
||||
expected: "position:absolute;transform-origin:top left;" +
|
||||
"transform:scale(0.5);width:200%;height:200%;"
|
||||
}, {
|
||||
level: 1,
|
||||
expected: "position:absolute;width:100%;height:100%;"
|
||||
}, {
|
||||
level: .5,
|
||||
expected: "position:absolute;transform-origin:top left;" +
|
||||
"transform:scale(2);width:50%;height:50%;"
|
||||
}];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Highlighting the test node");
|
||||
|
||||
yield hoverElement("div", inspector);
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is visible");
|
||||
|
||||
for (let {level, expected} of TEST_LEVELS) {
|
||||
info("Zoom to level " + level +
|
||||
" and check that the highlighter is correct");
|
||||
|
||||
yield testActor.zoomPageTo(level);
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "The highlighter is still visible at zoom level " + level);
|
||||
|
||||
yield testActor.isNodeCorrectlyHighlighted("div", is);
|
||||
|
||||
info("Check that the highlighter root wrapper node was scaled down");
|
||||
|
||||
let style = yield getRootNodeStyle(testActor);
|
||||
is(style, expected, "The style attribute of the root element is correct");
|
||||
}
|
||||
});
|
||||
|
||||
function* hoverElement(selector, inspector) {
|
||||
info("Hovering node " + selector + " in the markup view");
|
||||
let container = yield getContainerForSelector(selector, inspector);
|
||||
yield hoverContainer(container, inspector);
|
||||
}
|
||||
|
||||
function* hoverContainer(container, inspector) {
|
||||
let onHighlight = inspector.toolbox.once("node-highlight");
|
||||
EventUtils.synthesizeMouse(container.tagLine, 2, 2, {type: "mousemove"},
|
||||
inspector.markup.doc.defaultView);
|
||||
yield onHighlight;
|
||||
}
|
||||
|
||||
function* getRootNodeStyle(testActor) {
|
||||
let value = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-root", "style");
|
||||
return value;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the highlighter element picker still works through iframe
|
||||
// navigations.
|
||||
|
||||
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>";
|
||||
|
||||
add_task(function* () {
|
||||
let { toolbox, testActor } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Starting element picker.");
|
||||
yield startPicker(toolbox);
|
||||
|
||||
info("Waiting for highlighter to activate.");
|
||||
let highlighterShowing = toolbox.once("highlighter-ready");
|
||||
testActor.synthesizeMouse({
|
||||
selector: "body",
|
||||
options: {type: "mousemove"},
|
||||
x: 1,
|
||||
y: 1
|
||||
});
|
||||
yield highlighterShowing;
|
||||
|
||||
let isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "Inspector is highlighting.");
|
||||
|
||||
yield testActor.reloadFrame("iframe");
|
||||
info("Frame reloaded. Reloading again.");
|
||||
|
||||
yield testActor.reloadFrame("iframe");
|
||||
info("Frame reloaded twice.");
|
||||
|
||||
isVisible = yield testActor.isHighlighting();
|
||||
ok(isVisible, "Inspector is highlighting after iframe nav.");
|
||||
|
||||
info("Stopping element picker.");
|
||||
yield toolbox.highlighterUtils.stopPicker();
|
||||
});
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/* 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";
|
||||
|
||||
// Check the position and text content of the highlighter nodeinfo bar.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_infobar_01.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
let testData = [
|
||||
{
|
||||
selector: "#top",
|
||||
position: "bottom",
|
||||
tag: "div",
|
||||
id: "top",
|
||||
classes: ".class1.class2",
|
||||
dims: "500" + " \u00D7 " + "100"
|
||||
},
|
||||
{
|
||||
selector: "#vertical",
|
||||
position: "overlap",
|
||||
tag: "div",
|
||||
id: "vertical",
|
||||
classes: ""
|
||||
// No dims as they will vary between computers
|
||||
},
|
||||
{
|
||||
selector: "#bottom",
|
||||
position: "top",
|
||||
tag: "div",
|
||||
id: "bottom",
|
||||
classes: "",
|
||||
dims: "500" + " \u00D7 " + "100"
|
||||
},
|
||||
{
|
||||
selector: "body",
|
||||
position: "bottom",
|
||||
tag: "body",
|
||||
classes: ""
|
||||
// No dims as they will vary between computers
|
||||
},
|
||||
{
|
||||
selector: "clipPath",
|
||||
position: "bottom",
|
||||
tag: "clipPath",
|
||||
id: "clip",
|
||||
classes: ""
|
||||
// No dims as element is not displayed and we just want to test tag name
|
||||
},
|
||||
];
|
||||
|
||||
for (let currTest of testData) {
|
||||
yield testPosition(currTest, inspector, testActor);
|
||||
}
|
||||
});
|
||||
|
||||
function* testPosition(test, inspector, testActor) {
|
||||
info("Testing " + test.selector);
|
||||
|
||||
yield selectAndHighlightNode(test.selector, inspector);
|
||||
|
||||
let position = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-infobar-container", "position");
|
||||
is(position, test.position, "Node " + test.selector + ": position matches");
|
||||
|
||||
let tag = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-tagname");
|
||||
is(tag, test.tag, "node " + test.selector + ": tagName matches.");
|
||||
|
||||
if (test.id) {
|
||||
let id = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-id");
|
||||
is(id, "#" + test.id, "node " + test.selector + ": id matches.");
|
||||
}
|
||||
|
||||
let classes = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-classes");
|
||||
is(classes, test.classes, "node " + test.selector + ": classes match.");
|
||||
|
||||
if (test.dims) {
|
||||
let dims = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-dimensions");
|
||||
is(dims, test.dims, "node " + test.selector + ": dims match.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/* 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";
|
||||
|
||||
// Check the text content of the highlighter info bar for namespaced elements.
|
||||
|
||||
const XHTML = `
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<body>
|
||||
<svg:svg width="100" height="100">
|
||||
<svg:circle cx="0" cy="0" r="5"></svg:circle>
|
||||
</svg:svg>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
const TEST_URI = "data:application/xhtml+xml;charset=utf-8," + encodeURI(XHTML);
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
let testData = [
|
||||
{
|
||||
selector: "svg",
|
||||
tag: "svg:svg"
|
||||
},
|
||||
{
|
||||
selector: "circle",
|
||||
tag: "svg:circle"
|
||||
},
|
||||
];
|
||||
|
||||
for (let currTest of testData) {
|
||||
yield testNode(currTest, inspector, testActor);
|
||||
}
|
||||
});
|
||||
|
||||
function* testNode(test, inspector, testActor) {
|
||||
info("Testing " + test.selector);
|
||||
|
||||
yield selectAndHighlightNode(test.selector, inspector);
|
||||
|
||||
let tag = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-tagname");
|
||||
is(tag, test.tag, "node " + test.selector + ": tagName matches.");
|
||||
}
|
||||
|
|
@ -0,0 +1,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";
|
||||
|
||||
// Bug 1102269 - Make sure info-bar never gets outside of visible area after scrolling
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_infobar_03.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
let testData = {
|
||||
selector: "body",
|
||||
position: "overlap",
|
||||
style: "top:0px",
|
||||
};
|
||||
|
||||
yield testPositionAndStyle(testData, inspector, testActor);
|
||||
});
|
||||
|
||||
function* testPositionAndStyle(test, inspector, testActor) {
|
||||
info("Testing " + test.selector);
|
||||
|
||||
yield selectAndHighlightNode(test.selector, inspector);
|
||||
|
||||
let style = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-infobar-container", "style");
|
||||
|
||||
is(style.split(";")[0], test.style,
|
||||
"Infobar shows on top of the page when page isn't scrolled");
|
||||
|
||||
yield testActor.scrollWindow(0, 500);
|
||||
|
||||
style = yield testActor.getHighlighterNodeAttribute(
|
||||
"box-model-infobar-container", "style");
|
||||
|
||||
is(style.split(";")[0], test.style,
|
||||
"Infobar shows on top of the page even if the page is scrolled");
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* 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";
|
||||
|
||||
// Bug 1309212 - Make sure info-bar is displayed with dimensions for text nodes.
|
||||
|
||||
const TEST_URI = URL_ROOT + "doc_inspector_infobar_textnode.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URI);
|
||||
let { walker } = inspector;
|
||||
|
||||
info("Retrieve the children of #textnode-container");
|
||||
let div = yield walker.querySelector(walker.rootNode, "#textnode-container");
|
||||
let { nodes } = yield inspector.walker.children(div);
|
||||
|
||||
// Children 0, 2 and 4 are text nodes, for which we expect to see an infobar containing
|
||||
// dimensions.
|
||||
|
||||
// Regular text node.
|
||||
info("Select the first text node");
|
||||
yield selectNode(nodes[0], inspector, "test-highlight");
|
||||
yield checkTextNodeInfoBar(testActor);
|
||||
|
||||
// Whitespace-only text node.
|
||||
info("Select the second text node");
|
||||
yield selectNode(nodes[2], inspector, "test-highlight");
|
||||
yield checkTextNodeInfoBar(testActor);
|
||||
|
||||
// Regular text node.
|
||||
info("Select the third text node");
|
||||
yield selectNode(nodes[4], inspector, "test-highlight");
|
||||
yield checkTextNodeInfoBar(testActor);
|
||||
});
|
||||
|
||||
function* checkTextNodeInfoBar(testActor) {
|
||||
let tag = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-tagname");
|
||||
is(tag, "#text", "node display name is #text");
|
||||
let dims = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-dimensions");
|
||||
// Do not assert dimensions as they might be platform specific.
|
||||
ok(!!dims, "node has dims");
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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/. */
|
||||
/* globals getTestActorWithoutToolbox */
|
||||
"use strict";
|
||||
|
||||
// Tests for different ways to initialize the inspector.
|
||||
|
||||
const HTML = `
|
||||
<div id="first" style="margin: 10em; font-size: 14pt;
|
||||
font-family: helvetica, sans-serif; color: gray">
|
||||
<h1>Some header text</h1>
|
||||
<p id="salutation" style="font-size: 12pt">hi.</p>
|
||||
<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>
|
||||
<p>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>
|
||||
<p id="closing">end transmission</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," + encodeURI(HTML);
|
||||
|
||||
add_task(function* () {
|
||||
let tab = yield addTab(TEST_URI);
|
||||
let testActor = yield getTestActorWithoutToolbox(tab);
|
||||
|
||||
yield testToolboxInitialization(testActor, tab);
|
||||
yield testContextMenuInitialization(testActor);
|
||||
yield testContextMenuInspectorAlreadyOpen(testActor);
|
||||
});
|
||||
|
||||
function* testToolboxInitialization(testActor, 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.");
|
||||
|
||||
yield selectNode("p", inspector);
|
||||
yield testMarkupView("p", inspector);
|
||||
yield testBreadcrumbs("p", inspector);
|
||||
|
||||
yield testActor.scrollIntoView("span");
|
||||
|
||||
yield selectNode("span", inspector);
|
||||
yield testMarkupView("span", inspector);
|
||||
yield testBreadcrumbs("span", inspector);
|
||||
|
||||
info("Destroying toolbox");
|
||||
let destroyed = toolbox.once("destroyed");
|
||||
toolbox.destroy();
|
||||
yield destroyed;
|
||||
|
||||
ok("true", "'destroyed' notification received.");
|
||||
ok(!gDevTools.getToolbox(target), "Toolbox destroyed.");
|
||||
}
|
||||
|
||||
function* testContextMenuInitialization(testActor) {
|
||||
info("Opening inspector by clicking on 'Inspect Element' context menu item");
|
||||
yield clickOnInspectMenuItem(testActor, "#salutation");
|
||||
|
||||
info("Checking inspector state.");
|
||||
yield testMarkupView("#salutation");
|
||||
yield testBreadcrumbs("#salutation");
|
||||
}
|
||||
|
||||
function* testContextMenuInspectorAlreadyOpen(testActor) {
|
||||
info("Changing node by clicking on 'Inspect Element' context menu item");
|
||||
|
||||
let inspector = getActiveInspector();
|
||||
ok(inspector, "Inspector is active");
|
||||
|
||||
yield clickOnInspectMenuItem(testActor, "#closing");
|
||||
|
||||
ok(true, "Inspector was updated when 'Inspect Element' was clicked.");
|
||||
yield testMarkupView("#closing", inspector);
|
||||
yield testBreadcrumbs("#closing", inspector);
|
||||
}
|
||||
|
||||
function* testMarkupView(selector, inspector) {
|
||||
inspector = inspector || getActiveInspector();
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
try {
|
||||
is(inspector.selection.nodeFront, nodeFront,
|
||||
"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(selector, inspector) {
|
||||
inspector = inspector || getActiveInspector();
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
|
||||
let b = inspector.breadcrumbs;
|
||||
let expectedText = b.prettyPrintNodeAsText(nodeFront);
|
||||
let button = b.container.querySelector("button[checked=true]");
|
||||
ok(button, "A crumbs is checked=true");
|
||||
is(button.getAttribute("title"), expectedText,
|
||||
"Crumb refers to the right node");
|
||||
}
|
||||
|
|
@ -0,0 +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";
|
||||
|
||||
// A regression test for bug 665880 to make sure elements inside <object> can
|
||||
// be inspected without exceptions.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"<object><p>browser_inspector_inspect-object-element.js</p></object>";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
yield selectNode("object", inspector);
|
||||
|
||||
ok(true, "Selected <object> without throwing");
|
||||
});
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/* 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 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>";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
let divFront = yield getNodeFront("div", inspector);
|
||||
|
||||
info("Waiting for highlighter to activate");
|
||||
yield inspector.highlighter.showBoxModel(divFront);
|
||||
|
||||
let rect = yield testActor.getSimpleBorderRect();
|
||||
is(rect.width, 100, "The highlighter has the right width.");
|
||||
|
||||
info("Changing the test element's size and waiting for the highlighter " +
|
||||
"to update");
|
||||
yield testActor.changeHighlightedNodeWaitForUpdate(
|
||||
"style",
|
||||
"width: 200px; height: 100px; background:yellow;"
|
||||
);
|
||||
|
||||
rect = yield testActor.getSimpleBorderRect();
|
||||
is(rect.width, 200, "The highlighter has the right width after update");
|
||||
|
||||
info("Waiting for highlighter to hide");
|
||||
yield inspector.highlighter.hideBoxModel();
|
||||
});
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* 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 copy outer HTML from the keyboard/copy event
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_outerhtml.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
let root = inspector.markup._elt;
|
||||
|
||||
info("Test copy outerHTML for COMMENT node");
|
||||
let comment = getElementByType(inspector, Ci.nsIDOMNode.COMMENT_NODE);
|
||||
yield setSelectionNodeFront(comment, inspector);
|
||||
yield checkClipboard("<!-- Comment -->", root);
|
||||
|
||||
info("Test copy outerHTML for DOCTYPE node");
|
||||
let doctype = getElementByType(inspector, Ci.nsIDOMNode.DOCUMENT_TYPE_NODE);
|
||||
yield setSelectionNodeFront(doctype, inspector);
|
||||
yield checkClipboard("<!DOCTYPE html>", root);
|
||||
|
||||
info("Test copy outerHTML for ELEMENT node");
|
||||
yield selectAndHighlightNode("div", inspector);
|
||||
yield checkClipboard("<div><p>Test copy OuterHTML</p></div>", root);
|
||||
});
|
||||
|
||||
function* setSelectionNodeFront(node, inspector) {
|
||||
let updated = inspector.once("inspector-updated");
|
||||
inspector.selection.setNodeFront(node);
|
||||
yield updated;
|
||||
}
|
||||
|
||||
function* checkClipboard(expectedText, node) {
|
||||
try {
|
||||
yield waitForClipboardPromise(() => fireCopyEvent(node), expectedText);
|
||||
ok(true, "Clipboard successfully filled with : " + expectedText);
|
||||
} catch (e) {
|
||||
ok(false, "Clipboard could not be filled with the expected text : " +
|
||||
expectedText);
|
||||
}
|
||||
}
|
||||
|
||||
function getElementByType(inspector, type) {
|
||||
for (let [node] of inspector.markup._containers) {
|
||||
if (node.nodeType === type) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Tests that the keybindings for highlighting different elements work as
|
||||
// intended.
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"<html><head><title>Test for the highlighter keybindings</title></head>" +
|
||||
"<body><p><strong>Greetings, earthlings!</strong>" +
|
||||
" I come in peace.</p></body></html>";
|
||||
|
||||
const TEST_DATA = [
|
||||
{ key: "VK_LEFT", selectedNode: "p" },
|
||||
{ key: "VK_LEFT", selectedNode: "body" },
|
||||
{ key: "VK_LEFT", selectedNode: "html" },
|
||||
{ key: "VK_RIGHT", selectedNode: "body" },
|
||||
{ key: "VK_RIGHT", selectedNode: "p" },
|
||||
{ key: "VK_RIGHT", selectedNode: "strong" },
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
info("Selecting the deepest element to start with");
|
||||
yield selectNode("strong", inspector);
|
||||
|
||||
let nodeFront = yield getNodeFront("strong", inspector);
|
||||
is(inspector.selection.nodeFront, nodeFront,
|
||||
"<strong> should be selected initially");
|
||||
|
||||
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;
|
||||
|
||||
let selectedNodeFront = yield getNodeFront(selectedNode, inspector);
|
||||
is(inspector.selection.nodeFront, selectedNodeFront,
|
||||
selectedNode + " is selected.");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/* 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 context menu items are enabled / disabled correctly.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
|
||||
const PASTE_MENU_ITEMS = [
|
||||
"node-menu-pasteinnerhtml",
|
||||
"node-menu-pasteouterhtml",
|
||||
"node-menu-pastebefore",
|
||||
"node-menu-pasteafter",
|
||||
"node-menu-pastefirstchild",
|
||||
"node-menu-pastelastchild",
|
||||
];
|
||||
|
||||
const ACTIVE_ON_DOCTYPE_ITEMS = [
|
||||
"node-menu-showdomproperties",
|
||||
"node-menu-useinconsole"
|
||||
];
|
||||
|
||||
const ALL_MENU_ITEMS = [
|
||||
"node-menu-edithtml",
|
||||
"node-menu-copyinner",
|
||||
"node-menu-copyouter",
|
||||
"node-menu-copyuniqueselector",
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-delete",
|
||||
"node-menu-pseudo-hover",
|
||||
"node-menu-pseudo-active",
|
||||
"node-menu-pseudo-focus",
|
||||
"node-menu-scrollnodeintoview",
|
||||
"node-menu-screenshotnode",
|
||||
"node-menu-add-attribute",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
].concat(PASTE_MENU_ITEMS, ACTIVE_ON_DOCTYPE_ITEMS);
|
||||
|
||||
const INACTIVE_ON_DOCTYPE_ITEMS =
|
||||
ALL_MENU_ITEMS.filter(item => ACTIVE_ON_DOCTYPE_ITEMS.indexOf(item) === -1);
|
||||
|
||||
/**
|
||||
* Test cases, each item of this array may define the following properties:
|
||||
* desc: string that will be logged
|
||||
* selector: selector of the node to be selected
|
||||
* disabled: items that should have disabled state
|
||||
* clipboardData: clipboard content
|
||||
* clipboardDataType: clipboard content type
|
||||
* attributeTrigger: attribute that will be used as context menu trigger
|
||||
*/
|
||||
const TEST_CASES = [
|
||||
{
|
||||
desc: "doctype node with empty clipboard",
|
||||
selector: null,
|
||||
disabled: INACTIVE_ON_DOCTYPE_ITEMS,
|
||||
},
|
||||
{
|
||||
desc: "doctype node with html on clipboard",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
selector: null,
|
||||
disabled: INACTIVE_ON_DOCTYPE_ITEMS,
|
||||
},
|
||||
{
|
||||
desc: "element node HTML on the clipboard",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
disabled: [
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
],
|
||||
selector: "#sensitivity",
|
||||
},
|
||||
{
|
||||
desc: "<html> element",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
selector: "html",
|
||||
disabled: [
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-pastebefore",
|
||||
"node-menu-pasteafter",
|
||||
"node-menu-pastefirstchild",
|
||||
"node-menu-pastelastchild",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
],
|
||||
},
|
||||
{
|
||||
desc: "<body> with HTML on clipboard",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
selector: "body",
|
||||
disabled: [
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-pastebefore",
|
||||
"node-menu-pasteafter",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]
|
||||
},
|
||||
{
|
||||
desc: "<img> with HTML on clipboard",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
selector: "img",
|
||||
disabled: [
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]
|
||||
},
|
||||
{
|
||||
desc: "<head> with HTML on clipboard",
|
||||
clipboardData: "<p>some text</p>",
|
||||
clipboardDataType: "html",
|
||||
selector: "head",
|
||||
disabled: [
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-pastebefore",
|
||||
"node-menu-pasteafter",
|
||||
"node-menu-screenshotnode",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
],
|
||||
},
|
||||
{
|
||||
desc: "<head> with no html on clipboard",
|
||||
selector: "head",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-screenshotnode",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> with text on clipboard",
|
||||
clipboardData: "some text",
|
||||
clipboardDataType: undefined,
|
||||
selector: "#paste-area",
|
||||
disabled: [
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]
|
||||
},
|
||||
{
|
||||
desc: "<element> with base64 encoded image data uri on clipboard",
|
||||
clipboardData:
|
||||
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABC" +
|
||||
"AAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJggg==",
|
||||
clipboardDataType: undefined,
|
||||
selector: "#paste-area",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> with empty string on clipboard",
|
||||
clipboardData: "",
|
||||
clipboardDataType: undefined,
|
||||
selector: "#paste-area",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> with whitespace only on clipboard",
|
||||
clipboardData: " \n\n\t\n\n \n",
|
||||
clipboardDataType: undefined,
|
||||
selector: "#paste-area",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> that isn't visible on the page, empty clipboard",
|
||||
selector: "#hiddenElement",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-screenshotnode",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> nested in another hidden element, empty clipboard",
|
||||
selector: "#nestedHiddenElement",
|
||||
disabled: PASTE_MENU_ITEMS.concat([
|
||||
"node-menu-copyimagedatauri",
|
||||
"node-menu-screenshotnode",
|
||||
"node-menu-edit-attribute",
|
||||
"node-menu-remove-attribute"
|
||||
]),
|
||||
},
|
||||
{
|
||||
desc: "<element> with context menu triggered on attribute, empty clipboard",
|
||||
selector: "#attributes",
|
||||
disabled: PASTE_MENU_ITEMS.concat(["node-menu-copyimagedatauri"]),
|
||||
attributeTrigger: "data-edit"
|
||||
}
|
||||
];
|
||||
|
||||
var clipboard = require("sdk/clipboard");
|
||||
registerCleanupFunction(() => {
|
||||
clipboard = null;
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
for (let test of TEST_CASES) {
|
||||
let { desc, disabled, selector, attributeTrigger } = test;
|
||||
|
||||
info(`Test ${desc}`);
|
||||
setupClipboard(test.clipboardData, test.clipboardDataType);
|
||||
|
||||
let front = yield getNodeFrontForSelector(selector, inspector);
|
||||
|
||||
info("Selecting the specified node.");
|
||||
yield selectNode(front, inspector);
|
||||
|
||||
info("Simulating context menu click on the selected node container.");
|
||||
let nodeFrontContainer = getContainerForNodeFront(front, inspector);
|
||||
let contextMenuTrigger = attributeTrigger
|
||||
? nodeFrontContainer.tagLine.querySelector(
|
||||
`[data-attr="${attributeTrigger}"]`)
|
||||
: nodeFrontContainer.tagLine;
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: contextMenuTrigger,
|
||||
});
|
||||
|
||||
for (let id of ALL_MENU_ITEMS) {
|
||||
let menuItem = allMenuItems.find(item => item.id === id);
|
||||
let shouldBeDisabled = disabled.indexOf(id) !== -1;
|
||||
is(menuItem.disabled, shouldBeDisabled,
|
||||
`#${id} should be ${shouldBeDisabled ? "disabled" : "enabled"} `);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* A helper that fetches a front for a node that matches the given selector or
|
||||
* doctype node if the selector is falsy.
|
||||
*/
|
||||
function* getNodeFrontForSelector(selector, inspector) {
|
||||
if (selector) {
|
||||
info("Retrieving front for selector " + selector);
|
||||
return getNodeFront(selector, inspector);
|
||||
}
|
||||
|
||||
info("Retrieving front for doctype node");
|
||||
let {nodes} = yield inspector.walker.children(inspector.walker.rootNode);
|
||||
return nodes[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper that populates the clipboard with data of given type. Clears the
|
||||
* clipboard if data is falsy.
|
||||
*/
|
||||
function setupClipboard(data, type) {
|
||||
if (data) {
|
||||
info("Populating clipboard with " + type + " data.");
|
||||
clipboard.set(data, type);
|
||||
} else {
|
||||
info("Clearing clipboard.");
|
||||
clipboard.set("", "text");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/* 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 various copy items in the context menu works correctly.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
const COPY_ITEMS_TEST_DATA = [
|
||||
{
|
||||
desc: "copy inner html",
|
||||
id: "node-menu-copyinner",
|
||||
selector: "[data-id=\"copy\"]",
|
||||
text: "Paragraph for testing copy",
|
||||
},
|
||||
{
|
||||
desc: "copy outer html",
|
||||
id: "node-menu-copyouter",
|
||||
selector: "[data-id=\"copy\"]",
|
||||
text: "<p data-id=\"copy\">Paragraph for testing copy</p>",
|
||||
},
|
||||
{
|
||||
desc: "copy unique selector",
|
||||
id: "node-menu-copyuniqueselector",
|
||||
selector: "[data-id=\"copy\"]",
|
||||
text: "body > div:nth-child(1) > p:nth-child(2)",
|
||||
},
|
||||
{
|
||||
desc: "copy image data uri",
|
||||
id: "node-menu-copyimagedatauri",
|
||||
selector: "#copyimage",
|
||||
text: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABC" +
|
||||
"AAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJggg==",
|
||||
},
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
for (let {desc, id, selector, text} of COPY_ITEMS_TEST_DATA) {
|
||||
info("Testing " + desc);
|
||||
yield selectNode(selector, inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let item = allMenuItems.find(i => i.id === id);
|
||||
ok(item, "The popup has a " + desc + " menu item.");
|
||||
|
||||
yield waitForClipboardPromise(() => item.click(), text);
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* 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 HTML can be pasted in SVG elements.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_svg.svg";
|
||||
const PASTE_AS_FIRST_CHILD = '<circle xmlns="http://www.w3.org/2000/svg" cx="42" cy="42" r="5"/>';
|
||||
const PASTE_AS_LAST_CHILD = '<circle xmlns="http://www.w3.org/2000/svg" cx="42" cy="42" r="15"/>';
|
||||
|
||||
add_task(function* () {
|
||||
let clipboard = require("sdk/clipboard");
|
||||
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
let refSelector = "svg";
|
||||
let oldHTML = yield testActor.getProperty(refSelector, "innerHTML");
|
||||
yield selectNode(refSelector, inspector);
|
||||
let markupTagLine = getContainerForSelector(refSelector, inspector).tagLine;
|
||||
|
||||
yield pasteContent("node-menu-pastefirstchild", PASTE_AS_FIRST_CHILD);
|
||||
yield pasteContent("node-menu-pastelastchild", PASTE_AS_LAST_CHILD);
|
||||
|
||||
let html = yield testActor.getProperty(refSelector, "innerHTML");
|
||||
let expectedHtml = PASTE_AS_FIRST_CHILD + oldHTML + PASTE_AS_LAST_CHILD;
|
||||
is(html, expectedHtml, "The innerHTML of the SVG node is correct");
|
||||
|
||||
// Helpers
|
||||
function* pasteContent(menuId, clipboardData) {
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: markupTagLine,
|
||||
});
|
||||
info(`Testing ${menuId} for ${clipboardData}`);
|
||||
clipboard.set(clipboardData);
|
||||
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
allMenuItems.find(item => item.id === menuId).click();
|
||||
info("Waiting for mutation to occur");
|
||||
yield onMutation;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/* 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 different paste items work in the context menu
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
const PASTE_ADJACENT_HTML_DATA = [
|
||||
{
|
||||
desc: "As First Child",
|
||||
clipboardData: "2",
|
||||
menuId: "node-menu-pastefirstchild",
|
||||
},
|
||||
{
|
||||
desc: "As Last Child",
|
||||
clipboardData: "4",
|
||||
menuId: "node-menu-pastelastchild",
|
||||
},
|
||||
{
|
||||
desc: "Before",
|
||||
clipboardData: "1",
|
||||
menuId: "node-menu-pastebefore",
|
||||
},
|
||||
{
|
||||
desc: "After",
|
||||
clipboardData: "<span>5</span>",
|
||||
menuId: "node-menu-pasteafter",
|
||||
},
|
||||
];
|
||||
|
||||
var clipboard = require("sdk/clipboard");
|
||||
registerCleanupFunction(() => {
|
||||
clipboard = null;
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield testPasteOuterHTMLMenu();
|
||||
yield testPasteInnerHTMLMenu();
|
||||
yield testPasteAdjacentHTMLMenu();
|
||||
|
||||
function* testPasteOuterHTMLMenu() {
|
||||
info("Testing that 'Paste Outer HTML' menu item works.");
|
||||
clipboard.set("this was pasted (outerHTML)");
|
||||
let outerHTMLSelector = "#paste-area h1";
|
||||
|
||||
let nodeFront = yield getNodeFront(outerHTMLSelector, inspector);
|
||||
yield selectNode(nodeFront, inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: getContainerForNodeFront(nodeFront, inspector).tagLine,
|
||||
});
|
||||
|
||||
let onNodeReselected = inspector.markup.once("reselectedonremoved");
|
||||
allMenuItems.find(item => item.id === "node-menu-pasteouterhtml").click();
|
||||
|
||||
info("Waiting for inspector selection to update");
|
||||
yield onNodeReselected;
|
||||
|
||||
let outerHTML = yield testActor.getProperty("body", "outerHTML");
|
||||
ok(outerHTML.includes(clipboard.get()),
|
||||
"Clipboard content was pasted into the node's outer HTML.");
|
||||
ok(!(yield testActor.hasNode(outerHTMLSelector)),
|
||||
"The original node was removed.");
|
||||
}
|
||||
|
||||
function* testPasteInnerHTMLMenu() {
|
||||
info("Testing that 'Paste Inner HTML' menu item works.");
|
||||
clipboard.set("this was pasted (innerHTML)");
|
||||
let innerHTMLSelector = "#paste-area .inner";
|
||||
let getInnerHTML = () => testActor.getProperty(innerHTMLSelector,
|
||||
"innerHTML");
|
||||
let origInnerHTML = yield getInnerHTML();
|
||||
|
||||
let nodeFront = yield getNodeFront(innerHTMLSelector, inspector);
|
||||
yield selectNode(nodeFront, inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: getContainerForNodeFront(nodeFront, inspector).tagLine,
|
||||
});
|
||||
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
allMenuItems.find(item => item.id === "node-menu-pasteinnerhtml").click();
|
||||
info("Waiting for mutation to occur");
|
||||
yield onMutation;
|
||||
|
||||
ok((yield getInnerHTML()) === clipboard.get(),
|
||||
"Clipboard content was pasted into the node's inner HTML.");
|
||||
ok((yield testActor.hasNode(innerHTMLSelector)),
|
||||
"The original node has been preserved.");
|
||||
yield undoChange(inspector);
|
||||
ok((yield getInnerHTML()) === origInnerHTML,
|
||||
"Previous innerHTML has been restored after undo");
|
||||
}
|
||||
|
||||
function* testPasteAdjacentHTMLMenu() {
|
||||
let refSelector = "#paste-area .adjacent .ref";
|
||||
let adjacentNodeSelector = "#paste-area .adjacent";
|
||||
let nodeFront = yield getNodeFront(refSelector, inspector);
|
||||
yield selectNode(nodeFront, inspector);
|
||||
let markupTagLine = getContainerForNodeFront(nodeFront, inspector).tagLine;
|
||||
|
||||
for (let { clipboardData, menuId } of PASTE_ADJACENT_HTML_DATA) {
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: markupTagLine,
|
||||
});
|
||||
info(`Testing ${menuId} for ${clipboardData}`);
|
||||
clipboard.set(clipboardData);
|
||||
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
allMenuItems.find(item => item.id === menuId).click();
|
||||
info("Waiting for mutation to occur");
|
||||
yield onMutation;
|
||||
}
|
||||
|
||||
let html = yield testActor.getProperty(adjacentNodeSelector, "innerHTML");
|
||||
ok(html.trim() === "1<span class=\"ref\">234</span><span>5</span>",
|
||||
"The Paste as Last Child / as First Child / Before / After worked as " +
|
||||
"expected");
|
||||
yield undoChange(inspector);
|
||||
|
||||
html = yield testActor.getProperty(adjacentNodeSelector, "innerHTML");
|
||||
ok(html.trim() === "1<span class=\"ref\">234</span>",
|
||||
"Undo works for paste adjacent HTML");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* 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 "Use in Console" menu item
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
|
||||
registerCleanupFunction(() => {
|
||||
Services.prefs.clearUserPref("devtools.toolbox.splitconsoleEnabled");
|
||||
});
|
||||
|
||||
// Use the old webconsole since the node isn't being rendered as an HTML tag
|
||||
// in the new one (Bug 1304794)
|
||||
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
|
||||
registerCleanupFunction(function* () {
|
||||
Services.prefs.clearUserPref("devtools.webconsole.new-frontend-enabled");
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox } = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
yield testUseInConsole();
|
||||
|
||||
function* testUseInConsole() {
|
||||
info("Testing 'Use in Console' menu item.");
|
||||
|
||||
yield selectNode("#console-var", inspector);
|
||||
let container = yield getContainerForSelector("#console-var", inspector);
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: container.tagLine,
|
||||
});
|
||||
let menuItem = allMenuItems.find(i => i.id === "node-menu-useinconsole");
|
||||
menuItem.click();
|
||||
|
||||
yield inspector.once("console-var-ready");
|
||||
|
||||
let hud = toolbox.getPanel("webconsole").hud;
|
||||
let jsterm = hud.jsterm;
|
||||
|
||||
let jstermInput = jsterm.hud.document.querySelector(".jsterm-input-node");
|
||||
is(jstermInput.value, "temp0", "first console variable is named temp0");
|
||||
|
||||
let result = yield jsterm.execute();
|
||||
isnot(result.textContent.indexOf('<p id="console-var">'), -1,
|
||||
"variable temp0 references correct node");
|
||||
|
||||
yield selectNode("#console-var-multi", inspector);
|
||||
menuItem.click();
|
||||
yield inspector.once("console-var-ready");
|
||||
|
||||
is(jstermInput.value, "temp1", "second console variable is named temp1");
|
||||
|
||||
result = yield jsterm.execute();
|
||||
isnot(result.textContent.indexOf('<p id="console-var-multi">'), -1,
|
||||
"variable temp1 references correct node");
|
||||
|
||||
jsterm.clearHistory();
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/* 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 attribute items work in the context menu
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
yield selectNode("#attributes", inspector);
|
||||
|
||||
yield testAddAttribute();
|
||||
yield testEditAttribute();
|
||||
yield testRemoveAttribute();
|
||||
|
||||
function* testAddAttribute() {
|
||||
info("Triggering 'Add Attribute' and waiting for mutation to occur");
|
||||
let addAttribute = getMenuItem("node-menu-add-attribute");
|
||||
addAttribute.click();
|
||||
|
||||
EventUtils.synthesizeKey('class="u-hidden"', {});
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
yield onMutation;
|
||||
|
||||
let hasAttribute = testActor.hasNode("#attributes.u-hidden");
|
||||
ok(hasAttribute, "attribute was successfully added");
|
||||
}
|
||||
|
||||
function* testEditAttribute() {
|
||||
info("Testing 'Edit Attribute' menu item");
|
||||
let editAttribute = getMenuItem("node-menu-edit-attribute");
|
||||
|
||||
info("Triggering 'Edit Attribute' and waiting for mutation to occur");
|
||||
inspector.nodeMenuTriggerInfo = {
|
||||
type: "attribute",
|
||||
name: "data-edit"
|
||||
};
|
||||
editAttribute.click();
|
||||
EventUtils.synthesizeKey("data-edit='edited'", {});
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
EventUtils.synthesizeKey("VK_RETURN", {});
|
||||
yield onMutation;
|
||||
|
||||
let isAttributeChanged =
|
||||
yield testActor.hasNode("#attributes[data-edit='edited']");
|
||||
ok(isAttributeChanged, "attribute was successfully edited");
|
||||
}
|
||||
|
||||
function* testRemoveAttribute() {
|
||||
info("Testing 'Remove Attribute' menu item");
|
||||
let removeAttribute = getMenuItem("node-menu-remove-attribute");
|
||||
|
||||
info("Triggering 'Remove Attribute' and waiting for mutation to occur");
|
||||
inspector.nodeMenuTriggerInfo = {
|
||||
type: "attribute",
|
||||
name: "data-remove"
|
||||
};
|
||||
let onMutation = inspector.once("markupmutation");
|
||||
removeAttribute.click();
|
||||
yield onMutation;
|
||||
|
||||
let hasAttribute = yield testActor.hasNode("#attributes[data-remove]");
|
||||
ok(!hasAttribute, "attribute was successfully removed");
|
||||
}
|
||||
|
||||
function getMenuItem(id) {
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector, {
|
||||
target: getContainerForSelector("#attributes", inspector).tagLine,
|
||||
});
|
||||
let menuItem = allMenuItems.find(i => i.id === id);
|
||||
ok(menuItem, "Menu item '" + id + "' found");
|
||||
// Close the menu so synthesizing future keys won't select menu items.
|
||||
EventUtils.synthesizeKey("VK_ESCAPE", {});
|
||||
return menuItem;
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* 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 for menuitem functionality that doesn't fit into any specific category
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_menu.html";
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox, testActor } = yield openInspectorForURL(TEST_URL);
|
||||
yield testShowDOMProperties();
|
||||
yield testDuplicateNode();
|
||||
yield testDeleteNode();
|
||||
yield testDeleteRootNode();
|
||||
yield testScrollIntoView();
|
||||
function* testShowDOMProperties() {
|
||||
info("Testing 'Show DOM Properties' menu item.");
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let showDOMPropertiesNode =
|
||||
allMenuItems.find(item => item.id === "node-menu-showdomproperties");
|
||||
ok(showDOMPropertiesNode, "the popup menu has a show dom properties item");
|
||||
|
||||
let consoleOpened = toolbox.once("webconsole-ready");
|
||||
|
||||
info("Triggering 'Show DOM Properties' and waiting for inspector open");
|
||||
showDOMPropertiesNode.click();
|
||||
yield consoleOpened;
|
||||
|
||||
let webconsoleUI = toolbox.getPanel("webconsole").hud.ui;
|
||||
let messagesAdded = webconsoleUI.once("new-messages");
|
||||
yield messagesAdded;
|
||||
info("Checking if 'inspect($0)' was evaluated");
|
||||
ok(webconsoleUI.jsterm.history[0] === "inspect($0)");
|
||||
yield toolbox.toggleSplitConsole();
|
||||
}
|
||||
function* testDuplicateNode() {
|
||||
info("Testing 'Duplicate Node' menu item for normal elements.");
|
||||
|
||||
yield selectNode(".duplicate", inspector);
|
||||
is((yield testActor.getNumberOfElementMatches(".duplicate")), 1,
|
||||
"There should initially be 1 .duplicate node");
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let menuItem =
|
||||
allMenuItems.find(item => item.id === "node-menu-duplicatenode");
|
||||
ok(menuItem, "'Duplicate node' menu item should exist");
|
||||
|
||||
info("Triggering 'Duplicate Node' and waiting for inspector to update");
|
||||
let updated = inspector.once("markupmutation");
|
||||
menuItem.click();
|
||||
yield updated;
|
||||
|
||||
is((yield testActor.getNumberOfElementMatches(".duplicate")), 2,
|
||||
"The duplicated node should be in the markup.");
|
||||
|
||||
let container = yield getContainerForSelector(".duplicate + .duplicate",
|
||||
inspector);
|
||||
ok(container, "A MarkupContainer should be created for the new node");
|
||||
}
|
||||
|
||||
function* testDeleteNode() {
|
||||
info("Testing 'Delete Node' menu item for normal elements.");
|
||||
yield selectNode("#delete", inspector);
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let deleteNode = allMenuItems.find(item => item.id === "node-menu-delete");
|
||||
ok(deleteNode, "the popup menu has a delete menu item");
|
||||
let updated = inspector.once("inspector-updated");
|
||||
|
||||
info("Triggering 'Delete Node' and waiting for inspector to update");
|
||||
deleteNode.click();
|
||||
yield updated;
|
||||
|
||||
ok(!(yield testActor.hasNode("#delete")), "Node deleted");
|
||||
}
|
||||
|
||||
function* testDeleteRootNode() {
|
||||
info("Testing 'Delete Node' menu item does not delete root node.");
|
||||
yield selectNode("html", inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
let deleteNode = allMenuItems.find(item => item.id === "node-menu-delete");
|
||||
deleteNode.click();
|
||||
|
||||
let deferred = defer();
|
||||
executeSoon(deferred.resolve);
|
||||
yield deferred.promise;
|
||||
|
||||
ok((yield testActor.eval("!!content.document.documentElement")),
|
||||
"Document element still alive.");
|
||||
}
|
||||
|
||||
function* testScrollIntoView() {
|
||||
// Follow up bug to add this test - https://bugzilla.mozilla.org/show_bug.cgi?id=1154107
|
||||
todo(false, "Verify that node is scrolled into the viewport.");
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/* 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 works when navigating to error pages.
|
||||
|
||||
const TEST_URL_1 = "data:text/html,<html><body id=\"test-doc-1\">page</body></html>";
|
||||
const TEST_URL_2 = "http://127.0.0.1:36325/";
|
||||
const TEST_URL_3 = "http://www.wronguri.wronguri/";
|
||||
const TEST_URL_4 = "data:text/html,<html><body>test-doc-4</body></html>";
|
||||
|
||||
add_task(function* () {
|
||||
// Open the inspector on a valid URL
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL_1);
|
||||
|
||||
info("Navigate to closed port");
|
||||
yield navigateTo(inspector, TEST_URL_2);
|
||||
|
||||
let documentURI = yield testActor.eval("document.documentURI;");
|
||||
ok(documentURI.startsWith("about:neterror"), "content is correct.");
|
||||
|
||||
let hasPage = yield getNodeFront("#test-doc-1", inspector);
|
||||
ok(!hasPage, "Inspector actor is no longer able to reach previous page DOM node");
|
||||
|
||||
let hasNetErrorNode = yield getNodeFront("#errorShortDesc", inspector);
|
||||
ok(hasNetErrorNode, "Inspector actor is able to reach error page DOM node");
|
||||
|
||||
let bundle = Services.strings.createBundle("chrome://global/locale/appstrings.properties");
|
||||
let domain = TEST_URL_2.match(/^http:\/\/(.*)\/$/)[1];
|
||||
let errorMsg = bundle.formatStringFromName("connectionFailure",
|
||||
[domain], 1);
|
||||
is(yield getDisplayedNodeTextContent("#errorShortDescText", inspector), errorMsg,
|
||||
"Inpector really inspects the error page");
|
||||
|
||||
info("Navigate to unknown domain");
|
||||
yield navigateTo(inspector, TEST_URL_3);
|
||||
|
||||
domain = TEST_URL_3.match(/^http:\/\/(.*)\/$/)[1];
|
||||
errorMsg = bundle.formatStringFromName("dnsNotFound",
|
||||
[domain], 1);
|
||||
is(yield getDisplayedNodeTextContent("#errorShortDescText", inspector), errorMsg,
|
||||
"Inspector really inspects the new error page");
|
||||
|
||||
info("Navigate to a valid url");
|
||||
yield navigateTo(inspector, TEST_URL_4);
|
||||
|
||||
is(yield getDisplayedNodeTextContent("body", inspector), "test-doc-4",
|
||||
"Inspector really inspects the valid url");
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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 inspector updates when page is navigated.
|
||||
|
||||
const TEST_URL_FILE = "browser/devtools/client/inspector/test/" +
|
||||
"doc_inspector_breadcrumbs.html";
|
||||
|
||||
const TEST_URL_1 = "http://test1.example.org/" + TEST_URL_FILE;
|
||||
const TEST_URL_2 = "http://test2.example.org/" + TEST_URL_FILE;
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URL_1);
|
||||
|
||||
yield selectNode("#i1", inspector);
|
||||
|
||||
info("Navigating to a different page.");
|
||||
yield navigateTo(inspector, TEST_URL_2);
|
||||
|
||||
ok(true, "New page loaded");
|
||||
yield selectNode("#i1", inspector);
|
||||
|
||||
let markuploaded = inspector.once("markuploaded");
|
||||
let onUpdated = inspector.once("inspector-updated");
|
||||
|
||||
info("Going back in history");
|
||||
yield testActor.eval("history.go(-1)");
|
||||
|
||||
info("Waiting for markup view to load after going back in history.");
|
||||
yield markuploaded;
|
||||
|
||||
info("Check that the inspector updates");
|
||||
yield onUpdated;
|
||||
|
||||
ok(true, "Old page loaded");
|
||||
is((yield testActor.eval("location.href;")), TEST_URL_1, "URL is correct.");
|
||||
|
||||
yield selectNode("#i1", inspector);
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/* 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 works correctly when opened against a net error page
|
||||
|
||||
const TEST_URL_1 = "http://127.0.0.1:36325/";
|
||||
const TEST_URL_2 = "data:text/html,<html><body>test-doc-2</body></html>";
|
||||
|
||||
add_task(function* () {
|
||||
// Unfortunately, net error page are not firing load event, so that we can't
|
||||
// use addTab helper and have to do that:
|
||||
let tab = gBrowser.selectedTab = gBrowser.addTab("data:text/html,empty");
|
||||
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
|
||||
yield ContentTask.spawn(tab.linkedBrowser, { url: TEST_URL_1 }, function* ({ url }) {
|
||||
// Also, the neterror being privileged, the DOMContentLoaded only fires on
|
||||
// the chromeEventHandler.
|
||||
let { chromeEventHandler } = docShell; // eslint-disable-line no-undef
|
||||
let onDOMContentLoaded = ContentTaskUtils.waitForEvent(chromeEventHandler,
|
||||
"DOMContentLoaded", true);
|
||||
content.location = url;
|
||||
yield onDOMContentLoaded;
|
||||
});
|
||||
|
||||
let { inspector, testActor } = yield openInspector();
|
||||
ok(true, "Inspector loaded on the already opened net error");
|
||||
|
||||
let documentURI = yield testActor.eval("document.documentURI;");
|
||||
ok(documentURI.startsWith("about:neterror"), "content is really a net error page.");
|
||||
|
||||
info("Navigate to a valid url");
|
||||
yield navigateTo(inspector, TEST_URL_2);
|
||||
|
||||
is(yield getDisplayedNodeTextContent("body", inspector), "test-doc-2",
|
||||
"Inspector really inspects the valid url");
|
||||
});
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the inspector panel has a sidebar pane toggle button, and that
|
||||
// this button is visible both in BOTTOM and SIDE hosts.
|
||||
|
||||
add_task(function* () {
|
||||
info("Open the inspector in a bottom toolbox host");
|
||||
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "bottom");
|
||||
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
ok(button, "The toggle button exists in the DOM");
|
||||
is(button.parentNode.id, "inspector-sidebar-toggle-box",
|
||||
"The toggle button has the right parent");
|
||||
ok(button.getAttribute("title"), "The tool tip has initial state");
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!!button.getClientRects().length, "The button is visible");
|
||||
|
||||
info("Switch the host to side type");
|
||||
yield toolbox.switchHost("side");
|
||||
|
||||
ok(!!button.getClientRects().length, "The button is still visible");
|
||||
ok(!button.classList.contains("pane-collapsed"),
|
||||
"The button is still in expanded state");
|
||||
});
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the inspector toggled panel is visible by default, is hidden after
|
||||
// clicking on the toggle button and remains expanded/collapsed when switching
|
||||
// hosts.
|
||||
|
||||
add_task(function* () {
|
||||
info("Open the inspector in a side toolbox host");
|
||||
let {toolbox, inspector} = yield openInspectorForURL("about:blank", "side");
|
||||
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
|
||||
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
|
||||
info("Listen to the end of the animation on the sidebar panel");
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
ok(!panel.hasAttribute("animated"),
|
||||
"The collapsed panel will not perform unwanted animations");
|
||||
|
||||
info("Switch the host to bottom type");
|
||||
yield toolbox.switchHost("bottom");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
|
||||
info("Click on the toggle button to expand the panel again");
|
||||
|
||||
onTransitionEnd = once(panel, "transitionend");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
yield onTransitionEnd;
|
||||
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
});
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the toggle button can collapse and expand the inspector side/bottom
|
||||
// panel, and that the appropriate attributes are updated in the process.
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL("about:blank");
|
||||
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
|
||||
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
|
||||
info("Listen to the end of the animation on the sidebar panel");
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(button.classList.contains("pane-collapsed"), "The button is in collapsed state");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
|
||||
info("Listen again to the end of the animation on the sidebar panel");
|
||||
onTransitionEnd = once(panel, "transitionend");
|
||||
|
||||
info("Click on the toggle button again");
|
||||
EventUtils.synthesizeMouseAtCenter(button, {},
|
||||
inspector.panelDoc.defaultView);
|
||||
|
||||
yield onTransitionEnd;
|
||||
ok(!button.classList.contains("pane-collapsed"), "The button is in expanded state");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
});
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test the keyboard navigation for the pane toggle using
|
||||
* space and enter
|
||||
*/
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector} = yield openInspectorForURL("about:blank", "side");
|
||||
let panel = inspector.panelDoc.querySelector("#inspector-splitter-box .controlled");
|
||||
|
||||
let button = inspector.panelDoc.querySelector(".sidebar-toggle");
|
||||
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
|
||||
yield togglePane(button, "Press on the toggle button", panel, "VK_RETURN");
|
||||
ok(panel.classList.contains("pane-collapsed"), "The panel is in collapsed state");
|
||||
|
||||
yield togglePane(button, "Press on the toggle button to expand the panel again",
|
||||
panel, "VK_SPACE");
|
||||
ok(!panel.classList.contains("pane-collapsed"), "The panel is in expanded state");
|
||||
});
|
||||
|
||||
function* togglePane(button, message, panel, keycode) {
|
||||
let onTransitionEnd = once(panel, "transitionend");
|
||||
info(message);
|
||||
button.focus();
|
||||
EventUtils.synthesizeKey(keycode, {});
|
||||
yield onTransitionEnd;
|
||||
}
|
||||
|
|
@ -0,0 +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
|
||||
|
||||
const TEST_URI = "data:text/html;charset=utf-8," +
|
||||
"<p>testing the highlighter goes away on destroy</p>";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox } = yield openInspectorForURL(TEST_URI);
|
||||
let pickerStopped = toolbox.once("picker-stopped");
|
||||
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
info("Inspector displayed and ready, starting the picker.");
|
||||
yield startPicker(toolbox);
|
||||
|
||||
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");
|
||||
});
|
||||
|
|
@ -0,0 +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 is stopped when a different tool is
|
||||
// selected
|
||||
|
||||
const TEST_URI = "data:text/html;charset=UTF-8," +
|
||||
"testing the highlighter goes away on tool selection";
|
||||
|
||||
add_task(function* () {
|
||||
let { toolbox } = yield openInspectorForURL(TEST_URI);
|
||||
let pickerStopped = toolbox.once("picker-stopped");
|
||||
|
||||
info("Starting the inspector picker");
|
||||
yield startPicker(toolbox);
|
||||
|
||||
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; picker is closed");
|
||||
});
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/* 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 inspector splitter is properly initialized in horizontal mode if the
|
||||
// inspector starts in portrait mode.
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, toolbox } = yield openInspectorForURL(
|
||||
"data:text/html;charset=utf-8,<h1>foo</h1><span>bar</span>", "window");
|
||||
|
||||
let hostWindow = toolbox.win.parent;
|
||||
let originalWidth = hostWindow.outerWidth;
|
||||
let originalHeight = hostWindow.outerHeight;
|
||||
|
||||
let splitter = inspector.panelDoc.querySelector(".inspector-sidebar-splitter");
|
||||
|
||||
// If the inspector is not already in landscape mode.
|
||||
if (!splitter.classList.contains("vert")) {
|
||||
info("Resize toolbox window to force inspector to landscape mode");
|
||||
let onClassnameMutation = waitForClassMutation(splitter);
|
||||
hostWindow.resizeTo(800, 500);
|
||||
yield onClassnameMutation;
|
||||
|
||||
ok(splitter.classList.contains("vert"), "Splitter is in vertical mode");
|
||||
}
|
||||
|
||||
info("Resize toolbox window to force inspector to portrait mode");
|
||||
let onClassnameMutation = waitForClassMutation(splitter);
|
||||
hostWindow.resizeTo(500, 500);
|
||||
yield onClassnameMutation;
|
||||
|
||||
ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode");
|
||||
|
||||
info("Close the inspector");
|
||||
yield gDevTools.closeToolbox(toolbox.target);
|
||||
|
||||
info("Reopen inspector");
|
||||
({ inspector, toolbox } = yield openInspector("window"));
|
||||
|
||||
// Devtools window should still be 500px * 500px, inspector should still be in portrait.
|
||||
splitter = inspector.panelDoc.querySelector(".inspector-sidebar-splitter");
|
||||
ok(splitter.classList.contains("horz"), "Splitter is in horizontal mode");
|
||||
|
||||
info("Restore original window size");
|
||||
toolbox.win.parent.resizeTo(originalWidth, originalHeight);
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper waiting for a class attribute mutation on the provided target. Returns a
|
||||
* promise.
|
||||
*
|
||||
* @param {Node} target
|
||||
* Node to observe
|
||||
* @return {Promise} promise that will resolve upon receiving a mutation for the class
|
||||
* attribute on the target.
|
||||
*/
|
||||
function waitForClassMutation(target) {
|
||||
return new Promise(resolve => {
|
||||
let observer = new MutationObserver((mutations) => {
|
||||
for (let mutation of mutations) {
|
||||
if (mutation.attributeName === "class") {
|
||||
observer.disconnect();
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
observer.observe(target, { attributes: true });
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
// Restore the host type for other tests.
|
||||
Services.prefs.clearUserPref("devtools.toolbox.host");
|
||||
});
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
/* globals getTestActorWithoutToolbox */
|
||||
"use strict";
|
||||
|
||||
// Test that locking the pseudoclass displays correctly in the ruleview
|
||||
|
||||
const PSEUDO = ":hover";
|
||||
const TEST_URL = "data:text/html;charset=UTF-8," +
|
||||
"<head>" +
|
||||
" <style>div {color:red;} div:hover {color:blue;}</style>" +
|
||||
"</head>" +
|
||||
"<body>" +
|
||||
' <div id="parent-div">' +
|
||||
' <div id="div-1">test div</div>' +
|
||||
' <div id="div-2">test div2</div>' +
|
||||
" </div>" +
|
||||
"</body>";
|
||||
|
||||
add_task(function* () {
|
||||
info("Creating the test tab and opening the rule-view");
|
||||
let {toolbox, inspector, testActor} = yield openInspectorForURL(TEST_URL);
|
||||
|
||||
info("Selecting the ruleview sidebar");
|
||||
inspector.sidebar.select("ruleview");
|
||||
|
||||
let view = inspector.ruleview.view;
|
||||
|
||||
info("Selecting the test node");
|
||||
yield selectNode("#div-1", inspector);
|
||||
|
||||
yield togglePseudoClass(inspector);
|
||||
yield assertPseudoAddedToNode(inspector, testActor, view, "#div-1");
|
||||
|
||||
yield togglePseudoClass(inspector);
|
||||
yield assertPseudoRemovedFromNode(testActor, "#div-1");
|
||||
yield assertPseudoRemovedFromView(inspector, testActor, view, "#div-1");
|
||||
|
||||
yield togglePseudoClass(inspector);
|
||||
yield testNavigate(inspector, testActor, view);
|
||||
|
||||
info("Toggle pseudo on the parent and ensure everything is toggled off");
|
||||
yield selectNode("#parent-div", inspector);
|
||||
yield togglePseudoClass(inspector);
|
||||
yield assertPseudoRemovedFromNode(testActor, "#div-1");
|
||||
yield assertPseudoRemovedFromView(inspector, testActor, view, "#div-1");
|
||||
|
||||
yield togglePseudoClass(inspector);
|
||||
info("Assert pseudo is dismissed when toggling it on a sibling node");
|
||||
yield selectNode("#div-2", inspector);
|
||||
yield togglePseudoClass(inspector);
|
||||
yield assertPseudoAddedToNode(inspector, testActor, view, "#div-2");
|
||||
let hasLock = yield testActor.hasPseudoClassLock("#div-1", PSEUDO);
|
||||
ok(!hasLock, "pseudo-class lock has been removed for the previous locked node");
|
||||
|
||||
info("Destroying the toolbox");
|
||||
let tab = toolbox.target.tab;
|
||||
yield toolbox.destroy();
|
||||
|
||||
// As the toolbox get detroyed, we need to fetch a new test-actor
|
||||
testActor = yield getTestActorWithoutToolbox(tab);
|
||||
|
||||
yield assertPseudoRemovedFromNode(testActor, "#div-1");
|
||||
yield assertPseudoRemovedFromNode(testActor, "#div-2");
|
||||
});
|
||||
|
||||
function* togglePseudoClass(inspector) {
|
||||
info("Toggle the pseudoclass, wait for it to be applied");
|
||||
|
||||
// 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");
|
||||
|
||||
// Walker uses SDK-events so calling walker.once does not return a promise.
|
||||
let onMutations = once(inspector.walker, "mutations");
|
||||
|
||||
yield inspector.togglePseudoClass(PSEUDO);
|
||||
|
||||
yield onPseudo;
|
||||
yield onRefresh;
|
||||
yield onMutations;
|
||||
}
|
||||
|
||||
function* testNavigate(inspector, testActor, ruleview) {
|
||||
yield selectNode("#parent-div", inspector);
|
||||
|
||||
info("Make sure the pseudoclass is still on after navigating to a parent");
|
||||
|
||||
ok((yield testActor.hasPseudoClassLock("#div-1", PSEUDO)),
|
||||
"pseudo-class lock is still applied after inspecting ancestor");
|
||||
|
||||
yield selectNode("#div-2", inspector);
|
||||
|
||||
info("Make sure the pseudoclass is still set after navigating to a " +
|
||||
"non-hierarchy node");
|
||||
ok(yield testActor.hasPseudoClassLock("#div-1", PSEUDO),
|
||||
"pseudo-class lock is still on after inspecting sibling node");
|
||||
|
||||
yield selectNode("#div-1", inspector);
|
||||
}
|
||||
|
||||
function* showPickerOn(selector, inspector) {
|
||||
let nodeFront = yield getNodeFront(selector, inspector);
|
||||
yield inspector.highlighter.showBoxModel(nodeFront);
|
||||
}
|
||||
|
||||
function* assertPseudoAddedToNode(inspector, testActor, ruleview, selector) {
|
||||
info("Make sure the pseudoclass lock is applied to " + selector + " and its ancestors");
|
||||
|
||||
let hasLock = yield testActor.hasPseudoClassLock(selector, PSEUDO);
|
||||
ok(hasLock, "pseudo-class lock has been applied");
|
||||
hasLock = yield testActor.hasPseudoClassLock("#parent-div", PSEUDO);
|
||||
ok(hasLock, "pseudo-class lock has been applied");
|
||||
hasLock = yield testActor.hasPseudoClassLock("body", PSEUDO);
|
||||
ok(hasLock, "pseudo-class lock has been applied");
|
||||
|
||||
info("Check that the ruleview contains the pseudo-class rule");
|
||||
let rules = ruleview.element.querySelectorAll(
|
||||
".ruleview-rule.theme-separator");
|
||||
is(rules.length, 3,
|
||||
"rule view is showing 3 rules for pseudo-class locked div");
|
||||
is(rules[1]._ruleEditor.rule.selectorText, "div:hover",
|
||||
"rule view is showing " + PSEUDO + " rule");
|
||||
|
||||
info("Show the highlighter on " + selector);
|
||||
yield showPickerOn(selector, inspector);
|
||||
|
||||
info("Check that the infobar selector contains the pseudo-class");
|
||||
let value = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-pseudo-classes");
|
||||
is(value, PSEUDO, "pseudo-class in infobar selector");
|
||||
yield inspector.highlighter.hideBoxModel();
|
||||
}
|
||||
|
||||
function* assertPseudoRemovedFromNode(testActor, selector) {
|
||||
info("Make sure the pseudoclass lock is removed from #div-1 and its " +
|
||||
"ancestors");
|
||||
|
||||
let hasLock = yield testActor.hasPseudoClassLock(selector, PSEUDO);
|
||||
ok(!hasLock, "pseudo-class lock has been removed");
|
||||
hasLock = yield testActor.hasPseudoClassLock("#parent-div", PSEUDO);
|
||||
ok(!hasLock, "pseudo-class lock has been removed");
|
||||
hasLock = yield testActor.hasPseudoClassLock("body", PSEUDO);
|
||||
ok(!hasLock, "pseudo-class lock has been removed");
|
||||
}
|
||||
|
||||
function* assertPseudoRemovedFromView(inspector, testActor, ruleview, selector) {
|
||||
info("Check that the ruleview no longer contains the pseudo-class rule");
|
||||
let rules = ruleview.element.querySelectorAll(
|
||||
".ruleview-rule.theme-separator");
|
||||
is(rules.length, 2, "rule view is showing 2 rules after removing lock");
|
||||
|
||||
yield showPickerOn(selector, inspector);
|
||||
|
||||
let value = yield testActor.getHighlighterNodeTextContent(
|
||||
"box-model-infobar-pseudo-classes");
|
||||
is(value, "", "pseudo-class removed from infobar selector");
|
||||
yield inspector.highlighter.hideBoxModel();
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/* 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
|
||||
// that these items actually work
|
||||
|
||||
const TEST_URI = "data:text/html;charset=UTF-8," +
|
||||
"pseudo-class lock node menu tests" +
|
||||
"<div>test div</div>";
|
||||
const PSEUDOS = ["hover", "active", "focus"];
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL(TEST_URI);
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
let allMenuItems = openContextMenuAndGetAllItems(inspector);
|
||||
|
||||
yield testMenuItems(testActor, allMenuItems, inspector);
|
||||
});
|
||||
|
||||
function* testMenuItems(testActor, allMenuItems, inspector) {
|
||||
for (let pseudo of PSEUDOS) {
|
||||
let menuItem =
|
||||
allMenuItems.find(item => item.id === "node-menu-pseudo-" + pseudo);
|
||||
ok(menuItem, ":" + pseudo + " menuitem exists");
|
||||
is(menuItem.disabled, false, ":" + pseudo + " menuitem is enabled");
|
||||
|
||||
// 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");
|
||||
|
||||
// Walker uses SDK-events so calling walker.once does not return a promise.
|
||||
let onMutations = once(inspector.walker, "mutations");
|
||||
|
||||
menuItem.click();
|
||||
|
||||
yield onPseudo;
|
||||
yield onRefresh;
|
||||
yield onMutations;
|
||||
|
||||
let hasLock = yield testActor.hasPseudoClassLock("div", ":" + pseudo);
|
||||
ok(hasLock, "pseudo-class lock has been applied");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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";
|
||||
|
||||
// A test to ensure reloading a page doesn't break the inspector.
|
||||
|
||||
// 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>";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URI);
|
||||
yield selectNode("p", inspector);
|
||||
|
||||
let markupLoaded = inspector.once("markuploaded");
|
||||
|
||||
info("Reloading page.");
|
||||
yield testActor.eval("location.reload()");
|
||||
|
||||
info("Waiting for markupview to load after reload.");
|
||||
yield markupLoaded;
|
||||
|
||||
let nodeFront = yield getNodeFront("p", inspector);
|
||||
is(inspector.selection.nodeFront, nodeFront, "<p> selected after reload.");
|
||||
|
||||
info("Selecting a node to see that inspector still works.");
|
||||
yield selectNode("body", inspector);
|
||||
});
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* 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";
|
||||
|
||||
// A test to ensure reloading a page doesn't break the inspector.
|
||||
|
||||
// Reload should reselect the currently selected markup view element.
|
||||
// This should work even when an element whose selector is inaccessible
|
||||
// is selected (bug 1038651).
|
||||
const TEST_URI = 'data:text/xml,<?xml version="1.0" standalone="no"?>' +
|
||||
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"' +
|
||||
' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' +
|
||||
'<svg width="4cm" height="4cm" viewBox="0 0 400 400"' +
|
||||
' xmlns="http://www.w3.org/2000/svg" version="1.1">' +
|
||||
" <title>Example triangle01- simple example of a path</title>" +
|
||||
" <desc>A path that draws a triangle</desc>" +
|
||||
' <rect x="1" y="1" width="398" height="398"' +
|
||||
' fill="none" stroke="blue" />' +
|
||||
' <path d="M 100 100 L 300 100 L 200 300 z"' +
|
||||
' fill="red" stroke="blue" stroke-width="3" />' +
|
||||
"</svg>";
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector, testActor } = yield openInspectorForURL(TEST_URI);
|
||||
|
||||
let markupLoaded = inspector.once("markuploaded");
|
||||
|
||||
info("Reloading page.");
|
||||
yield testActor.eval("location.reload()");
|
||||
|
||||
info("Waiting for markupview to load after reload.");
|
||||
yield markupLoaded;
|
||||
|
||||
let svgFront = yield getNodeFront("svg", inspector);
|
||||
is(inspector.selection.nodeFront, svgFront, "<svg> selected after reload.");
|
||||
|
||||
info("Selecting a node to see that inspector still works.");
|
||||
yield selectNode("rect", inspector);
|
||||
|
||||
info("Reloading page.");
|
||||
yield testActor.eval("location.reload");
|
||||
|
||||
let rectFront = yield getNodeFront("rect", inspector);
|
||||
is(inspector.selection.nodeFront, rectFront, "<rect> selected after reload.");
|
||||
});
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* 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";
|
||||
|
||||
// Testing that the inspector doesn't go blank when navigating to a page that
|
||||
// deletes an iframe while loading.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_remove-iframe-during-load.html";
|
||||
|
||||
add_task(function* () {
|
||||
let {inspector, testActor} = yield openInspectorForURL("about:blank");
|
||||
yield selectNode("body", inspector);
|
||||
|
||||
// We do not want to wait for the inspector to be fully ready before testing
|
||||
// so we load TEST_URL and just wait for the content window to be done loading
|
||||
yield testActor.loadAndWaitForCustomEvent(TEST_URL);
|
||||
|
||||
// The content doc contains a script that creates iframes and deletes them
|
||||
// immediately after. It does this before the load event, after
|
||||
// DOMContentLoaded and after load. This is what used to make the inspector go
|
||||
// blank when navigating to that page.
|
||||
// At this stage, there should be no iframes in the page anymore.
|
||||
ok(!(yield testActor.hasNode("iframe")),
|
||||
"Iframes added by the content page should have been removed");
|
||||
|
||||
// Create/remove an extra one now, after the load event.
|
||||
info("Creating and removing an iframe.");
|
||||
let onMarkupLoaded = inspector.once("markuploaded");
|
||||
testActor.eval("new " + function () {
|
||||
let iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.remove();
|
||||
});
|
||||
|
||||
ok(!(yield testActor.hasNode("iframe")),
|
||||
"The after-load iframe should have been removed.");
|
||||
|
||||
info("Waiting for markup-view to load.");
|
||||
yield onMarkupLoaded;
|
||||
|
||||
// Assert that the markup-view is displayed and works
|
||||
ok(!(yield testActor.hasNode("iframe")), "Iframe has been removed.");
|
||||
is((yield testActor.getProperty("#yay", "textContent")), "load",
|
||||
"Load event fired.");
|
||||
|
||||
yield selectNode("#yay", inspector);
|
||||
});
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/* 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/ */
|
||||
/* eslint no-inline-comments: 0 */
|
||||
"use strict";
|
||||
|
||||
requestLongerTimeout(2);
|
||||
|
||||
// Test that searching for nodes in the search field actually selects those
|
||||
// nodes.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_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 = [
|
||||
["#", "b1", true], // #
|
||||
["d", "b1", true], // #d
|
||||
["1", "b1", true], // #d1
|
||||
["VK_RETURN", "d1", true], // #d1
|
||||
["VK_BACK_SPACE", "d1", true], // #d
|
||||
["2", "d1", true], // #d2
|
||||
["VK_RETURN", "d2", true], // #d2
|
||||
["2", "d2", true], // #d22
|
||||
["VK_RETURN", "d2", false], // #d22
|
||||
["VK_BACK_SPACE", "d2", false], // #d2
|
||||
["VK_RETURN", "d2", true], // #d2
|
||||
["VK_BACK_SPACE", "d2", true], // #d
|
||||
["1", "d2", true], // #d1
|
||||
["VK_RETURN", "d1", true], // #d1
|
||||
["VK_BACK_SPACE", "d1", true], // #d
|
||||
["VK_BACK_SPACE", "d1", true], // #
|
||||
["VK_BACK_SPACE", "d1", true], //
|
||||
["d", "d1", true], // d
|
||||
["i", "d1", true], // di
|
||||
["v", "d1", true], // div
|
||||
[".", "d1", true], // div.
|
||||
["c", "d1", true], // div.c
|
||||
["VK_UP", "d1", true], // div.c1
|
||||
["VK_TAB", "d1", true], // div.c1
|
||||
["VK_RETURN", "d2", true], // div.c1
|
||||
["VK_BACK_SPACE", "d2", true], // div.c
|
||||
["VK_BACK_SPACE", "d2", true], // div.
|
||||
["VK_BACK_SPACE", "d2", true], // div
|
||||
["VK_BACK_SPACE", "d2", true], // di
|
||||
["VK_BACK_SPACE", "d2", true], // d
|
||||
["VK_BACK_SPACE", "d2", true], //
|
||||
[".", "d2", true], // .
|
||||
["c", "d2", true], // .c
|
||||
["1", "d2", true], // .c1
|
||||
["VK_RETURN", "d2", true], // .c1
|
||||
["VK_RETURN", "s2", true], // .c1
|
||||
["VK_RETURN", "p1", true], // .c1
|
||||
["P", "p1", true], // .c1P
|
||||
["VK_RETURN", "p1", false], // .c1P
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
let { searchBox } = inspector;
|
||||
|
||||
yield selectNode("#b1", inspector);
|
||||
yield focusSearchBoxUsingShortcut(inspector.panelWin);
|
||||
|
||||
let index = 0;
|
||||
for (let [ key, id, isValid ] of KEY_STATES) {
|
||||
info(index + ": Pressing key " + key + " to get id " + id + ".");
|
||||
let done = inspector.searchSuggestions.once("processing-done");
|
||||
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
|
||||
yield done;
|
||||
info("Got processing-done event");
|
||||
|
||||
if (key === "VK_RETURN") {
|
||||
info("Waiting for " + (isValid ? "NO " : "") + "results");
|
||||
yield inspector.search.once("search-result");
|
||||
}
|
||||
|
||||
info("Waiting for search query to complete");
|
||||
yield inspector.searchSuggestions._lastQuery;
|
||||
|
||||
info(inspector.selection.nodeFront.id + " is selected with text " +
|
||||
searchBox.value);
|
||||
let nodeFront = yield getNodeFront("#" + id, inspector);
|
||||
is(inspector.selection.nodeFront, nodeFront,
|
||||
"Correct node is selected for state " + index);
|
||||
|
||||
is(!searchBox.classList.contains("devtools-style-searchbox-no-match"), isValid,
|
||||
"Correct searchbox result state for state " + index);
|
||||
|
||||
index++;
|
||||
}
|
||||
});
|
||||
169
devtools/client/inspector/test/browser_inspector_search-02.js
Normal file
169
devtools/client/inspector/test/browser_inspector_search-02.js
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/* 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";
|
||||
|
||||
// Testing that searching for combining selectors using the inspector search
|
||||
// field produces correct suggestions.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_search-suggestions.html";
|
||||
|
||||
// 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 = [
|
||||
{
|
||||
key: "d",
|
||||
suggestions: [
|
||||
{label: "div"},
|
||||
{label: "#d1"},
|
||||
{label: "#d2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "i",
|
||||
suggestions: [{label: "div"}]
|
||||
},
|
||||
{
|
||||
key: "v",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: " ",
|
||||
suggestions: [
|
||||
{label: "div div"},
|
||||
{label: "div span"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: ">",
|
||||
suggestions: [
|
||||
{label: "div >div"},
|
||||
{label: "div >span"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: "div div"},
|
||||
{label: "div span"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "+",
|
||||
suggestions: [{label: "div +span"}]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: "div div"},
|
||||
{label: "div span"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [{label: "div"}]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: "div"},
|
||||
{label: "#d1"},
|
||||
{label: "#d2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: "p",
|
||||
suggestions: [
|
||||
{label: "p"},
|
||||
{label: "#p1"},
|
||||
{label: "#p2"},
|
||||
{label: "#p3"},
|
||||
]
|
||||
},
|
||||
{
|
||||
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"}]
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
let searchBox = inspector.searchBox;
|
||||
let popup = inspector.searchSuggestions.searchPopup;
|
||||
|
||||
yield focusSearchBoxUsingShortcut(inspector.panelWin);
|
||||
|
||||
for (let { key, suggestions } of TEST_DATA) {
|
||||
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
|
||||
|
||||
let command = once(searchBox, "input");
|
||||
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
|
||||
yield command;
|
||||
|
||||
info("Waiting for search query to complete");
|
||||
yield inspector.searchSuggestions._lastQuery;
|
||||
|
||||
info("Query completed. Performing checks for input '" + searchBox.value +
|
||||
"' - key pressed: " + key);
|
||||
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(actualSuggestions[i].label, suggestions[i].label,
|
||||
"The suggestion at " + i + "th index is correct.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function formatSuggestions(suggestions) {
|
||||
return "[" + suggestions
|
||||
.map(s => "'" + s.label + "'")
|
||||
.join(", ") + "]";
|
||||
}
|
||||
250
devtools/client/inspector/test/browser_inspector_search-03.js
Normal file
250
devtools/client/inspector/test/browser_inspector_search-03.js
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/* 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";
|
||||
|
||||
// Testing that searching for elements using the inspector search field
|
||||
// produces correct suggestions.
|
||||
|
||||
const TEST_URL = URL_ROOT + "doc_inspector_search.html";
|
||||
|
||||
// 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)
|
||||
var TEST_DATA = [
|
||||
{
|
||||
key: "d",
|
||||
suggestions: [
|
||||
{label: "div"},
|
||||
{label: "#d1"},
|
||||
{label: "#d2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "i",
|
||||
suggestions: [{label: "div"}]
|
||||
},
|
||||
{
|
||||
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"}]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: "div"},
|
||||
{label: "#d1"},
|
||||
{label: "#d2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: ".",
|
||||
suggestions: [
|
||||
{label: ".c1"},
|
||||
{label: ".c2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "c",
|
||||
suggestions: [
|
||||
{label: ".c1"},
|
||||
{label: ".c2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: ".c1"},
|
||||
{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"},
|
||||
{label: ".c2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: [
|
||||
{label: ".c1"},
|
||||
{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: []
|
||||
},
|
||||
{
|
||||
key: "p",
|
||||
suggestions: [
|
||||
{label: "p"},
|
||||
{label: "#p1"},
|
||||
{label: "#p2"},
|
||||
{label: "#p3"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "[", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "i", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "d", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "*", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "=", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "p", suggestions: []
|
||||
},
|
||||
{
|
||||
key: "]", suggestions: []
|
||||
},
|
||||
{
|
||||
key: ".",
|
||||
suggestions: [
|
||||
{label: "p[id*=p].c1"},
|
||||
{label: "p[id*=p].c2"}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: "VK_BACK_SPACE",
|
||||
suggestions: []
|
||||
},
|
||||
{
|
||||
key: "#",
|
||||
suggestions: [
|
||||
{label: "p[id*=p]#p1"},
|
||||
{label: "p[id*=p]#p2"},
|
||||
{label: "p[id*=p]#p3"}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
let { inspector } = yield openInspectorForURL(TEST_URL);
|
||||
let searchBox = inspector.searchBox;
|
||||
let popup = inspector.searchSuggestions.searchPopup;
|
||||
|
||||
yield focusSearchBoxUsingShortcut(inspector.panelWin);
|
||||
|
||||
for (let { key, suggestions } of TEST_DATA) {
|
||||
info("Pressing " + key + " to get " + formatSuggestions(suggestions));
|
||||
|
||||
let command = once(searchBox, "input");
|
||||
EventUtils.synthesizeKey(key, {}, inspector.panelWin);
|
||||
yield command;
|
||||
|
||||
info("Waiting for search query to complete");
|
||||
yield inspector.searchSuggestions._lastQuery;
|
||||
|
||||
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(actualSuggestions[i].label, suggestions[i].label,
|
||||
"The suggestion at " + i + "th index is correct.");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function formatSuggestions(suggestions) {
|
||||
return "[" + suggestions
|
||||
.map(s => "'" + s.label + "'")
|
||||
.join(", ") + "]";
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue