summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/screen-capture/getdisplaymedia.https.html')
-rw-r--r--testing/web-platform/tests/screen-capture/getdisplaymedia.https.html279
1 files changed, 279 insertions, 0 deletions
diff --git a/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html b/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html
new file mode 100644
index 0000000000..095b98dea4
--- /dev/null
+++ b/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html
@@ -0,0 +1,279 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>getDisplayMedia</title>
+<meta name="timeout" content="long">
+<button id="button">User gesture</button>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+ 'use strict';
+test(() => {
+ assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
+}, "getDisplayMedia in navigator.mediaDevices");
+
+const stopTracks = stream => stream.getTracks().forEach(track => track.stop());
+const j = obj => JSON.stringify(obj);
+
+async function getDisplayMedia(constraints) {
+ const p = new Promise(r => button.onclick = r);
+ await test_driver.click(button);
+ await p;
+ return navigator.mediaDevices.getDisplayMedia(constraints);
+}
+
+promise_test(t => {
+ const p = navigator.mediaDevices.getDisplayMedia({video: true});
+ t.add_cleanup(async () => {
+ try { stopTracks(await p) } catch {}
+ });
+ // Race a settled promise to check that the returned promise is already
+ // rejected.
+ return promise_rejects_dom(
+ t, 'InvalidStateError', Promise.race([p, Promise.resolve()]),
+ 'getDisplayMedia should have returned an already-rejected promise.');
+}, `getDisplayMedia() must require user activation`);
+
+[
+ {video: true},
+ {video: true, audio: false},
+ {video: {}},
+ {audio: false},
+ {},
+ undefined
+].forEach(constraints => promise_test(async t => {
+ const stream = await getDisplayMedia(constraints);
+ t.add_cleanup(() => stopTracks(stream));
+ assert_equals(stream.getTracks().length, 1);
+ assert_equals(stream.getVideoTracks().length, 1);
+ assert_equals(stream.getAudioTracks().length, 0);
+}, `getDisplayMedia(${j(constraints)}) must succeed with video`));
+
+[
+ {video: false},
+ {video: {advanced: [{width: 320}]}},
+ {video: {width: {min: 320}}},
+ {video: {width: {exact: 320}}},
+ {video: {height: {min: 240}}},
+ {video: {height: {exact: 240}}},
+ {video: {frameRate: {min: 4}}},
+ {video: {frameRate: {exact: 4}}},
+ {video: false, audio: true},
+].forEach(constraints => promise_test(async t => {
+ await test_driver.bless('getDisplayMedia()');
+ const p = navigator.mediaDevices.getDisplayMedia(constraints);
+ t.add_cleanup(async () => {
+ try { stopTracks(await p) } catch {}
+ });
+ await promise_rejects_js(
+ t, TypeError, Promise.race([p, Promise.resolve()]),
+ 'getDisplayMedia should have returned an already-rejected promise.');
+}, `getDisplayMedia(${j(constraints)}) must fail with TypeError`));
+
+[
+ {video: true, audio: true},
+ {audio: true},
+].forEach(constraints => promise_test(async t => {
+ const stream = await getDisplayMedia(constraints);
+ t.add_cleanup(() => stopTracks(stream));
+ assert_greater_than_equal(stream.getTracks().length, 1);
+ assert_less_than_equal(stream.getTracks().length, 2);
+ assert_equals(stream.getVideoTracks().length, 1);
+ assert_less_than_equal(stream.getAudioTracks().length, 1);
+}, `getDisplayMedia(${j(constraints)}) must succeed with video maybe audio`));
+
+[
+ {width: {max: 360}},
+ {height: {max: 240}},
+ {width: {max: 360}, height: {max: 240}},
+ {frameRate: {max: 4}},
+ {frameRate: {max: 4}, width: {max: 360}},
+ {frameRate: {max: 4}, height: {max: 240}},
+ {frameRate: {max: 4}, width: {max: 360}, height: {max: 240}},
+].forEach(constraints => promise_test(async t => {
+ const stream = await getDisplayMedia({video: constraints});
+ t.add_cleanup(() => stopTracks(stream));
+ const {width, height, frameRate} = stream.getTracks()[0].getSettings();
+ assert_greater_than_equal(width, 1);
+ assert_greater_than_equal(height, 1);
+ assert_greater_than_equal(frameRate, 1);
+ if (constraints.width) {
+ assert_less_than_equal(width, constraints.width.max);
+ }
+ if (constraints.height) {
+ assert_less_than_equal(height, constraints.height.max);
+ }
+ if (constraints.frameRate) {
+ assert_less_than_equal(frameRate, constraints.frameRate.max);
+ }
+}, `getDisplayMedia({video: ${j(constraints)}}) must be constrained`));
+
+const someSizes = [
+ {width: 160},
+ {height: 120},
+ {width: 80},
+ {height: 60},
+ {width: 158},
+ {height: 118},
+];
+
+someSizes.forEach(constraints => promise_test(async t => {
+ const stream = await getDisplayMedia({video: constraints});
+ t.add_cleanup(() => stopTracks(stream));
+ const {width, height, frameRate} = stream.getTracks()[0].getSettings();
+ if (constraints.width) {
+ assert_equals(width, constraints.width);
+ } else {
+ assert_equals(height, constraints.height);
+ }
+ assert_greater_than_equal(frameRate, 1);
+}, `getDisplayMedia({video: ${j(constraints)}}) must be downscaled precisely`));
+
+promise_test(async t => {
+ const video = {height: 240};
+ const stream = await getDisplayMedia({video});
+ t.add_cleanup(() => stopTracks(stream));
+ const [track] = stream.getVideoTracks();
+ const {height} = track.getSettings();
+ assert_equals(height, video.height);
+ for (const constraints of someSizes) {
+ await track.applyConstraints(constraints);
+ const {width, height} = track.getSettings();
+ if (constraints.width) {
+ assert_equals(width, constraints.width);
+ } else {
+ assert_equals(height, constraints.height);
+ }
+ }
+}, `applyConstraints(width or height) must downscale precisely`);
+
+[
+ {video: {width: {max: 0}}},
+ {video: {height: {max: 0}}},
+ {video: {frameRate: {max: 0}}},
+ {video: {width: {max: -1}}},
+ {video: {height: {max: -1}}},
+ {video: {frameRate: {max: -1}}},
+].forEach(constraints => promise_test(async t => {
+ try {
+ stopTracks(await getDisplayMedia(constraints));
+ } catch (err) {
+ assert_equals(err.name, 'OverconstrainedError', err.message);
+ return;
+ }
+ assert_unreached('getDisplayMedia should have failed');
+}, `getDisplayMedia(${j(constraints)}) must fail with OverconstrainedError`));
+
+// Content shell picks a fake desktop device by default.
+promise_test(async t => {
+ const stream = await getDisplayMedia({video: true});
+ t.add_cleanup(() => stopTracks(stream));
+ assert_equals(stream.getVideoTracks().length, 1);
+ const track = stream.getVideoTracks()[0];
+ assert_equals(track.kind, "video");
+ assert_equals(track.enabled, true);
+ assert_equals(track.readyState, "live");
+ track.stop();
+ assert_equals(track.readyState, "ended");
+}, 'getDisplayMedia() resolves with stream with video track');
+
+{
+ const displaySurfaces = ['monitor', 'window', 'browser'];
+ displaySurfaces.forEach((displaySurface) => {
+ promise_test(async t => {
+ const stream = await getDisplayMedia({video: {displaySurface}});
+ t.add_cleanup(() => stopTracks(stream));
+ const settings = stream.getVideoTracks()[0].getSettings();
+ assert_equals(settings.displaySurface, displaySurface);
+ assert_any(assert_equals, settings.logicalSurface, [true, false]);
+ assert_any(assert_equals, settings.cursor, ['never', 'always', 'motion']);
+ assert_false("suppressLocalAudioPlayback" in settings);
+ }, `getDisplayMedia({"video":{"displaySurface":"${displaySurface}"}}) with getSettings`);
+ })
+}
+
+{
+ const properties = ["displaySurface"];
+ properties.forEach((property) => {
+ test(() => {
+ const supportedConstraints =
+ navigator.mediaDevices.getSupportedConstraints();
+ assert_true(supportedConstraints[property]);
+ }, property + " is supported");
+ });
+}
+
+[
+ {video: {displaySurface: "monitor"}},
+ {video: {displaySurface: "window"}},
+ {video: {displaySurface: "browser"}},
+ {selfBrowserSurface: "include"},
+ {selfBrowserSurface: "exclude"},
+ {surfaceSwitching: "include"},
+ {surfaceSwitching: "exclude"},
+ {systemAudio: "include"},
+ {systemAudio: "exclude"},
+].forEach(constraints => promise_test(async t => {
+ const stream = await getDisplayMedia(constraints);
+ t.add_cleanup(() => stopTracks(stream));
+}, `getDisplayMedia(${j(constraints)}) must succeed`));
+
+[
+ {selfBrowserSurface: "invalid"},
+ {surfaceSwitching: "invalid"},
+ {systemAudio: "invalid"},
+].forEach(constraints => promise_test(async t => {
+ await test_driver.bless('getDisplayMedia()');
+ const p = navigator.mediaDevices.getDisplayMedia(constraints);
+ t.add_cleanup(async () => {
+ try { stopTracks(await p) } catch {}
+ });
+ await promise_rejects_js(
+ t, TypeError, Promise.race([p, Promise.resolve()]),
+ 'getDisplayMedia should have returned an already-rejected promise.');
+}, `getDisplayMedia(${j(constraints)}) must fail with TypeError`));
+
+test(() => {
+ const supportedConstraints =
+ navigator.mediaDevices.getSupportedConstraints();
+ assert_true(supportedConstraints.suppressLocalAudioPlayback);
+}, "suppressLocalAudioPlayback is supported");
+
+{
+ const suppressLocalAudioPlaybacks = [true, false];
+ suppressLocalAudioPlaybacks.forEach((suppressLocalAudioPlayback) => {
+ promise_test(async (t) => {
+ const stream = await getDisplayMedia({
+ audio: { suppressLocalAudioPlayback },
+ });
+ t.add_cleanup(() => stopTracks(stream));
+ const [videoTrack] = stream.getVideoTracks();
+ assert_false("suppressLocalAudioPlayback" in videoTrack.getSettings());
+ const [audioTrack] = stream.getAudioTracks();
+ const audioTrackSettings = audioTrack.getSettings();
+ assert_true("suppressLocalAudioPlayback" in audioTrackSettings);
+ assert_equals(
+ audioTrackSettings.suppressLocalAudioPlayback,
+ suppressLocalAudioPlayback
+ );
+ await audioTrack.applyConstraints();
+ assert_true("suppressLocalAudioPlayback" in audioTrackSettings);
+ assert_equals(
+ audioTrackSettings.suppressLocalAudioPlayback,
+ suppressLocalAudioPlayback
+ );
+ }, `getDisplayMedia({"audio":{"suppressLocalAudioPlayback":${suppressLocalAudioPlayback}}}) with getSettings`);
+ });
+}
+
+promise_test(async t => {
+ const stream = await getDisplayMedia({video: true});
+ t.add_cleanup(() => stopTracks(stream));
+ const capabilities = stream.getVideoTracks()[0].getCapabilities();
+ assert_any(
+ assert_equals, capabilities.displaySurface,
+ ['monitor', 'window', 'browser']);
+}, 'getDisplayMedia() with getCapabilities');
+
+</script>