From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- devtools/client/inspector/test/.eslintrc.js | 6 + devtools/client/inspector/test/browser.ini | 172 +++++ .../inspector/test/browser_inspector_addNode_01.js | 22 + .../inspector/test/browser_inspector_addNode_02.js | 63 ++ .../inspector/test/browser_inspector_addNode_03.js | 84 +++ .../test/browser_inspector_addSidebarTab.js | 62 ++ .../test/browser_inspector_breadcrumbs.js | 132 ++++ ...rowser_inspector_breadcrumbs_highlight_hover.js | 47 ++ .../browser_inspector_breadcrumbs_keybinding.js | 71 ++ .../browser_inspector_breadcrumbs_keyboard_trap.js | 83 +++ .../browser_inspector_breadcrumbs_mutations.js | 212 ++++++ .../browser_inspector_breadcrumbs_namespaced.js | 55 ++ .../browser_inspector_breadcrumbs_visibility.js | 110 ++++ .../browser_inspector_delete-selected-node-01.js | 24 + .../browser_inspector_delete-selected-node-02.js | 154 +++++ .../browser_inspector_delete-selected-node-03.js | 27 + .../browser_inspector_destroy-after-navigation.js | 24 + .../test/browser_inspector_destroy-before-ready.js | 26 + .../test/browser_inspector_expand-collapse.js | 64 ++ .../test/browser_inspector_gcli-inspect-command.js | 118 ++++ .../test/browser_inspector_highlighter-01.js | 31 + .../test/browser_inspector_highlighter-02.js | 39 ++ .../test/browser_inspector_highlighter-03.js | 70 ++ .../test/browser_inspector_highlighter-04.js | 43 ++ .../test/browser_inspector_highlighter-by-type.js | 66 ++ .../test/browser_inspector_highlighter-cancel.js | 52 ++ .../test/browser_inspector_highlighter-comments.js | 105 +++ .../browser_inspector_highlighter-cssgrid_01.js | 77 +++ ...rowser_inspector_highlighter-csstransform_01.js | 152 +++++ ...rowser_inspector_highlighter-csstransform_02.js | 56 ++ .../test/browser_inspector_highlighter-embed.js | 30 + ...r_inspector_highlighter-eyedropper-clipboard.js | 39 ++ ...browser_inspector_highlighter-eyedropper-csp.js | 30 + ...wser_inspector_highlighter-eyedropper-events.js | 141 ++++ ...owser_inspector_highlighter-eyedropper-label.js | 115 ++++ ...r_inspector_highlighter-eyedropper-show-hide.js | 42 ++ ...browser_inspector_highlighter-eyedropper-xul.js | 64 ++ .../browser_inspector_highlighter-geometry_01.js | 89 +++ .../browser_inspector_highlighter-geometry_02.js | 116 ++++ .../browser_inspector_highlighter-geometry_03.js | 61 ++ .../browser_inspector_highlighter-geometry_04.js | 85 +++ .../browser_inspector_highlighter-geometry_05.js | 119 ++++ .../browser_inspector_highlighter-geometry_06.js | 166 +++++ .../test/browser_inspector_highlighter-hover_01.js | 41 ++ .../test/browser_inspector_highlighter-hover_02.js | 38 ++ .../test/browser_inspector_highlighter-hover_03.js | 55 ++ .../browser_inspector_highlighter-iframes_01.js | 64 ++ .../browser_inspector_highlighter-iframes_02.js | 59 ++ .../test/browser_inspector_highlighter-inline.js | 76 +++ .../browser_inspector_highlighter-keybinding_01.js | 64 ++ .../browser_inspector_highlighter-keybinding_02.js | 64 ++ .../browser_inspector_highlighter-keybinding_03.js | 71 ++ .../browser_inspector_highlighter-keybinding_04.js | 46 ++ .../browser_inspector_highlighter-measure_01.js | 88 +++ .../browser_inspector_highlighter-measure_02.js | 130 ++++ .../test/browser_inspector_highlighter-options.js | 204 ++++++ .../test/browser_inspector_highlighter-preview.js | 56 ++ .../test/browser_inspector_highlighter-rect_01.js | 121 ++++ .../test/browser_inspector_highlighter-rect_02.js | 37 ++ .../browser_inspector_highlighter-rulers_01.js | 76 +++ .../browser_inspector_highlighter-rulers_02.js | 103 +++ .../browser_inspector_highlighter-selector_01.js | 63 ++ .../browser_inspector_highlighter-selector_02.js | 61 ++ .../test/browser_inspector_highlighter-xbl.js | 39 ++ .../test/browser_inspector_highlighter-zoom.js | 72 ++ .../test/browser_inspector_iframe-navigation.js | 43 ++ .../inspector/test/browser_inspector_infobar_01.js | 89 +++ .../inspector/test/browser_inspector_infobar_02.js | 50 ++ .../inspector/test/browser_inspector_infobar_03.js | 41 ++ .../test/browser_inspector_infobar_textnode.js | 46 ++ .../test/browser_inspector_initialization.js | 112 ++++ .../browser_inspector_inspect-object-element.js | 18 + .../inspector/test/browser_inspector_invalidate.js | 35 + ..._inspector_keyboard-shortcuts-copy-outerhtml.js | 52 ++ .../test/browser_inspector_keyboard-shortcuts.js | 48 ++ .../test/browser_inspector_menu-01-sensitivity.js | 278 ++++++++ .../test/browser_inspector_menu-02-copy-items.js | 49 ++ .../browser_inspector_menu-03-paste-items-svg.js | 42 ++ .../test/browser_inspector_menu-03-paste-items.js | 128 ++++ .../browser_inspector_menu-04-use-in-console.js | 61 ++ .../browser_inspector_menu-05-attribute-items.js | 79 +++ .../test/browser_inspector_menu-06-other.js | 95 +++ .../test/browser_inspector_navigate_to_errors.js | 50 ++ .../inspector/test/browser_inspector_navigation.js | 43 ++ .../test/browser_inspector_open_on_neterror.js | 37 ++ .../test/browser_inspector_pane-toggle-01.js | 27 + .../test/browser_inspector_pane-toggle-02.js | 43 ++ .../test/browser_inspector_pane-toggle-03.js | 38 ++ .../test/browser_inspector_pane-toggle-05.js | 33 + .../browser_inspector_picker-stop-on-destroy.js | 30 + ...browser_inspector_picker-stop-on-tool-change.js | 27 + .../test/browser_inspector_portrait_mode.js | 78 +++ .../test/browser_inspector_pseudoclass-lock.js | 160 +++++ .../test/browser_inspector_pseudoclass-menu.js | 46 ++ .../inspector/test/browser_inspector_reload-01.js | 32 + .../inspector/test/browser_inspector_reload-02.js | 48 ++ .../browser_inspector_remove-iframe-during-load.js | 48 ++ .../inspector/test/browser_inspector_search-01.js | 96 +++ .../inspector/test/browser_inspector_search-02.js | 169 +++++ .../inspector/test/browser_inspector_search-03.js | 250 +++++++ .../inspector/test/browser_inspector_search-04.js | 112 ++++ .../inspector/test/browser_inspector_search-05.js | 93 +++ .../inspector/test/browser_inspector_search-06.js | 87 +++ .../inspector/test/browser_inspector_search-07.js | 49 ++ .../inspector/test/browser_inspector_search-08.js | 64 ++ .../test/browser_inspector_search-clear.js | 52 ++ ...browser_inspector_search-filter_context-menu.js | 82 +++ .../test/browser_inspector_search-label.js | 33 + .../test/browser_inspector_search-navigation.js | 76 +++ .../test/browser_inspector_search-reserved.js | 132 ++++ .../test/browser_inspector_search-selection.js | 62 ++ .../test/browser_inspector_search-sidebar.js | 74 +++ ...er_inspector_search-suggests-ids-and-classes.js | 84 +++ .../test/browser_inspector_search_keyboard_trap.js | 94 +++ .../test/browser_inspector_select-docshell.js | 86 +++ .../test/browser_inspector_select-last-selected.js | 95 +++ .../test/browser_inspector_sidebarstate.js | 38 ++ ...rowser_inspector_switch-to-inspector-on-pick.js | 39 ++ .../test/browser_inspector_textbox-menu.js | 90 +++ .../inspector/test/doc_inspector_add_node.html | 22 + .../inspector/test/doc_inspector_breadcrumbs.html | 75 +++ .../test/doc_inspector_breadcrumbs_visibility.html | 22 + .../client/inspector/test/doc_inspector_csp.html | 10 + .../inspector/test/doc_inspector_csp.html^headers^ | 2 + .../doc_inspector_delete-selected-node-01.html | 4 + .../doc_inspector_delete-selected-node-02.html | 20 + .../client/inspector/test/doc_inspector_embed.html | 6 + .../test/doc_inspector_gcli-inspect-command.html | 25 + .../doc_inspector_highlight_after_transition.html | 26 + .../test/doc_inspector_highlighter-comments.html | 19 + .../doc_inspector_highlighter-geometry_01.html | 90 +++ .../doc_inspector_highlighter-geometry_02.html | 120 ++++ .../inspector/test/doc_inspector_highlighter.html | 40 ++ .../doc_inspector_highlighter_csstransform.html | 25 + .../test/doc_inspector_highlighter_dom.html | 20 + .../test/doc_inspector_highlighter_inline.html | 36 + .../test/doc_inspector_highlighter_rect.html | 22 + .../doc_inspector_highlighter_rect_iframe.html | 15 + .../test/doc_inspector_highlighter_xbl.xul | 9 + .../inspector/test/doc_inspector_infobar.html | 43 ++ .../inspector/test/doc_inspector_infobar_01.html | 44 ++ .../inspector/test/doc_inspector_infobar_02.html | 34 + .../inspector/test/doc_inspector_infobar_03.html | 14 + .../test/doc_inspector_infobar_textnode.html | 14 + .../inspector/test/doc_inspector_long-divs.html | 104 +++ .../client/inspector/test/doc_inspector_menu.html | 29 + .../inspector/test/doc_inspector_outerhtml.html | 11 + .../doc_inspector_remove-iframe-during-load.html | 45 ++ .../test/doc_inspector_search-reserved.html | 11 + .../test/doc_inspector_search-suggestions.html | 27 + .../inspector/test/doc_inspector_search-svg.html | 16 + .../inspector/test/doc_inspector_search.html | 26 + .../doc_inspector_select-last-selected-01.html | 21 + .../doc_inspector_select-last-selected-02.html | 10 + .../client/inspector/test/doc_inspector_svg.svg | 3 + devtools/client/inspector/test/head.js | 732 +++++++++++++++++++++ devtools/client/inspector/test/shared-head.js | 186 ++++++ 157 files changed, 10913 insertions(+) create mode 100644 devtools/client/inspector/test/.eslintrc.js create mode 100644 devtools/client/inspector/test/browser.ini create mode 100644 devtools/client/inspector/test/browser_inspector_addNode_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_addNode_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_addNode_03.js create mode 100644 devtools/client/inspector/test/browser_inspector_addSidebarTab.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_highlight_hover.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_keybinding.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_keyboard_trap.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_mutations.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js create mode 100644 devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js create mode 100644 devtools/client/inspector/test/browser_inspector_delete-selected-node-01.js create mode 100644 devtools/client/inspector/test/browser_inspector_delete-selected-node-02.js create mode 100644 devtools/client/inspector/test/browser_inspector_delete-selected-node-03.js create mode 100644 devtools/client/inspector/test/browser_inspector_destroy-after-navigation.js create mode 100644 devtools/client/inspector/test/browser_inspector_destroy-before-ready.js create mode 100644 devtools/client/inspector/test/browser_inspector_expand-collapse.js create mode 100644 devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-03.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-04.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-by-type.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-cancel.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-comments.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-cssgrid_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-csstransform_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-csstransform_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-embed.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-clipboard.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-csp.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-events.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-label.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-show-hide.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-eyedropper-xul.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_03.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_04.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_05.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-geometry_06.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-hover_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-hover_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-hover_03.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-iframes_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-iframes_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-inline.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-keybinding_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-keybinding_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-keybinding_03.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-keybinding_04.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-measure_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-measure_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-options.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-preview.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-rect_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-rect_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-rulers_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-rulers_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-selector_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-selector_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-xbl.js create mode 100644 devtools/client/inspector/test/browser_inspector_highlighter-zoom.js create mode 100644 devtools/client/inspector/test/browser_inspector_iframe-navigation.js create mode 100644 devtools/client/inspector/test/browser_inspector_infobar_01.js create mode 100644 devtools/client/inspector/test/browser_inspector_infobar_02.js create mode 100644 devtools/client/inspector/test/browser_inspector_infobar_03.js create mode 100644 devtools/client/inspector/test/browser_inspector_infobar_textnode.js create mode 100644 devtools/client/inspector/test/browser_inspector_initialization.js create mode 100644 devtools/client/inspector/test/browser_inspector_inspect-object-element.js create mode 100644 devtools/client/inspector/test/browser_inspector_invalidate.js create mode 100644 devtools/client/inspector/test/browser_inspector_keyboard-shortcuts-copy-outerhtml.js create mode 100644 devtools/client/inspector/test/browser_inspector_keyboard-shortcuts.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-01-sensitivity.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-02-copy-items.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-03-paste-items-svg.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-03-paste-items.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-04-use-in-console.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-05-attribute-items.js create mode 100644 devtools/client/inspector/test/browser_inspector_menu-06-other.js create mode 100644 devtools/client/inspector/test/browser_inspector_navigate_to_errors.js create mode 100644 devtools/client/inspector/test/browser_inspector_navigation.js create mode 100644 devtools/client/inspector/test/browser_inspector_open_on_neterror.js create mode 100644 devtools/client/inspector/test/browser_inspector_pane-toggle-01.js create mode 100644 devtools/client/inspector/test/browser_inspector_pane-toggle-02.js create mode 100644 devtools/client/inspector/test/browser_inspector_pane-toggle-03.js create mode 100644 devtools/client/inspector/test/browser_inspector_pane-toggle-05.js create mode 100644 devtools/client/inspector/test/browser_inspector_picker-stop-on-destroy.js create mode 100644 devtools/client/inspector/test/browser_inspector_picker-stop-on-tool-change.js create mode 100644 devtools/client/inspector/test/browser_inspector_portrait_mode.js create mode 100644 devtools/client/inspector/test/browser_inspector_pseudoclass-lock.js create mode 100644 devtools/client/inspector/test/browser_inspector_pseudoclass-menu.js create mode 100644 devtools/client/inspector/test/browser_inspector_reload-01.js create mode 100644 devtools/client/inspector/test/browser_inspector_reload-02.js create mode 100644 devtools/client/inspector/test/browser_inspector_remove-iframe-during-load.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-01.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-02.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-03.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-04.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-05.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-06.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-07.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-08.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-clear.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-filter_context-menu.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-label.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-navigation.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-reserved.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-selection.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-sidebar.js create mode 100644 devtools/client/inspector/test/browser_inspector_search-suggests-ids-and-classes.js create mode 100644 devtools/client/inspector/test/browser_inspector_search_keyboard_trap.js create mode 100644 devtools/client/inspector/test/browser_inspector_select-docshell.js create mode 100644 devtools/client/inspector/test/browser_inspector_select-last-selected.js create mode 100644 devtools/client/inspector/test/browser_inspector_sidebarstate.js create mode 100644 devtools/client/inspector/test/browser_inspector_switch-to-inspector-on-pick.js create mode 100644 devtools/client/inspector/test/browser_inspector_textbox-menu.js create mode 100644 devtools/client/inspector/test/doc_inspector_add_node.html create mode 100644 devtools/client/inspector/test/doc_inspector_breadcrumbs.html create mode 100644 devtools/client/inspector/test/doc_inspector_breadcrumbs_visibility.html create mode 100644 devtools/client/inspector/test/doc_inspector_csp.html create mode 100644 devtools/client/inspector/test/doc_inspector_csp.html^headers^ create mode 100644 devtools/client/inspector/test/doc_inspector_delete-selected-node-01.html create mode 100644 devtools/client/inspector/test/doc_inspector_delete-selected-node-02.html create mode 100644 devtools/client/inspector/test/doc_inspector_embed.html create mode 100644 devtools/client/inspector/test/doc_inspector_gcli-inspect-command.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlight_after_transition.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter-comments.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter-geometry_02.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_csstransform.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_dom.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_inline.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_rect.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_rect_iframe.html create mode 100644 devtools/client/inspector/test/doc_inspector_highlighter_xbl.xul create mode 100644 devtools/client/inspector/test/doc_inspector_infobar.html create mode 100644 devtools/client/inspector/test/doc_inspector_infobar_01.html create mode 100644 devtools/client/inspector/test/doc_inspector_infobar_02.html create mode 100644 devtools/client/inspector/test/doc_inspector_infobar_03.html create mode 100644 devtools/client/inspector/test/doc_inspector_infobar_textnode.html create mode 100644 devtools/client/inspector/test/doc_inspector_long-divs.html create mode 100644 devtools/client/inspector/test/doc_inspector_menu.html create mode 100644 devtools/client/inspector/test/doc_inspector_outerhtml.html create mode 100644 devtools/client/inspector/test/doc_inspector_remove-iframe-during-load.html create mode 100644 devtools/client/inspector/test/doc_inspector_search-reserved.html create mode 100644 devtools/client/inspector/test/doc_inspector_search-suggestions.html create mode 100644 devtools/client/inspector/test/doc_inspector_search-svg.html create mode 100644 devtools/client/inspector/test/doc_inspector_search.html create mode 100644 devtools/client/inspector/test/doc_inspector_select-last-selected-01.html create mode 100644 devtools/client/inspector/test/doc_inspector_select-last-selected-02.html create mode 100644 devtools/client/inspector/test/doc_inspector_svg.svg create mode 100644 devtools/client/inspector/test/head.js create mode 100644 devtools/client/inspector/test/shared-head.js (limited to 'devtools/client/inspector/test') diff --git a/devtools/client/inspector/test/.eslintrc.js b/devtools/client/inspector/test/.eslintrc.js new file mode 100644 index 000000000..8d15a76d9 --- /dev/null +++ b/devtools/client/inspector/test/.eslintrc.js @@ -0,0 +1,6 @@ +"use strict"; + +module.exports = { + // Extend from the shared list of defined globals for mochitests. + "extends": "../../../.eslintrc.mochitests.js" +}; diff --git a/devtools/client/inspector/test/browser.ini b/devtools/client/inspector/test/browser.ini new file mode 100644 index 000000000..65ad71c0c --- /dev/null +++ b/devtools/client/inspector/test/browser.ini @@ -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] diff --git a/devtools/client/inspector/test/browser_inspector_addNode_01.js b/devtools/client/inspector/test/browser_inspector_addNode_01.js new file mode 100644 index 000000000..f90cb6c5c --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_addNode_01.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,

Add node

"; + +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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_addNode_02.js b/devtools/client/inspector/test/browser_inspector_addNode_02.js new file mode 100644 index 000000000..2421f9df3 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_addNode_02.js @@ -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); +} diff --git a/devtools/client/inspector/test/browser_inspector_addNode_03.js b/devtools/client/inspector/test/browser_inspector_addNode_03.js new file mode 100644 index 000000000..38a8369ec --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_addNode_03.js @@ -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); +} diff --git a/devtools/client/inspector/test/browser_inspector_addSidebarTab.js b/devtools/client/inspector/test/browser_inspector_addSidebarTab.js new file mode 100644 index 000000000..77dc2632e --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_addSidebarTab.js @@ -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," + + "

browser_inspector_addtabbar.js

"; + +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."); +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs.js new file mode 100644 index 000000000..e5befff9e --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs.js @@ -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"); +} diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_highlight_hover.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_highlight_hover.js new file mode 100644 index 000000000..6714ea35e --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_highlight_hover.js @@ -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,

