diff options
Diffstat (limited to '')
-rw-r--r-- | testing/web-platform/tests/screen-capture/getdisplaymedia.https.html | 279 |
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> |