diff options
Diffstat (limited to 'toolkit/components/pictureinpicture/tests/browser_aaa_run_first_firstTimePiPToggleEvents.js')
-rw-r--r-- | toolkit/components/pictureinpicture/tests/browser_aaa_run_first_firstTimePiPToggleEvents.js | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/toolkit/components/pictureinpicture/tests/browser_aaa_run_first_firstTimePiPToggleEvents.js b/toolkit/components/pictureinpicture/tests/browser_aaa_run_first_firstTimePiPToggleEvents.js new file mode 100644 index 0000000000..df6261584c --- /dev/null +++ b/toolkit/components/pictureinpicture/tests/browser_aaa_run_first_firstTimePiPToggleEvents.js @@ -0,0 +1,314 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const { TelemetryTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TelemetryTestUtils.sys.mjs" +); + +const FIRST_TIME_PIP_TOGGLE_STYLES = { + rootID: "pictureInPictureToggle", + stages: { + hoverVideo: { + opacities: { + ".pip-wrapper": DEFAULT_TOGGLE_OPACITY, + }, + hidden: [], + }, + + hoverToggle: { + opacities: { + ".pip-wrapper": 1.0, + }, + hidden: [], + }, + }, +}; + +const FIRST_CONTEXT_MENU_EXPECTED_EVENTS = [ + [ + "pictureinpicture", + "opened_method", + "contextMenu", + null, + { firstTimeToggle: "true" }, + ], +]; + +const SECOND_CONTEXT_MENU_EXPECTED_EVENTS = [ + [ + "pictureinpicture", + "opened_method", + "contextMenu", + null, + { firstTimeToggle: "false" }, + ], +]; + +const FIRST_TOGGLE_EXPECTED_EVENTS = [ + ["pictureinpicture", "saw_toggle", "toggle", null, { firstTime: "true" }], + [ + "pictureinpicture", + "opened_method", + "toggle", + null, + { firstTimeToggle: "true" }, + ], +]; + +const SECOND_TOGGLE_EXPECTED_EVENTS = [ + ["pictureinpicture", "saw_toggle", "toggle", null, { firstTime: "false" }], + [ + "pictureinpicture", + "opened_method", + "toggle", + null, + { firstTimeToggle: "false" }, + ], +]; + +/** + * This function will open the PiP window by clicking the toggle + * and then close the PiP window + * @param browser The current browser + * @param videoID The video element id + */ +async function openAndClosePipWithToggle(browser, videoID) { + await SimpleTest.promiseFocus(browser); + await ensureVideosReady(browser); + + await prepareForToggleClick(browser, videoID); + + await clearAllContentEvents(); + + // Hover the mouse over the video to reveal the toggle, which is necessary + // if we want to click on the toggle. + await BrowserTestUtils.synthesizeMouseAtCenter( + `#${videoID}`, + { + type: "mousemove", + }, + browser + ); + await BrowserTestUtils.synthesizeMouseAtCenter( + `#${videoID}`, + { + type: "mouseover", + }, + browser + ); + + info("Waiting for toggle to become visible"); + await toggleOpacityReachesThreshold( + browser, + videoID, + "hoverVideo", + FIRST_TIME_PIP_TOGGLE_STYLES + ); + + let toggleClientRect = await getToggleClientRect(browser, videoID); + + // The toggle center, because of how it slides out, is actually outside + // of the bounds of a click event. For now, we move the mouse in by a + // hard-coded 15 pixels along the x and y axis to achieve the hover. + let toggleLeft = toggleClientRect.left + 15; + let toggleTop = toggleClientRect.top + 15; + + info("Clicking on toggle, and expecting a Picture-in-Picture window to open"); + // We need to wait for the window to have completed loading before we + // can close it as the document's type required by closeWindow may not + // be available. + let domWindowOpened = BrowserTestUtils.domWindowOpenedAndLoaded(null); + + await BrowserTestUtils.synthesizeMouseAtPoint( + toggleLeft, + toggleTop, + { + type: "mousedown", + }, + browser + ); + + await BrowserTestUtils.synthesizeMouseAtPoint( + 1, + 1, + { + type: "mouseup", + }, + browser + ); + + let win = await domWindowOpened; + ok(win, "A Picture-in-Picture window opened."); + + await SpecialPowers.spawn(browser, [videoID], async videoID => { + let video = content.document.getElementById(videoID); + await ContentTaskUtils.waitForCondition(() => { + return video.isCloningElementVisually; + }, "Video is being cloned visually."); + }); + + await BrowserTestUtils.closeWindow(win); + await assertSawClickEventOnly(browser); + + await BrowserTestUtils.synthesizeMouseAtPoint(1, 1, {}, browser); + await assertSawMouseEvents(browser, true); +} + +/** + * This function will open the PiP window by with the context menu + * @param browser The current browser + * @param videoID The video element id + */ +async function openAndClosePipWithContextMenu(browser, videoID) { + await SimpleTest.promiseFocus(browser); + await ensureVideosReady(browser); + + let menu = document.getElementById("contentAreaContextMenu"); + let popupshown = BrowserTestUtils.waitForPopupEvent(menu, "shown"); + + await BrowserTestUtils.synthesizeMouseAtCenter( + `#${videoID}`, + { + type: "contextmenu", + }, + browser + ); + + await popupshown; + let isContextMenuOpen = menu.state === "showing" || menu.state === "open"; + ok(isContextMenuOpen, "Context menu is open"); + + let domWindowOpened = BrowserTestUtils.domWindowOpenedAndLoaded(null); + + // clear content events + await clearAllContentEvents(); + + let hidden = BrowserTestUtils.waitForPopupEvent(menu, "hidden"); + menu.activateItem(menu.querySelector("#context-video-pictureinpicture")); + await hidden; + + let win = await domWindowOpened; + ok(win, "A Picture-in-Picture window opened."); + + await SpecialPowers.spawn(browser, [videoID], async videoID => { + let video = content.document.getElementById(videoID); + await ContentTaskUtils.waitForCondition(() => { + return video.isCloningElementVisually; + }, "Video is being cloned visually."); + }); + + await BrowserTestUtils.closeWindow(win); +} + +async function clearAllContentEvents() { + // Clear everything. + await TestUtils.waitForCondition(() => { + Services.telemetry.clearEvents(); + let events = Services.telemetry.snapshotEvents( + Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, + true + ).content; + return !events || !events.length; + }); +} + +add_task(async function test_eventTelemetry() { + Services.telemetry.clearEvents(); + await clearAllContentEvents(); + await BrowserTestUtils.withNewTab( + { + gBrowser, + url: TEST_PAGE, + }, + async browser => { + Services.telemetry.setEventRecordingEnabled("pictureinpicture", true); + let videoID = "no-controls"; + + const PIP_PREF = + "media.videocontrols.picture-in-picture.video-toggle.has-used"; + await SpecialPowers.pushPrefEnv({ + set: [[PIP_PREF, false]], + }); + + // open with context menu for first time + await openAndClosePipWithContextMenu(browser, videoID); + + let filter = { + category: "pictureinpicture", + method: "opened_method", + object: "contextMenu", + }; + await waitForTelemeryEvents( + filter, + FIRST_CONTEXT_MENU_EXPECTED_EVENTS.length, + "content" + ); + + TelemetryTestUtils.assertEvents( + FIRST_CONTEXT_MENU_EXPECTED_EVENTS, + filter, + { clear: true, process: "content" } + ); + + // open with toggle for first time + await SpecialPowers.pushPrefEnv({ + set: [[PIP_PREF, false]], + }); + + await openAndClosePipWithToggle(browser, videoID); + + filter = { + category: "pictureinpicture", + }; + await waitForTelemeryEvents( + filter, + FIRST_TOGGLE_EXPECTED_EVENTS.length, + "content" + ); + + TelemetryTestUtils.assertEvents(FIRST_TOGGLE_EXPECTED_EVENTS, filter, { + clear: true, + process: "content", + }); + + // open with toggle for not first time + await openAndClosePipWithToggle(browser, videoID); + + filter = { + category: "pictureinpicture", + }; + await waitForTelemeryEvents( + filter, + SECOND_TOGGLE_EXPECTED_EVENTS.length, + "content" + ); + + TelemetryTestUtils.assertEvents(SECOND_TOGGLE_EXPECTED_EVENTS, filter, { + clear: true, + process: "content", + }); + + // open with context menu for not first time + await openAndClosePipWithContextMenu(browser, videoID); + + filter = { + category: "pictureinpicture", + method: "opened_method", + object: "contextMenu", + }; + await waitForTelemeryEvents( + filter, + SECOND_CONTEXT_MENU_EXPECTED_EVENTS.length, + "content" + ); + + TelemetryTestUtils.assertEvents( + SECOND_CONTEXT_MENU_EXPECTED_EVENTS, + filter, + { true: false, process: "content" } + ); + } + ); +}); |