foo

bar"); + 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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_keybinding.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_keybinding.js new file mode 100644 index 000000000..8e72a8bab --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_keybinding.js @@ -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 ", + key: "VK_LEFT", + newSelection: "body" +}, { + desc: "Pressing left again should select the parent ", + key: "VK_LEFT", + newSelection: "html" +}, { + desc: "Pressing left again should stay on , it's the first element", + key: "VK_LEFT", + newSelection: "html" +}, { + desc: "Pressing right should go to ", + 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; + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_keyboard_trap.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_keyboard_trap.js new file mode 100644 index 000000000..16c70650b --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_keyboard_trap.js @@ -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"); + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_mutations.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_mutations.js new file mode 100644 index 000000000..100ee275a --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_mutations.js @@ -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, "test"); + }, + 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"); + } + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js new file mode 100644 index 000000000..0b14ef1b0 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_namespaced.js @@ -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 = ` + + + + + + + + + + + +`; + +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"); + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js new file mode 100644 index 000000000..caee745c9 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js @@ -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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_delete-selected-node-01.js b/devtools/client/inspector/test/browser_inspector_delete-selected-node-01.js new file mode 100644 index 000000000..3b5049e25 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_delete-selected-node-01.js @@ -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 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 got selected."); +}); diff --git a/devtools/client/inspector/test/browser_inspector_delete-selected-node-02.js b/devtools/client/inspector/test/browser_inspector_delete-selected-node-02.js new file mode 100644 index 000000000..fbd008a89 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_delete-selected-node-02.js @@ -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"); + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_delete-selected-node-03.js b/devtools/client/inspector/test/browser_inspector_delete-selected-node-03.js new file mode 100644 index 000000000..21057cdb6 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_delete-selected-node-03.js @@ -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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_destroy-after-navigation.js b/devtools/client/inspector/test/browser_inspector_destroy-after-navigation.js new file mode 100644 index 000000000..5fcd5538b --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_destroy-after-navigation.js @@ -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); + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_destroy-before-ready.js b/devtools/client/inspector/test/browser_inspector_destroy-before-ready.js new file mode 100644 index 000000000..ac8ad5d37 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_destroy-before-ready.js @@ -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; +}); diff --git a/devtools/client/inspector/test/browser_inspector_expand-collapse.js b/devtools/client/inspector/test/browser_inspector_expand-collapse.js new file mode 100644 index 000000000..3b1dcb6b2 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_expand-collapse.js @@ -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," + + "
"; + +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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js b/devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js new file mode 100644 index 000000000..dca8167c4 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_gcli-inspect-command.js @@ -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: " ", + 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"), + }, + ]); + })); +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-01.js b/devtools/client/inspector/test/browser_inspector_highlighter-01.js new file mode 100644 index 000000000..946b8c3c8 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-01.js @@ -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,

