browser_split-toolbar-button.js (6719B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 function isActive() { 8 return Services.profiler.IsActive(); 9 } 10 11 /** 12 * Force focus to an element that isn't focusable. 13 * Toolbar buttons aren't focusable because if they were, clicking them would 14 * focus them, which is undesirable. Therefore, they're only made focusable 15 * when a user is navigating with the keyboard. This function forces focus as 16 * is done during toolbar keyboard navigation. 17 */ 18 function forceFocus(elem) { 19 elem.setAttribute("tabindex", "-1"); 20 elem.focus(); 21 elem.removeAttribute("tabindex"); 22 } 23 24 async function waitForProfileAndCloseTab() { 25 await waitUntil( 26 () => !button.classList.contains("profiler-paused"), 27 "Waiting until the profiler is no longer paused" 28 ); 29 30 await checkTabLoadedProfile({ 31 initialTitle: "Waiting on the profile", 32 successTitle: "Profile received", 33 errorTitle: "Error", 34 }); 35 } 36 var button; 37 var dropmarker; 38 39 add_setup(async function () { 40 info( 41 "Add the profiler button to the toolbar and ensure capturing a profile loads a local url." 42 ); 43 await setProfilerFrontendUrl( 44 "https://example.com", 45 "/browser/devtools/client/performance-new/test/browser/fake-frontend.html" 46 ); 47 await makeSureProfilerPopupIsEnabled(); 48 button = document.getElementById("profiler-button-button"); 49 dropmarker = document.getElementById("profiler-button-dropmarker"); 50 }); 51 52 add_task(async function click_icon() { 53 info("Test that the profiler icon starts and captures a profile."); 54 55 ok(!dropmarker.hasAttribute("open"), "should start with the panel closed"); 56 ok(!isActive(), "should start with the profiler inactive"); 57 58 button.click(); 59 await getElementByTooltip(document, "The profiler is recording a profile"); 60 ok(isActive(), "should have started the profiler"); 61 62 button.click(); 63 // We're not testing for the tooltip "capturing a profile" because this might 64 // be racy. 65 await waitForProfileAndCloseTab(); 66 67 // Back to the inactive state. 68 await getElementByTooltip(document, "Record a performance profile"); 69 }); 70 71 add_task(async function click_dropmarker() { 72 info("Test that the profiler icon dropmarker opens the panel."); 73 74 ok(!dropmarker.hasAttribute("open"), "should start with the panel closed"); 75 ok(!isActive(), "should start with the profiler inactive"); 76 77 const popupShownPromise = waitForProfilerPopupEvent(window, "popupshown"); 78 dropmarker.click(); 79 await popupShownPromise; 80 81 info("Ensure the panel is open and the profiler still inactive."); 82 Assert.equal(dropmarker.getAttribute("open"), "true", "panel should be open"); 83 ok(!isActive(), "profiler should still be inactive"); 84 await getElementByLabel(document, "Start Recording"); 85 86 info("Press Escape to close the panel."); 87 const popupHiddenPromise = waitForProfilerPopupEvent(window, "popuphidden"); 88 EventUtils.synthesizeKey("KEY_Escape"); 89 await popupHiddenPromise; 90 ok(!dropmarker.hasAttribute("open"), "panel should be closed"); 91 }); 92 93 add_task(async function click_overflowed_icon() { 94 info("Test that the profiler icon opens the panel when overflowed."); 95 96 const toolbaritem = button.parentNode; 97 const chevron = document.getElementById("nav-bar-overflow-button"); 98 const overflowMenu = document.getElementById("widget-overflow"); 99 const profilerPanel = document.getElementById("PanelUI-profiler"); 100 const originalPlacement = CustomizableUI.getPlacementOfWidget(toolbaritem.id); 101 102 ok(!dropmarker.hasAttribute("open"), "should start with the panel closed"); 103 ok(!isActive(), "should start with the profiler inactive"); 104 ok( 105 BrowserTestUtils.isHidden(chevron), 106 "Should start with the overflow button hidden." 107 ); 108 109 info("Pinning button to overflow panel."); 110 CustomizableUI.addWidgetToArea( 111 toolbaritem.id, 112 CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, 113 0 114 ); 115 await TestUtils.waitForCondition( 116 () => BrowserTestUtils.isVisible(chevron), 117 "Waiting for the overflow button to become visible" 118 ); 119 120 info("Open the overflow menu."); 121 chevron.click(); 122 await TestUtils.waitForCondition(() => overflowMenu.state == "open"); 123 124 info("Open the profiler panel."); 125 button.click(); 126 await TestUtils.waitForCondition(() => 127 profilerPanel?.hasAttribute("visible") 128 ); 129 130 info("Ensure the panel is open and the profiler still inactive."); 131 ok(profilerPanel?.hasAttribute("visible"), "panel should be open"); 132 ok(!isActive(), "profiler should still be inactive"); 133 await getElementByLabel(document, "Start Recording"); 134 135 info("Press Escape to close the panel."); 136 EventUtils.synthesizeKey("KEY_Escape"); 137 await TestUtils.waitForCondition(() => overflowMenu.state == "closed"); 138 ok(!dropmarker.hasAttribute("open"), "panel should be closed"); 139 140 info("Removing button from overflow panel."); 141 CustomizableUI.addWidgetToArea( 142 toolbaritem.id, 143 originalPlacement.area, 144 originalPlacement.position 145 ); 146 }); 147 148 add_task(async function space_key() { 149 info("Test that the Space key starts and captures a profile."); 150 151 ok(!dropmarker.hasAttribute("open"), "should start with the panel closed"); 152 ok(!isActive(), "should start with the profiler inactive"); 153 forceFocus(button); 154 155 info("Press Space to start the profiler."); 156 EventUtils.synthesizeKey(" "); 157 ok(isActive(), "should have started the profiler"); 158 159 info("Press Space again to capture the profile."); 160 EventUtils.synthesizeKey(" "); 161 await waitForProfileAndCloseTab(); 162 }); 163 164 add_task(async function enter_key() { 165 info("Test that the Enter key starts and captures a profile."); 166 167 ok(!dropmarker.hasAttribute("open"), "should start with the panel closed"); 168 ok(!isActive(), "should start with the profiler inactive"); 169 forceFocus(button); 170 171 const isMacOS = Services.appinfo.OS === "Darwin"; 172 if (isMacOS) { 173 // On macOS, pressing Enter on a focused toolbarbutton does not fire a 174 // command event, so we do not expect Enter to start the profiler. 175 return; 176 } 177 178 info("Pressing Enter should start the profiler."); 179 EventUtils.synthesizeKey("KEY_Enter"); 180 ok(isActive(), "should have started the profiler"); 181 182 info("Pressing Enter again to capture the profile."); 183 EventUtils.synthesizeKey("KEY_Enter"); 184 await waitForProfileAndCloseTab(); 185 }); 186 187 /** 188 * Tests that dropmarker has l10n attributes. 189 */ 190 add_task(async function dropmarker_has_l10n() { 191 ok( 192 BrowserTestUtils.isVisible(dropmarker), 193 "Profiler button dropmarker is visible" 194 ); 195 196 is( 197 dropmarker.getAttribute("data-l10n-id"), 198 "profiler-button-dropmarker", 199 "Profiler button dropmarker has l10n attributes set" 200 ); 201 });