<!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},
 {audio: false},
 {audio: true},
 {},
 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},
].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');

promise_test(async t => {
  const stream = await getDisplayMedia({video: true});
  t.add_cleanup(() => stopTracks(stream));
  const settings = stream.getVideoTracks()[0].getSettings();
  assert_any(
      assert_equals, settings.displaySurface,
      ['monitor', 'window', 'application', 'browser']);
  assert_any(assert_equals, settings.logicalSurface, [true, false]);
  assert_any(assert_equals, settings.cursor, ['never', 'always', 'motion']);
}, 'getDisplayMedia() with getSettings');

</script>