foo

bar"); + + 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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-02.js b/devtools/client/inspector/test/browser_inspector_highlighter-02.js new file mode 100644 index 000000000..37eb9389e --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-02.js @@ -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"); +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-03.js b/devtools/client/inspector/test/browser_inspector_highlighter-03.js new file mode 100644 index 000000000..344b5c6c8 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-03.js @@ -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 = "hello from iframe"; + +const DOCUMENT_SRC = "" + + "" + + "" + + ""; + +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"); + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-04.js b/devtools/client/inspector/test/browser_inspector_highlighter-04.js new file mode 100644 index 000000000..d87f20e94 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-04.js @@ -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,
test
"; + +// 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(); +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-by-type.js b/devtools/client/inspector/test/browser_inspector_highlighter-by-type.js new file mode 100644 index 000000000..485d9db0e --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-by-type.js @@ -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"); +} diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-cancel.js b/devtools/client/inspector/test/browser_inspector_highlighter-cancel.js new file mode 100644 index 000000000..f1022bb50 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-cancel.js @@ -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; + } +}); diff --git a/devtools/client/inspector/test/browser_inspector_highlighter-comments.js b/devtools/client/inspector/test/browser_inspector_highlighter-comments.js new file mode 100644 index 000000000..104395227 --- /dev/null +++ b/devtools/client/inspector/test/browser_inspector_highlighter-comments.js @@ -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 +
Visible div 3
+ + Visible text node + + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html b/devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html new file mode 100644 index 000000000..f05f15deb --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter-geometry_01.html @@ -0,0 +1,90 @@ + + + + + geometry highlighter test page + + + +
+
+
+
+
+ +
+
+
+
+ +
+ + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter-geometry_02.html b/devtools/client/inspector/test/doc_inspector_highlighter-geometry_02.html new file mode 100644 index 000000000..4392c9042 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter-geometry_02.html @@ -0,0 +1,120 @@ + + + + +

