summaryrefslogtreecommitdiffstats
path: root/browser/extensions/pictureinpicture/tests/browser/browser_mock_wrapper.js
blob: 6dcdd7536e765674e3b83fee27ee25f98009f2b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

/* import-globals-from ../../../../../toolkit/components/pictureinpicture/tests/head.js */

ChromeUtils.defineESModuleGetters(this, {
  TOGGLE_POLICIES: "resource://gre/modules/PictureInPictureControls.sys.mjs",
});

const TEST_URL =
  getRootDirectory(gTestPath).replace(
    "chrome://mochitests/content",
    "https://mochitest.youtube.com:443"
  ) + "test-mock-wrapper.html";
const TEST_URL_TOGGLE_VISIBILITY =
  getRootDirectory(gTestPath).replace(
    "chrome://mochitests/content",
    "https://mochitest.youtube.com:443"
  ) + "test-toggle-visibility.html";

/**
 * Tests the mock-wrapper.js video wrapper script selects the expected element
 * responsible for toggling the video player's mute status.
 */
add_task(async function test_mock_mute_button() {
  await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
    await ensureVideosReady(browser);

    // Open the video in PiP
    let videoID = "mock-video-controls";
    let pipWin = await triggerPictureInPicture(browser, videoID);
    ok(pipWin, "Got Picture-in-Picture window.");

    // Mute audio
    await toggleMute(browser, pipWin);
    ok(await isVideoMuted(browser, videoID), "The audio is muted.");

    await SpecialPowers.spawn(browser, [], async function () {
      let muteButton = content.document.querySelector(".mute-button");
      ok(
        muteButton.getAttribute("isMuted"),
        "muteButton has isMuted attribute."
      );
    });

    // Unmute audio
    await toggleMute(browser, pipWin);
    ok(!(await isVideoMuted(browser, videoID)), "The audio is playing.");

    await SpecialPowers.spawn(browser, [], async function () {
      let muteButton = content.document.querySelector(".mute-button");
      ok(
        !muteButton.getAttribute("isMuted"),
        "muteButton does not have isMuted attribute"
      );
    });

    // Close PiP window
    let pipClosed = BrowserTestUtils.domWindowClosed(pipWin);
    let closeButton = pipWin.document.getElementById("close");
    EventUtils.synthesizeMouseAtCenter(closeButton, {}, pipWin);
    await pipClosed;
  });
});

/**
 * Tests the mock-wrapper.js video wrapper script selects the expected element
 * responsible for toggling the video player's play/pause status.
 */
add_task(async function test_mock_play_pause_button() {
  await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
    await ensureVideosReady(browser);
    await setupVideoListeners(browser);

    // Open the video in PiP
    let videoID = "mock-video-controls";
    let pipWin = await triggerPictureInPicture(browser, videoID);
    ok(pipWin, "Got Picture-in-Picture window.");

    info("Test a wrapper method with a correct selector");
    // Play video
    let playbackPromise = waitForVideoEvent(browser, "playing");
    let playPause = pipWin.document.getElementById("playpause");
    EventUtils.synthesizeMouseAtCenter(playPause, {}, pipWin);
    await playbackPromise;
    ok(!(await isVideoPaused(browser, videoID)), "The video is playing.");

    info("Test a wrapper method with an incorrect selector");
    // Pause the video.
    let pausePromise = waitForVideoEvent(browser, "pause");
    EventUtils.synthesizeMouseAtCenter(playPause, {}, pipWin);
    await pausePromise;
    ok(await isVideoPaused(browser, videoID), "The video is paused.");

    // Close PiP window
    let pipClosed = BrowserTestUtils.domWindowClosed(pipWin);
    let closeButton = pipWin.document.getElementById("close");
    EventUtils.synthesizeMouseAtCenter(closeButton, {}, pipWin);
    await pipClosed;
  });
});

/**
 * Tests the mock-wrapper.js video wrapper script does not toggle mute/umute
 * state when increasing/decreasing the volume using the arrow keys.
 */
add_task(async function test_volume_change_with_keyboard() {
  await BrowserTestUtils.withNewTab(TEST_URL, async browser => {
    await ensureVideosReady(browser);
    await setupVideoListeners(browser);

    // Open the video in PiP
    let videoID = "mock-video-controls";
    let pipWin = await triggerPictureInPicture(browser, videoID);
    ok(pipWin, "Got Picture-in-Picture window.");

    // Initially set video to be muted
    await toggleMute(browser, pipWin);
    ok(await isVideoMuted(browser, videoID), "The audio is not playing.");

    // Decrease volume with arrow down
    EventUtils.synthesizeKey("KEY_ArrowDown", {}, pipWin);
    ok(!(await isVideoMuted(browser, videoID)), "The audio is playing.");

    // Increase volume with arrow up
    EventUtils.synthesizeKey("KEY_ArrowUp", {}, pipWin);
    ok(!(await isVideoMuted(browser, videoID)), "The audio is still playing.");

    await SpecialPowers.spawn(browser, [], async function () {
      let video = content.document.querySelector("video");
      ok(!video.muted, "Video should be unmuted.");
    });

    // Close PiP window
    let pipClosed = BrowserTestUtils.domWindowClosed(pipWin);
    let closeButton = pipWin.document.getElementById("close");
    EventUtils.synthesizeMouseAtCenter(closeButton, {}, pipWin);
    await pipClosed;
  });
});

function waitForVideoEvent(browser, eventType) {
  return BrowserTestUtils.waitForContentEvent(browser, eventType, true);
}

async function toggleMute(browser, pipWin) {
  let mutedPromise = waitForVideoEvent(browser, "volumechange");
  let audioButton = pipWin.document.getElementById("audio");
  EventUtils.synthesizeMouseAtCenter(audioButton, {}, pipWin);
  await mutedPromise;
}

async function setupVideoListeners(browser) {
  await SpecialPowers.spawn(browser, [], async function () {
    let video = content.document.querySelector("video");

    // Set a listener for "playing" event
    video.addEventListener("playing", async () => {
      info("Got playing event!");
      let playPauseButton =
        content.document.querySelector(".play-pause-button");
      ok(
        !playPauseButton.getAttribute("isPaused"),
        "playPauseButton does not have isPaused attribute."
      );
    });

    // Set a listener for "pause" event
    video.addEventListener("pause", async () => {
      info("Got pause event!");
      let playPauseButton =
        content.document.querySelector(".play-pause-button");
      // mock-wrapper's pause() method uses an invalid selector and should throw
      // an error. Test that the PiP wrapper uses the fallback pause() method.
      // This is to ensure PiP can handle cases where a site wrapper script is
      // incorrect, but does not break functionality altogether.
      ok(
        !playPauseButton.getAttribute("isPaused"),
        "playPauseButton still doesn't have isPaused attribute."
      );
    });
  });
}

/**
 * Tests that the mock-wrapper.js video wrapper hides the pip toggle when shouldHideToggle()
 * returns true.
 */
add_task(async function test_mock_should_hide_toggle() {
  await testToggle(TEST_URL_TOGGLE_VISIBILITY, {
    "mock-video-controls": { canToggle: false, policy: TOGGLE_POLICIES.HIDDEN },
  });
});

/**
 * Tests that the mock-wrapper.js video wrapper does not hide the pip toggle when shouldHideToggle()
 * returns false.
 */
add_task(async function test_mock_should_not_hide_toggle() {
  await testToggle(TEST_URL, {
    "mock-video-controls": { canToggle: true },
  });
});