mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 1535454 - Add some preliminary Picture-in-Picture automated tests. r=Felipe
Differential Revision: https://phabricator.services.mozilla.com/D23730 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
1dc9c72510
commit
fe0b02a356
@ -9,3 +9,7 @@ JAR_MANIFESTS += ['jar.mn']
|
||||
EXTRA_JS_MODULES += [
|
||||
'PictureInPicture.jsm',
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
'tests/browser.ini',
|
||||
]
|
||||
|
7
toolkit/components/pictureinpicture/tests/.eslintrc.js
Normal file
7
toolkit/components/pictureinpicture/tests/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
"extends": [
|
||||
"plugin:mozilla/browser-test"
|
||||
]
|
||||
};
|
12
toolkit/components/pictureinpicture/tests/browser.ini
Normal file
12
toolkit/components/pictureinpicture/tests/browser.ini
Normal file
@ -0,0 +1,12 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
head.js
|
||||
test-page.html
|
||||
test-video.mp4
|
||||
|
||||
prefs =
|
||||
media.videocontrols.picture-in-picture.enabled=true
|
||||
|
||||
[browser_cannotTriggerFromContent.js]
|
||||
[browser_closeTab.js]
|
||||
[browser_showMessage.js]
|
@ -0,0 +1,29 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that the MozTogglePictureInPicture event is ignored if
|
||||
* fired by unprivileged web content.
|
||||
*/
|
||||
add_task(async () => {
|
||||
await BrowserTestUtils.withNewTab({
|
||||
url: TEST_PAGE,
|
||||
gBrowser,
|
||||
}, async browser => {
|
||||
// For now, the easiest way to ensure that this didn't happen is to fail
|
||||
// if we receive the PictureInPicture:Request message.
|
||||
const MESSAGE = "PictureInPicture:Request";
|
||||
let sawMessage = false;
|
||||
let listener = msg => {
|
||||
sawMessage = true;
|
||||
};
|
||||
browser.messageManager.addMessageListener(MESSAGE, listener);
|
||||
await ContentTask.spawn(browser, null, async () => {
|
||||
content.wrappedJSObject.fireEvents();
|
||||
});
|
||||
browser.messageManager.removeMessageListener(MESSAGE, listener);
|
||||
ok(!sawMessage, "Got PictureInPicture:Request message unexpectedly.");
|
||||
});
|
||||
});
|
@ -0,0 +1,25 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that if the tab that's hosting a <video> that's opened in a
|
||||
* Picture-in-Picture window is closed, that the Picture-in-Picture
|
||||
* window is also closed.
|
||||
*/
|
||||
add_task(async () => {
|
||||
for (let videoID of ["with-controls", "no-controls"]) {
|
||||
info(`Testing ${videoID} case.`);
|
||||
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
|
||||
let browser = tab.linkedBrowser;
|
||||
|
||||
let pipWin = await triggerPictureInPicture(browser, videoID);
|
||||
ok(pipWin, "Got Picture-in-Picture window.");
|
||||
|
||||
let pipClosed = BrowserTestUtils.domWindowClosed(pipWin);
|
||||
BrowserTestUtils.removeTab(tab);
|
||||
await pipClosed;
|
||||
}
|
||||
});
|
@ -0,0 +1,39 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests that triggering Picture-in-Picture causes the Picture-in-Picture
|
||||
* window to be opened, and a message to be displayed in the original video
|
||||
* player area. Also ensures that once the Picture-in-Picture window is closed,
|
||||
* the video goes back to the original state.
|
||||
*/
|
||||
add_task(async () => {
|
||||
for (let videoID of ["with-controls", "no-controls"]) {
|
||||
info(`Testing ${videoID} case.`);
|
||||
|
||||
await BrowserTestUtils.withNewTab({
|
||||
url: TEST_PAGE,
|
||||
gBrowser,
|
||||
}, async browser => {
|
||||
let pipWin = await triggerPictureInPicture(browser, videoID);
|
||||
ok(pipWin, "Got Picture-in-Picture window.");
|
||||
|
||||
try {
|
||||
await assertShowingMessage(browser, videoID, true);
|
||||
} finally {
|
||||
let uaWidgetUpdate = BrowserTestUtils.waitForContentEvent(browser, "UAWidgetSetupOrChange");
|
||||
pipWin.close();
|
||||
await uaWidgetUpdate;
|
||||
}
|
||||
|
||||
// no-controls case is disabled until we ensure that there's a UAWidget for
|
||||
// the no-controls case on Desktop (which should be fixed as part of
|
||||
// bug 1535354).
|
||||
if (videoID !== "no-controls") {
|
||||
await assertShowingMessage(browser, videoID, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
66
toolkit/components/pictureinpicture/tests/head.js
Normal file
66
toolkit/components/pictureinpicture/tests/head.js
Normal file
@ -0,0 +1,66 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_ROOT = getRootDirectory(gTestPath).replace("chrome://mochitests/content", "http://example.com");
|
||||
const TEST_PAGE = TEST_ROOT + "test-page.html";
|
||||
const WINDOW_TYPE = "Toolkit:PictureInPicture";
|
||||
|
||||
/**
|
||||
* Given a browser and the ID for a <video> element, triggers
|
||||
* Picture-in-Picture for that <video>, and resolves with the
|
||||
* Picture-in-Picture window once it is ready to be used.
|
||||
*
|
||||
* @param {Element} browser The <xul:browser> hosting the <video>
|
||||
*
|
||||
* @param {String} videoID The ID of the video to trigger
|
||||
* Picture-in-Picture on.
|
||||
*
|
||||
* @returns Promise
|
||||
* @resolves With the Picture-in-Picture window when ready.
|
||||
*/
|
||||
async function triggerPictureInPicture(browser, videoID) {
|
||||
let domWindowOpened = BrowserTestUtils.domWindowOpened(null);
|
||||
let videoReady = ContentTask.spawn(browser, videoID, async videoID => {
|
||||
let video = content.document.getElementById(videoID);
|
||||
let event = new content.CustomEvent("MozTogglePictureInPicture", { bubbles: true });
|
||||
video.dispatchEvent(event);
|
||||
await ContentTaskUtils.waitForCondition(() => {
|
||||
return video.isCloningElementVisually;
|
||||
}, "Video is being cloned visually.");
|
||||
});
|
||||
let win = await domWindowOpened;
|
||||
await BrowserTestUtils.waitForEvent(win, "load");
|
||||
await videoReady;
|
||||
return win;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a browser and the ID for a <video> element, checks that the
|
||||
* video is showing the "This video is playing in Picture-in-Picture mode."
|
||||
* status message overlay.
|
||||
*
|
||||
* @param {Element} browser The <xul:browser> hosting the <video>
|
||||
*
|
||||
* @param {String} videoID The ID of the video to trigger
|
||||
* Picture-in-Picture on.
|
||||
*
|
||||
* @param {bool} expected True if we expect the message to be showing.
|
||||
*
|
||||
* @returns Promise
|
||||
* @resolves When the checks have completed.
|
||||
*/
|
||||
async function assertShowingMessage(browser, videoID, expected) {
|
||||
let showing = await ContentTask.spawn(browser, videoID, async videoID => {
|
||||
let video = content.document.getElementById(videoID);
|
||||
let shadowRoot = video.openOrClosedShadowRoot;
|
||||
let pipOverlay = shadowRoot.querySelector(".pictureInPictureOverlay");
|
||||
ok(pipOverlay, "Should be able to find Picture-in-Picture overlay.");
|
||||
|
||||
let rect = pipOverlay.getBoundingClientRect();
|
||||
return rect.height > 0 && rect.width > 0;
|
||||
});
|
||||
Assert.equal(showing, expected,
|
||||
"Video should be showing the expected state.");
|
||||
}
|
29
toolkit/components/pictureinpicture/tests/test-page.html
Normal file
29
toolkit/components/pictureinpicture/tests/test-page.html
Normal file
@ -0,0 +1,29 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Picture-in-Picture tests</title>
|
||||
</head>
|
||||
<style>
|
||||
video {
|
||||
display: block;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h1>Video with controls</h1>
|
||||
<video id="with-controls" src="test-video.mp4" controls loop="true"></video>
|
||||
<h1>Video without controls</h1>
|
||||
<video id="no-controls" src="test-video.mp4" loop="true"></video>
|
||||
|
||||
<script>
|
||||
function fireEvents() {
|
||||
for (let videoID of ["with-controls", "no-controls"]) {
|
||||
let video = document.getElementById(videoID);
|
||||
let event = new CustomEvent("MozTogglePictureInPicture", { bubbles: true });
|
||||
video.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
BIN
toolkit/components/pictureinpicture/tests/test-video.mp4
Normal file
BIN
toolkit/components/pictureinpicture/tests/test-video.mp4
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user