Positioning playground

+

A demo of various positioning schemes: http://dev.w3.org/csswg/css-position/#pos-sch.

+

absolute, static, fixed, relative, sticky

+ +

Absolute positioning

+
+ Absolute child with no relative parent +
+
+
+ Absolute child with a relative parent +
+
+ Absolute child with a relative parent, positioned from the bottom right +
+
+ Absolute child with a relative parent, with all 4 positions +
+
+ Absolute child with a relative parent, with negative positions +
+
+ Absolute child with a relative parent, size, margin +
+
+ +

Relative positioning

+
+
+ Relative child +
+
+
+ Relative inline child, across multiple lines +
+
+
+
+ Relative child, in a positioned parent +
+
+
+ +

Fixed positioning

+
+
+ Fixed child +
+
+ Fixed child, bottom right +
+
+ +

Static positioning

+
+
+ Static child with no width/height +
+
+ Static child with width/height +
+
+ + \ No newline at end of file diff --git a/devtools/client/inspector/test/doc_inspector_highlighter.html b/devtools/client/inspector/test/doc_inspector_highlighter.html new file mode 100644 index 000000000..376a9c714 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter.html @@ -0,0 +1,40 @@ + + + + + + + +
Gort! Klaatu barada nikto!
+
+
Width & height = 0
+ + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_csstransform.html b/devtools/client/inspector/test/doc_inspector_highlighter_csstransform.html new file mode 100644 index 000000000..cfa2761d7 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_csstransform.html @@ -0,0 +1,25 @@ + + + + + css transform highlighter test + + + +
+ + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_dom.html b/devtools/client/inspector/test/doc_inspector_highlighter_dom.html new file mode 100644 index 000000000..fab0c8803 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_dom.html @@ -0,0 +1,20 @@ + + + + +

Hello World!

+ +
+
+

The DOM is very useful! #useless-para

+

This example is really useful. #useful-para

+
+ +
+

This is another node. You won't reach this in my test.

+

Ahoy! How you doin' Capn'? #ahoy

+
+
+ + + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_inline.html b/devtools/client/inspector/test/doc_inspector_highlighter_inline.html new file mode 100644 index 000000000..e1aa5bb1f --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_inline.html @@ -0,0 +1,36 @@ + + + + + + + +

Lorem Ipsum

+

Lorem ipsum dolor sit amet

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed varius, nisl eget semper maximus, dui tellus tempor leo, at pharetra eros tortor sed odio. Nullam sagittis ex nec mi sagittis pulvinar. Pellentesque dapibus feugiat fermentum. Curabitur lacinia quis enim et tristique. Aliquam in semper massa. In ac vulputate nunc, at rutrum neque. Fusce condimentum, tellus quis placerat imperdiet, dolor tortor mattis erat, nec luctus magna diam pharetra mauris.

+
+ some ltr text in an rtl container +
+ + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_rect.html b/devtools/client/inspector/test/doc_inspector_highlighter_rect.html new file mode 100644 index 000000000..4d23d52fd --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_rect.html @@ -0,0 +1,22 @@ + + + + + rect highlighter parent test page + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_rect_iframe.html b/devtools/client/inspector/test/doc_inspector_highlighter_rect_iframe.html new file mode 100644 index 000000000..d59050f69 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_rect_iframe.html @@ -0,0 +1,15 @@ + + + + + rect highlighter child test page + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_highlighter_xbl.xul b/devtools/client/inspector/test/doc_inspector_highlighter_xbl.xul new file mode 100644 index 000000000..8cbf990ea --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_highlighter_xbl.xul @@ -0,0 +1,9 @@ + + + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_infobar.html b/devtools/client/inspector/test/doc_inspector_infobar.html new file mode 100644 index 000000000..137b3487f --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_infobar.html @@ -0,0 +1,43 @@ + + + + + + + + +
+
+
+
+
+ + diff --git a/devtools/client/inspector/test/doc_inspector_infobar_01.html b/devtools/client/inspector/test/doc_inspector_infobar_01.html new file mode 100644 index 000000000..a0c42ee38 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_infobar_01.html @@ -0,0 +1,44 @@ + + + + + + + + +
Vertical
+
Top
+
Bottom
+ + + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_infobar_02.html b/devtools/client/inspector/test/doc_inspector_infobar_02.html new file mode 100644 index 000000000..ed1843f8d --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_infobar_02.html @@ -0,0 +1,34 @@ + + + + + + + + +
Above top
+
Far bottom
+ + diff --git a/devtools/client/inspector/test/doc_inspector_infobar_03.html b/devtools/client/inspector/test/doc_inspector_infobar_03.html new file mode 100644 index 000000000..a9aa05fa0 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_infobar_03.html @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_infobar_textnode.html b/devtools/client/inspector/test/doc_inspector_infobar_textnode.html new file mode 100644 index 000000000..2370708f4 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_infobar_textnode.html @@ -0,0 +1,14 @@ + + + + + + +
+ text + content + content + text +
+ + diff --git a/devtools/client/inspector/test/doc_inspector_long-divs.html b/devtools/client/inspector/test/doc_inspector_long-divs.html new file mode 100644 index 000000000..52d6343aa --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_long-divs.html @@ -0,0 +1,104 @@ + + + + + Inspector Long Div Listing + + + +
+
+
+
+
+
+
+
+
+
+
+
+
focus here
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
zoom-here
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + diff --git a/devtools/client/inspector/test/doc_inspector_menu.html b/devtools/client/inspector/test/doc_inspector_menu.html new file mode 100644 index 000000000..862a34579 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_menu.html @@ -0,0 +1,29 @@ + + + + Inspector Tree Menu Test + + + +
+
+

