summaryrefslogtreecommitdiffstats
path: root/toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js')
-rw-r--r--toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js242
1 files changed, 242 insertions, 0 deletions
diff --git a/toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js b/toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js
new file mode 100644
index 0000000000..e50c430d0c
--- /dev/null
+++ b/toolkit/components/pictureinpicture/tests/browser_touch_toggle_enablepip.js
@@ -0,0 +1,242 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests that Picture-in-Picture intializes without changes to video playback
+ * when opened via the toggle using a touch event. Also ensures that elements
+ * in the content window can still be interacted with afterwards.
+ */
+add_task(async () => {
+ let videoID = "with-controls";
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["media.videocontrols.picture-in-picture.video-toggle.position", "right"],
+ ],
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ url: TEST_PAGE,
+ gBrowser,
+ },
+ async browser => {
+ await ensureVideosReady(browser);
+ let toggleStyles = DEFAULT_TOGGLE_STYLES;
+ let stage = "hoverVideo";
+ let toggleStylesForStage = toggleStyles.stages[stage];
+
+ // Remove other page elements before reading PiP toggle's client rect.
+ // Otherwise, we will provide the wrong coordinates when simulating the touch event.
+ await SpecialPowers.spawn(browser, [], async args => {
+ info(
+ "Removing other elements first to make the PiP toggle more visible"
+ );
+ this.content.document.getElementById("no-controls").remove();
+ let otherEls = this.content.document.querySelectorAll("h1");
+ for (let el of otherEls) {
+ el.remove();
+ }
+ });
+
+ let toggleClientRect = await getToggleClientRect(browser, videoID);
+ await prepareForToggleClick(browser, videoID);
+
+ await SpecialPowers.spawn(
+ browser,
+ [{ videoID, toggleClientRect, toggleStylesForStage }],
+ async args => {
+ // waitForToggleOpacity is based on toggleOpacityReachesThreshold.
+ // Waits for toggle to reach target opacity.
+ async function waitForToggleOpacity(
+ shadowRoot,
+ toggleStylesForStage
+ ) {
+ for (let hiddenElement of toggleStylesForStage.hidden) {
+ let el = shadowRoot.querySelector(hiddenElement);
+ ok(
+ ContentTaskUtils.isHidden(el),
+ `Expected ${hiddenElement} to be hidden.`
+ );
+ }
+
+ for (let opacityElement in toggleStylesForStage.opacities) {
+ let opacityThreshold =
+ toggleStylesForStage.opacities[opacityElement];
+ let el = shadowRoot.querySelector(opacityElement);
+
+ await ContentTaskUtils.waitForCondition(
+ () => {
+ let opacity = parseFloat(
+ this.content.getComputedStyle(el).opacity
+ );
+ return opacity >= opacityThreshold;
+ },
+ `Toggle element ${opacityElement} should have eventually reached ` +
+ `target opacity ${opacityThreshold}`,
+ 100,
+ 100
+ );
+
+ ok(true, "Toggle reached target opacity.");
+ }
+ }
+ let { videoID, toggleClientRect, toggleStylesForStage } = args;
+ let video = this.content.document.getElementById(videoID);
+ let shadowRoot = video.openOrClosedShadowRoot;
+
+ info("Creating a new button in the content window");
+ let button = this.content.document.createElement("button");
+ let buttonSelected = false;
+ button.ontouchstart = () => {
+ info("Button selected via touch event");
+ buttonSelected = true;
+ return true;
+ };
+ button.id = "testbutton";
+ button.style.backgroundColor = "red";
+ // Move button to the top for better visibility.
+ button.style.position = "absolute";
+ button.style.top = "0";
+ button.textContent = "test button";
+ this.content.document.body.appendChild(button);
+
+ await video.play();
+
+ info("Hover over the video to show the Picture-in-Picture toggle");
+ await EventUtils.synthesizeMouseAtCenter(
+ video,
+ { type: "mousemove" },
+ this.content.window
+ );
+ await EventUtils.synthesizeMouseAtCenter(
+ video,
+ { type: "mouseover" },
+ this.content.window
+ );
+
+ let toggleCenterX =
+ toggleClientRect.left + toggleClientRect.width / 2;
+ let toggleCenterY =
+ toggleClientRect.top + toggleClientRect.height / 2;
+
+ // We want to wait for the toggle to reach opacity so that we can select it.
+ info("Waiting for toggle to become fully visible");
+ await waitForToggleOpacity(shadowRoot, toggleStylesForStage);
+
+ info("Simulating touch event on PiP toggle");
+ let utils = EventUtils._getDOMWindowUtils(this.content.window);
+ let id = utils.DEFAULT_TOUCH_POINTER_ID;
+ let rx = 1;
+ let ry = 1;
+ let angle = 0;
+ let force = 1;
+ let tiltX = 0;
+ let tiltY = 0;
+ let twist = 0;
+
+ let defaultPrevented = utils.sendTouchEvent(
+ "touchstart",
+ [id],
+ [toggleCenterX],
+ [toggleCenterY],
+ [rx],
+ [ry],
+ [angle],
+ [force],
+ [tiltX],
+ [tiltY],
+ [twist],
+ false /* modifiers */
+ );
+ utils.sendTouchEvent(
+ "touchend",
+ [id],
+ [toggleCenterX],
+ [toggleCenterY],
+ [rx],
+ [ry],
+ [angle],
+ [force],
+ [tiltX],
+ [tiltY],
+ [twist],
+ false /* modifiers */
+ );
+
+ ok(
+ defaultPrevented,
+ "Touchstart event's default actions should be prevented"
+ );
+ ok(!video.paused, "Video should still be playing");
+
+ await ContentTaskUtils.waitForCondition(() => {
+ return video.isCloningElementVisually;
+ }, "Video is being cloned visually.");
+
+ let testButton = this.content.document.getElementById("testbutton");
+ let buttonRect = testButton.getBoundingClientRect();
+ let buttonCenterX = buttonRect.left + buttonRect.width / 2;
+ let buttonCenterY = buttonRect.top + buttonRect.height / 2;
+
+ info("Simulating touch event on new button");
+ defaultPrevented = utils.sendTouchEvent(
+ "touchstart",
+ [id],
+ [buttonCenterX],
+ [buttonCenterY],
+ [rx],
+ [ry],
+ [angle],
+ [force],
+ [tiltX],
+ [tiltY],
+ [twist],
+ false /* modifiers */
+ );
+ utils.sendTouchEvent(
+ "touchend",
+ [id],
+ [buttonCenterX],
+ [buttonCenterY],
+ [rx],
+ [ry],
+ [angle],
+ [force],
+ [tiltX],
+ [tiltY],
+ [twist],
+ false /* modifiers */
+ );
+
+ ok(
+ buttonSelected,
+ "Button in content window was selected via touchstart"
+ );
+ ok(
+ !defaultPrevented,
+ "Touchstart event's default actions should no longer be prevented"
+ );
+ }
+ );
+
+ try {
+ info("Picture-in-Picture window should open");
+ await BrowserTestUtils.waitForCondition(
+ () => Services.wm.getEnumerator(WINDOW_TYPE).hasMoreElements(),
+ "Found a Picture-in-Picture"
+ );
+ for (let win of Services.wm.getEnumerator(WINDOW_TYPE)) {
+ if (!win.closed) {
+ ok(true, "Found a Picture-in-Picture window as expected");
+ win.close();
+ }
+ }
+ } catch {
+ ok(false, "No Picture-in-Picture window found, which is unexpected");
+ }
+ }
+ );
+});