Inspector Tree Menu Test

+

Unset

+

+ 3 +

+
+

Paragraph for testing copy

+

Paragraph for sensitivity

+

This will be duplicated

+

This has to be deleted

+ + +

Paragraph for testing console variables

+

Paragraph for testing multiple console variables

+

Attributes are going to be changed here

+
+ + diff --git a/devtools/client/inspector/test/doc_inspector_outerhtml.html b/devtools/client/inspector/test/doc_inspector_outerhtml.html new file mode 100644 index 000000000..cc400674d --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_outerhtml.html @@ -0,0 +1,11 @@ + + + + + Inspector Copy OuterHTML Test + + + +

Test copy OuterHTML

+ + diff --git a/devtools/client/inspector/test/doc_inspector_remove-iframe-during-load.html b/devtools/client/inspector/test/doc_inspector_remove-iframe-during-load.html new file mode 100644 index 000000000..25454e122 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_remove-iframe-during-load.html @@ -0,0 +1,45 @@ + + + + + iframe creation/deletion test + + +
+ + + diff --git a/devtools/client/inspector/test/doc_inspector_search-reserved.html b/devtools/client/inspector/test/doc_inspector_search-reserved.html new file mode 100644 index 000000000..15cf8c3af --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_search-reserved.html @@ -0,0 +1,11 @@ + + + + + Inspector Search Box Reserved Character Test + + +
Hi, I'm an id that contains a CSS reserved character
+
Hi, a class that contains a CSS reserved character
+ + diff --git a/devtools/client/inspector/test/doc_inspector_search-suggestions.html b/devtools/client/inspector/test/doc_inspector_search-suggestions.html new file mode 100644 index 000000000..a84a2e3d4 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_search-suggestions.html @@ -0,0 +1,27 @@ + + + + + Inspector Search Box Test + + +
+
+
Hello, I'm nested div
+
+
+ Hello, I'm a span +
+ Hi I am a nested span + Hi I am a nested classed span +
+
+ And me + +

.someclass

+

#someid

+ +

p>strong

+ + + diff --git a/devtools/client/inspector/test/doc_inspector_search-svg.html b/devtools/client/inspector/test/doc_inspector_search-svg.html new file mode 100644 index 000000000..f762b2288 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_search-svg.html @@ -0,0 +1,16 @@ + + + + + Inspector SVG Search Box Test + + +
+ + + + + + + + diff --git a/devtools/client/inspector/test/doc_inspector_search.html b/devtools/client/inspector/test/doc_inspector_search.html new file mode 100644 index 000000000..262eb0be6 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_search.html @@ -0,0 +1,26 @@ + + + + + Inspector Search Box Test + + + + + + +
Hello, I'm a div
+
Hello, I'm another div
+ + + Hello, I'm a span + And me + + +

.someclass

+

#someid

+ +

p>strong

+ + + diff --git a/devtools/client/inspector/test/doc_inspector_select-last-selected-01.html b/devtools/client/inspector/test/doc_inspector_select-last-selected-01.html new file mode 100644 index 000000000..fbe1251cb --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_select-last-selected-01.html @@ -0,0 +1,21 @@ + + + + + select last selected test + + +
+
+
+
    +
  • +
  • +
  • +
  • + +
  • +
+
+ + \ No newline at end of file diff --git a/devtools/client/inspector/test/doc_inspector_select-last-selected-02.html b/devtools/client/inspector/test/doc_inspector_select-last-selected-02.html new file mode 100644 index 000000000..2fbef312c --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_select-last-selected-02.html @@ -0,0 +1,10 @@ + + + + + select last selected test + + +
+ + \ No newline at end of file diff --git a/devtools/client/inspector/test/doc_inspector_svg.svg b/devtools/client/inspector/test/doc_inspector_svg.svg new file mode 100644 index 000000000..75154dcf3 --- /dev/null +++ b/devtools/client/inspector/test/doc_inspector_svg.svg @@ -0,0 +1,3 @@ + + + diff --git a/devtools/client/inspector/test/head.js b/devtools/client/inspector/test/head.js new file mode 100644 index 000000000..f251568df --- /dev/null +++ b/devtools/client/inspector/test/head.js @@ -0,0 +1,732 @@ +/* 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/. */ +/* eslint no-unused-vars: [2, {"vars": "local"}] */ +/* import-globals-from ../../framework/test/shared-head.js */ +/* import-globals-from ../../commandline/test/helpers.js */ +/* import-globals-from ../../shared/test/test-actor-registry.js */ +/* import-globals-from ../../inspector/test/shared-head.js */ +"use strict"; + +// Load the shared-head file first. +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/framework/test/shared-head.js", + this); + +// Services.prefs.setBoolPref("devtools.debugger.log", true); +// SimpleTest.registerCleanupFunction(() => { +// Services.prefs.clearUserPref("devtools.debugger.log"); +// }); + +// Import the GCLI test helper +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/commandline/test/helpers.js", + this); + +// Import helpers registering the test-actor in remote targets +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/shared/test/test-actor-registry.js", + this); + +// Import helpers for the inspector that are also shared with others +Services.scriptloader.loadSubScript( + "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js", + this); + +const {LocalizationHelper} = require("devtools/shared/l10n"); +const INSPECTOR_L10N = + new LocalizationHelper("devtools/client/locales/inspector.properties"); + +flags.testing = true; +registerCleanupFunction(() => { + flags.testing = false; +}); + +registerCleanupFunction(() => { + Services.prefs.clearUserPref("devtools.inspector.activeSidebar"); +}); + +registerCleanupFunction(function* () { + // Move the mouse outside inspector. If the test happened fake a mouse event + // somewhere over inspector the pointer is considered to be there when the + // next test begins. This might cause unexpected events to be emitted when + // another test moves the mouse. + EventUtils.synthesizeMouseAtPoint(1, 1, {type: "mousemove"}, window); +}); + +var navigateTo = Task.async(function* (inspector, url) { + let markuploaded = inspector.once("markuploaded"); + let onNewRoot = inspector.once("new-root"); + let onUpdated = inspector.once("inspector-updated"); + + info("Navigating to: " + url); + let activeTab = inspector.toolbox.target.activeTab; + yield activeTab.navigateTo(url); + + info("Waiting for markup view to load after navigation."); + yield markuploaded; + + info("Waiting for new root."); + yield onNewRoot; + + info("Waiting for inspector to update after new-root event."); + yield onUpdated; +}); + +/** + * Start the element picker and focus the content window. + * @param {Toolbox} toolbox + * @param {Boolean} skipFocus - Allow tests to bypass the focus event. + */ +var startPicker = Task.async(function* (toolbox, skipFocus) { + info("Start the element picker"); + toolbox.win.focus(); + yield toolbox.highlighterUtils.startPicker(); + if (!skipFocus) { + // By default make sure the content window is focused since the picker may not focus + // the content window by default. + yield ContentTask.spawn(gBrowser.selectedBrowser, null, function* () { + content.focus(); + }); + } +}); + +/** + * Highlight a node and set the inspector's current selection to the node or + * the first match of the given css selector. + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector + * The instance of InspectorPanel currently loaded in the toolbox + * @return a promise that resolves when the inspector is updated with the new + * node + */ +function selectAndHighlightNode(selector, inspector) { + info("Highlighting and selecting the node " + selector); + return selectNode(selector, inspector, "test-highlight"); +} + +/** + * Select node for a given selector, make it focusable and set focus in its + * container element. + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The current inspector-panel instance. + * @return {MarkupContainer} + */ +function* focusNode(selector, inspector) { + getContainerForNodeFront(inspector.walker.rootNode, inspector).elt.focus(); + let nodeFront = yield getNodeFront(selector, inspector); + let container = getContainerForNodeFront(nodeFront, inspector); + yield selectNode(nodeFront, inspector); + EventUtils.sendKey("return", inspector.panelWin); + return container; +} + +/** + * Set the inspector's current selection to null so that no node is selected + * + * @param {InspectorPanel} inspector + * The instance of InspectorPanel currently loaded in the toolbox + * @return a promise that resolves when the inspector is updated + */ +function clearCurrentNodeSelection(inspector) { + info("Clearing the current selection"); + let updated = inspector.once("inspector-updated"); + inspector.selection.setNodeFront(null); + return updated; +} + +/** + * Open the inspector in a tab with given URL. + * @param {string} url The URL to open. + * @param {String} hostType Optional hostType, as defined in Toolbox.HostType + * @return A promise that is resolved once the tab and inspector have loaded + * with an object: { tab, toolbox, inspector }. + */ +var openInspectorForURL = Task.async(function* (url, hostType) { + let tab = yield addTab(url); + let { inspector, toolbox, testActor } = yield openInspector(hostType); + return { tab, inspector, toolbox, testActor }; +}); + +function getActiveInspector() { + let target = TargetFactory.forTab(gBrowser.selectedTab); + return gDevTools.getToolbox(target).getPanel("inspector"); +} + +/** + * Right click on a node in the test page and click on the inspect menu item. + * @param {TestActor} + * @param {String} selector The selector for the node to click on in the page. + * @return {Promise} Resolves to the inspector when it has opened and is updated + */ +var clickOnInspectMenuItem = Task.async(function* (testActor, selector) { + info("Showing the contextual menu on node " + selector); + let contentAreaContextMenu = document.querySelector( + "#contentAreaContextMenu"); + let contextOpened = once(contentAreaContextMenu, "popupshown"); + + yield testActor.synthesizeMouse({ + selector: selector, + center: true, + options: {type: "contextmenu", button: 2} + }); + + yield contextOpened; + + info("Triggering the inspect action"); + yield gContextMenu.inspectNode(); + + info("Hiding the menu"); + let contextClosed = once(contentAreaContextMenu, "popuphidden"); + contentAreaContextMenu.hidePopup(); + yield contextClosed; + + return getActiveInspector(); +}); + +/** + * Get the NodeFront for a node that matches a given css selector inside a + * given iframe. + * @param {String|NodeFront} selector + * @param {String|NodeFront} frameSelector A selector that matches the iframe + * the node is in + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {Promise} Resolves when the inspector is updated with the new node + */ +var getNodeFrontInFrame = Task.async(function* (selector, frameSelector, + inspector) { + let iframe = yield getNodeFront(frameSelector, inspector); + let {nodes} = yield inspector.walker.children(iframe); + return inspector.walker.querySelector(nodes[0], selector); +}); + +var focusSearchBoxUsingShortcut = Task.async(function* (panelWin, callback) { + info("Focusing search box"); + let searchBox = panelWin.document.getElementById("inspector-searchbox"); + let focused = once(searchBox, "focus"); + + panelWin.focus(); + + synthesizeKeyShortcut(INSPECTOR_L10N.getStr("inspector.searchHTML.key")); + + yield focused; + + if (callback) { + callback(); + } +}); + +/** + * Get the MarkupContainer object instance that corresponds to the given + * NodeFront + * @param {NodeFront} nodeFront + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {MarkupContainer} + */ +function getContainerForNodeFront(nodeFront, {markup}) { + return markup.getContainer(nodeFront); +} + +/** + * Get the MarkupContainer object instance that corresponds to the given + * selector + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {MarkupContainer} + */ +var getContainerForSelector = Task.async(function* (selector, inspector) { + info("Getting the markup-container for node " + selector); + let nodeFront = yield getNodeFront(selector, inspector); + let container = getContainerForNodeFront(nodeFront, inspector); + info("Found markup-container " + container); + return container; +}); + +/** + * Simulate a mouse-over on the markup-container (a line in the markup-view) + * that corresponds to the selector passed. + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {Promise} Resolves when the container is hovered and the higlighter + * is shown on the corresponding node + */ +var hoverContainer = Task.async(function* (selector, inspector) { + info("Hovering over the markup-container for node " + selector); + + let nodeFront = yield getNodeFront(selector, inspector); + let container = getContainerForNodeFront(nodeFront, inspector); + + let highlit = inspector.toolbox.once("node-highlight"); + EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousemove"}, + inspector.markup.doc.defaultView); + return highlit; +}); + +/** + * Simulate a click on the markup-container (a line in the markup-view) + * that corresponds to the selector passed. + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {Promise} Resolves when the node has been selected. + */ +var clickContainer = Task.async(function* (selector, inspector) { + info("Clicking on the markup-container for node " + selector); + + let nodeFront = yield getNodeFront(selector, inspector); + let container = getContainerForNodeFront(nodeFront, inspector); + + let updated = inspector.once("inspector-updated"); + EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mousedown"}, + inspector.markup.doc.defaultView); + EventUtils.synthesizeMouseAtCenter(container.tagLine, {type: "mouseup"}, + inspector.markup.doc.defaultView); + return updated; +}); + +/** + * Simulate the mouse leaving the markup-view area + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return a promise when done + */ +function mouseLeaveMarkupView(inspector) { + info("Leaving the markup-view area"); + let def = defer(); + + // Find another element to mouseover over in order to leave the markup-view + let btn = inspector.toolbox.doc.querySelector("#toolbox-controls"); + + EventUtils.synthesizeMouseAtCenter(btn, {type: "mousemove"}, + inspector.toolbox.win); + executeSoon(def.resolve); + + return def.promise; +} + +/** + * Dispatch the copy event on the given element + */ +function fireCopyEvent(element) { + let evt = element.ownerDocument.createEvent("Event"); + evt.initEvent("copy", true, true); + element.dispatchEvent(evt); +} + +/** + * Undo the last markup-view action and wait for the corresponding mutation to + * occur + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return a promise that resolves when the markup-mutation has been treated or + * rejects if no undo action is possible + */ +function undoChange(inspector) { + let canUndo = inspector.markup.undo.canUndo(); + ok(canUndo, "The last change in the markup-view can be undone"); + if (!canUndo) { + return promise.reject(); + } + + let mutated = inspector.once("markupmutation"); + inspector.markup.undo.undo(); + return mutated; +} + +/** + * Redo the last markup-view action and wait for the corresponding mutation to + * occur + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return a promise that resolves when the markup-mutation has been treated or + * rejects if no redo action is possible + */ +function redoChange(inspector) { + let canRedo = inspector.markup.undo.canRedo(); + ok(canRedo, "The last change in the markup-view can be redone"); + if (!canRedo) { + return promise.reject(); + } + + let mutated = inspector.once("markupmutation"); + inspector.markup.undo.redo(); + return mutated; +} + +/** + * 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 simple polling helper that executes a given function until it returns true. + * @param {Function} check A generator function that is expected to return true at some + * stage. + * @param {String} desc A text description to be displayed when the polling starts. + * @param {Number} attemptes Optional number of times we poll. Defaults to 10. + * @param {Number} timeBetweenAttempts Optional time to wait between each attempt. + * Defaults to 200ms. + */ +function* poll(check, desc, attempts = 10, timeBetweenAttempts = 200) { + info(desc); + + for (let i = 0; i < attempts; i++) { + if (yield check()) { + return; + } + yield new Promise(resolve => setTimeout(resolve, timeBetweenAttempts)); + } + + throw new Error(`Timeout while: ${desc}`); +} + +/** + * Encapsulate some common operations for highlighter's tests, to have + * the tests cleaner, without exposing directly `inspector`, `highlighter`, and + * `testActor` if not needed. + * + * @param {String} + * The highlighter's type + * @return + * A generator function that takes an object with `inspector` and `testActor` + * properties. (see `openInspector`) + */ +const getHighlighterHelperFor = (type) => Task.async( + function* ({inspector, testActor}) { + let front = inspector.inspector; + let highlighter = yield front.getHighlighterByType(type); + + let prefix = ""; + + // Internals for mouse events + let prevX, prevY; + + // Highlighted node + let highlightedNode = null; + + return { + set prefix(value) { + prefix = value; + }, + + get highlightedNode() { + if (!highlightedNode) { + return null; + } + + return { + getComputedStyle: function* (options = {}) { + return yield inspector.pageStyle.getComputed( + highlightedNode, options); + } + }; + }, + + show: function* (selector = ":root", options) { + highlightedNode = yield getNodeFront(selector, inspector); + return yield highlighter.show(highlightedNode, options); + }, + + hide: function* () { + yield highlighter.hide(); + }, + + isElementHidden: function* (id) { + return (yield testActor.getHighlighterNodeAttribute( + prefix + id, "hidden", highlighter)) === "true"; + }, + + getElementTextContent: function* (id) { + return yield testActor.getHighlighterNodeTextContent( + prefix + id, highlighter); + }, + + getElementAttribute: function* (id, name) { + return yield testActor.getHighlighterNodeAttribute( + prefix + id, name, highlighter); + }, + + waitForElementAttributeSet: function* (id, name) { + yield poll(function* () { + let value = yield testActor.getHighlighterNodeAttribute( + prefix + id, name, highlighter); + return !!value; + }, `Waiting for element ${id} to have attribute ${name} set`); + }, + + waitForElementAttributeRemoved: function* (id, name) { + yield poll(function* () { + let value = yield testActor.getHighlighterNodeAttribute( + prefix + id, name, highlighter); + return !value; + }, `Waiting for element ${id} to have attribute ${name} removed`); + }, + + synthesizeMouse: function* (options) { + options = Object.assign({selector: ":root"}, options); + yield testActor.synthesizeMouse(options); + }, + + // This object will synthesize any "mouse" prefixed event to the + // `testActor`, using the name of method called as suffix for the + // event's name. + // If no x, y coords are given, the previous ones are used. + // + // For example: + // mouse.down(10, 20); // synthesize "mousedown" at 10,20 + // mouse.move(20, 30); // synthesize "mousemove" at 20,30 + // mouse.up(); // synthesize "mouseup" at 20,30 + mouse: new Proxy({}, { + get: (target, name) => + function* (x = prevX, y = prevY) { + prevX = x; + prevY = y; + yield testActor.synthesizeMouse({ + selector: ":root", x, y, options: {type: "mouse" + name}}); + } + }), + + reflow: function* () { + yield testActor.reflow(); + }, + + finalize: function* () { + highlightedNode = null; + yield highlighter.finalize(); + } + }; + } +); + +// The expand all operation of the markup-view calls itself recursively and +// there's not one event we can wait for to know when it's done so use this +// helper function to wait until all recursive children updates are done. +function* waitForMultipleChildrenUpdates(inspector) { + // As long as child updates are queued up while we wait for an update already + // wait again + if (inspector.markup._queuedChildUpdates && + inspector.markup._queuedChildUpdates.size) { + yield waitForChildrenUpdated(inspector); + return yield waitForMultipleChildrenUpdates(inspector); + } + return null; +} + +/** + * Using the markupview's _waitForChildren function, wait for all queued + * children updates to be handled. + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return a promise that resolves when all queued children updates have been + * handled + */ +function waitForChildrenUpdated({markup}) { + info("Waiting for queued children updates to be handled"); + let def = defer(); + markup._waitForChildren().then(() => { + executeSoon(def.resolve); + }); + return def.promise; +} + +/** + * Wait for the toolbox to emit the styleeditor-selected event and when done + * wait for the stylesheet identified by href to be loaded in the stylesheet + * editor + * + * @param {Toolbox} toolbox + * @param {String} href + * Optional, if not provided, wait for the first editor to be ready + * @return a promise that resolves to the editor when the stylesheet editor is + * ready + */ +function waitForStyleEditor(toolbox, href) { + let def = defer(); + + info("Waiting for the toolbox to switch to the styleeditor"); + toolbox.once("styleeditor-selected").then(() => { + let panel = toolbox.getCurrentPanel(); + ok(panel && panel.UI, "Styleeditor panel switched to front"); + + // A helper that resolves the promise once it receives an editor that + // matches the expected href. Returns false if the editor was not correct. + let gotEditor = (event, editor) => { + let currentHref = editor.styleSheet.href; + if (!href || (href && currentHref.endsWith(href))) { + info("Stylesheet editor selected"); + panel.UI.off("editor-selected", gotEditor); + + editor.getSourceEditor().then(sourceEditor => { + info("Stylesheet editor fully loaded"); + def.resolve(sourceEditor); + }); + + return true; + } + + info("The editor was incorrect. Waiting for editor-selected event."); + return false; + }; + + // The expected editor may already be selected. Check the if the currently + // selected editor is the expected one and if not wait for an + // editor-selected event. + if (!gotEditor("styleeditor-selected", panel.UI.selectedEditor)) { + // The expected editor is not selected (yet). Wait for it. + panel.UI.on("editor-selected", gotEditor); + } + }); + + return def.promise; +} + +/** + * Checks if document's active element is within the given element. + * @param {HTMLDocument} doc document with active element in question + * @param {DOMNode} container element tested on focus containment + * @return {Boolean} + */ +function containsFocus(doc, container) { + let elm = doc.activeElement; + while (elm) { + if (elm === container) { + return true; + } + elm = elm.parentNode; + } + return false; +} + +/** + * Listen for a new tab to open and return a promise that resolves when one + * does and completes the load event. + * + * @return a promise that resolves to the tab object + */ +var waitForTab = Task.async(function* () { + info("Waiting for a tab to open"); + yield once(gBrowser.tabContainer, "TabOpen"); + let tab = gBrowser.selectedTab; + yield BrowserTestUtils.browserLoaded(tab.linkedBrowser); + info("The tab load completed"); + return tab; +}); + +/** + * Simulate the key input for the given input in the window. + * + * @param {String} input + * The string value to input + * @param {Window} win + * The window containing the panel + */ +function synthesizeKeys(input, win) { + for (let key of input.split("")) { + EventUtils.synthesizeKey(key, {}, win); + } +} + +/** + * Given a tooltip object instance (see Tooltip.js), checks if it is set to + * toggle and hover and if so, checks if the given target is a valid hover + * target. This won't actually show the tooltip (the less we interact with XUL + * panels during test runs, the better). + * + * @return a promise that resolves when the answer is known + */ +function isHoverTooltipTarget(tooltip, target) { + if (!tooltip._toggle._baseNode || !tooltip.panel) { + return promise.reject(new Error( + "The tooltip passed isn't set to toggle on hover or is not a tooltip")); + } + return tooltip._toggle.isValidHoverTarget(target); +} + +/** + * Same as isHoverTooltipTarget except that it will fail the test if there is no + * tooltip defined on hover of the given element + * + * @return a promise + */ +function assertHoverTooltipOn(tooltip, element) { + return isHoverTooltipTarget(tooltip, element).then(() => { + ok(true, "A tooltip is defined on hover of the given element"); + }, () => { + ok(false, "No tooltip is defined on hover of the given element"); + }); +} + +/** + * Open the inspector menu and return all of it's items in a flat array + * @param {InspectorPanel} inspector + * @param {Object} options to pass into openMenu + * @return An array of MenuItems + */ +function openContextMenuAndGetAllItems(inspector, options) { + let menu = inspector._openMenu(options); + + // Flatten all menu items into a single array to make searching through it easier + let allItems = [].concat.apply([], menu.items.map(function addItem(item) { + if (item.submenu) { + return addItem(item.submenu.items); + } + return item; + })); + + return allItems; +} + +/** + * Get the rule editor from the rule-view given its index + * + * @param {CssRuleView} view + * The instance of the rule-view panel + * @param {Number} childrenIndex + * The children index of the element to get + * @param {Number} nodeIndex + * The child node index of the element to get + * @return {DOMNode} The rule editor if any at this index + */ +function getRuleViewRuleEditor(view, childrenIndex, nodeIndex) { + return nodeIndex !== undefined ? + view.element.children[childrenIndex].childNodes[nodeIndex]._ruleEditor : + view.element.children[childrenIndex]._ruleEditor; +} + +/** + * Get the text displayed for a given DOM Element's textContent within the + * markup view. + * + * @param {String} selector + * @param {InspectorPanel} inspector + * @return {String} The text displayed in the markup view + */ +function* getDisplayedNodeTextContent(selector, inspector) { + // We have to ensure that the textContent is displayed, for that the DOM + // Element has to be selected in the markup view and to be expanded. + yield selectNode(selector, inspector); + + let container = yield getContainerForSelector(selector, inspector); + yield inspector.markup.expandNode(container.node); + yield waitForMultipleChildrenUpdates(inspector); + if (container) { + let textContainer = container.elt.querySelector("pre"); + return textContainer.textContent; + } + return null; +} diff --git a/devtools/client/inspector/test/shared-head.js b/devtools/client/inspector/test/shared-head.js new file mode 100644 index 000000000..13eeca0f7 --- /dev/null +++ b/devtools/client/inspector/test/shared-head.js @@ -0,0 +1,186 @@ +/* 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"; + +/* eslint no-unused-vars: [2, {"vars": "local"}] */ +/* globals registerTestActor, getTestActor, Task, openToolboxForTab, gBrowser */ + +// This file contains functions related to the inspector that are also of interest to +// other test directores as well. + +/** + * Open the toolbox, with the inspector tool visible. + * @param {String} hostType Optional hostType, as defined in Toolbox.HostType + * @return a promise that resolves when the inspector is ready + */ +var openInspector = Task.async(function* (hostType) { + info("Opening the inspector"); + + let toolbox = yield openToolboxForTab(gBrowser.selectedTab, "inspector", + hostType); + let inspector = toolbox.getPanel("inspector"); + + if (inspector._updateProgress) { + info("Need to wait for the inspector to update"); + yield inspector.once("inspector-updated"); + } + + info("Waiting for actor features to be detected"); + yield inspector._detectingActorFeatures; + + yield registerTestActor(toolbox.target.client); + let testActor = yield getTestActor(toolbox); + + return {toolbox, inspector, testActor}; +}); + +/** + * Open the toolbox, with the inspector tool visible, and the one of the sidebar + * tabs selected. + * + * @param {String} id + * The ID of the sidebar tab to be opened + * @return a promise that resolves when the inspector is ready and the tab is + * visible and ready + */ +var openInspectorSidebarTab = Task.async(function* (id) { + let {toolbox, inspector, testActor} = yield openInspector(); + + info("Selecting the " + id + " sidebar"); + inspector.sidebar.select(id); + + return { + toolbox, + inspector, + testActor + }; +}); + +/** + * Open the toolbox, with the inspector tool visible, and the rule-view + * sidebar tab selected. + * + * @return a promise that resolves when the inspector is ready and the rule view + * is visible and ready + */ +function openRuleView() { + return openInspectorSidebarTab("ruleview").then(data => { + // Replace the view to use a custom throttle function that can be triggered manually + // through an additional ".flush()" property. + data.inspector.ruleview.view.throttle = manualThrottle(); + + return { + toolbox: data.toolbox, + inspector: data.inspector, + testActor: data.testActor, + view: data.inspector.ruleview.view + }; + }); +} + +/** + * Open the toolbox, with the inspector tool visible, and the computed-view + * sidebar tab selected. + * + * @return a promise that resolves when the inspector is ready and the computed + * view is visible and ready + */ +function openComputedView() { + return openInspectorSidebarTab("computedview").then(data => { + return { + toolbox: data.toolbox, + inspector: data.inspector, + testActor: data.testActor, + view: data.inspector.computedview.computedView + }; + }); +} + +/** + * Select the rule view sidebar tab on an already opened inspector panel. + * + * @param {InspectorPanel} inspector + * The opened inspector panel + * @return {CssRuleView} the rule view + */ +function selectRuleView(inspector) { + inspector.sidebar.select("ruleview"); + return inspector.ruleview.view; +} + +/** + * Select the computed view sidebar tab on an already opened inspector panel. + * + * @param {InspectorPanel} inspector + * The opened inspector panel + * @return {CssComputedView} the computed view + */ +function selectComputedView(inspector) { + inspector.sidebar.select("computedview"); + return inspector.computedview.computedView; +} + +/** + * Get the NodeFront for a node that matches a given css selector, via the + * protocol. + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @return {Promise} Resolves to the NodeFront instance + */ +function getNodeFront(selector, {walker}) { + if (selector._form) { + return selector; + } + return walker.querySelector(walker.rootNode, selector); +} + +/** + * Set the inspector's current selection to the first match of the given css + * selector + * @param {String|NodeFront} selector + * @param {InspectorPanel} inspector The instance of InspectorPanel currently + * loaded in the toolbox + * @param {String} reason Defaults to "test" which instructs the inspector not + * to highlight the node upon selection + * @return {Promise} Resolves when the inspector is updated with the new node + */ +var selectNode = Task.async(function* (selector, inspector, reason = "test") { + info("Selecting the node for '" + selector + "'"); + let nodeFront = yield getNodeFront(selector, inspector); + let updated = inspector.once("inspector-updated"); + inspector.selection.setNodeFront(nodeFront, reason); + yield updated; +}); + +/** + * Create a throttling function that can be manually "flushed". This is to replace the + * use of the `throttle` function from `devtools/client/inspector/shared/utils.js`, which + * has a setTimeout that can cause intermittents. + * @return {Function} This function has the same function signature as throttle, but + * the property `.flush()` has been added for flushing out any + * throttled calls. + */ +function manualThrottle() { + let calls = []; + + function throttle(func, wait, scope) { + return function () { + let existingCall = calls.find(call => call.func === func); + if (existingCall) { + existingCall.args = arguments; + } else { + calls.push({ func, wait, scope, args: arguments }); + } + }; + } + + throttle.flush = function () { + calls.forEach(({func, scope, args}) => func.apply(scope, args)); + calls = []; + }; + + return throttle; +} -- cgit v1.2.3