<!doctype html>
<html>
<head>
<title>getUserMedia: test that mediaDevices.getUserMedia is present</title>
<link rel="author" title="Dr Alex Gouaillard" href="mailto:agouaillard@gmail.com"/>
<link rel="help" href="https://w3c.github.io/mediacapture-main/#mediadevices-interface-extensions">
<meta name='assert' content='Check that the mediaDevices.getUserMedia() method is present.'/>
</head>
<body>
<h1 class="instructions">Description</h1>
<p class="instructions">This test checks for the presence of the
<code>navigator.mediaDevices.getUserMedia</code> method.</p>
<div id='log'></div>
<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 src=permission-helper.js></script>
<script>
test(function () {
  assert_not_equals(navigator.mediaDevices.getUserMedia, undefined, "navigator.mediaDevices.getUserMedia exists.");
  // TODO: do some stuff with it
  assert_not_equals(navigator.mediaDevices.getSupportedConstraints, undefined, "navigator.mediaDevices.getSupportedConstraints exists.");
  var list = navigator.mediaDevices.getSupportedConstraints();
  // TODO: we are supposed to check that all values returned can be used in a constraint ....
  // NOTE: the current list of attributes that may or may not be here
  // ...   FF for example has many no tin that list, should we fail if an attribute is present but not listed in the specs?
  //   list.width
  //   list.height
  //   list.aspectRatio
  //   list.frameRate
  //   list.facingMode
  //   list.volume
  //   list.sampleRate
  //   list.sampleSize
  //   list.echoCancellation
  //   list.latency
  //   list.channelCount
  //   list.deviceId
  //   list.groupId
  }, "mediaDevices.getUserMedia() is present on navigator");

promise_test(async t => {
  // Both permissions are needed at some point, asking both at once
  await setMediaPermission();
  // A successful camera gUM call is needed to expose camera information
  const afterGum = await navigator.mediaDevices.getUserMedia({video: true});
  afterGum.getTracks()[0].stop();

  assert_true(navigator.mediaDevices.getSupportedConstraints()["groupId"],
    "groupId should be supported");
  const devices = await navigator.mediaDevices.enumerateDevices();
  for (const device of devices) {
    await navigator.mediaDevices.getUserMedia(
        {video: {groupId: {exact: device.groupId}}}).then(stream => {
      const found_device = devices.find(({deviceId}) =>
        deviceId == stream.getTracks()[0].getSettings().deviceId);
      assert_not_equals(found_device, undefined);
      assert_equals(found_device.kind, "videoinput");
      assert_equals(found_device.groupId, device.groupId);
      stream.getTracks().forEach(t => t.stop());
    }, error => {
      assert_equals(error.name, "OverconstrainedError");
      assert_equals(error.constraint, "groupId");
      const found_device = devices.find(element =>
        element.kind == "videoinput" && element.groupId == device.groupId);
      assert_equals(found_device, undefined);
    });
  }
}, 'groupId is correctly supported by getUserMedia() for video devices');

promise_test(async t => {
  // A successful microphone gUM call is needed to expose microphone information
  const afterGum = await navigator.mediaDevices.getUserMedia({audio: true});
  afterGum.getTracks()[0].stop();

  assert_true(navigator.mediaDevices.getSupportedConstraints()["groupId"],
    "groupId should be supported");
  const devices = await navigator.mediaDevices.enumerateDevices();
  for (const device of devices) {
    await navigator.mediaDevices.getUserMedia(
        {audio: {groupId: {exact: device.groupId}}}).then(stream => {
      const found_device = devices.find(({deviceId}) =>
        deviceId == stream.getTracks()[0].getSettings().deviceId);
      assert_not_equals(found_device, undefined);
      assert_equals(found_device.kind, "audioinput");
      assert_equals(found_device.groupId, device.groupId);
      stream.getTracks().forEach(t => t.stop());
    }, error => {
      assert_equals(error.name, "OverconstrainedError");
      assert_equals(error.constraint, "groupId");
      const found_device = devices.find(element =>
        element.kind == "audioinput" && element.groupId == device.groupId);
      assert_equals(found_device, undefined);
    });
  }
}, 'groupId is correctly supported by getUserMedia() for audio devices');

promise_test(async t => {
  assert_true(navigator.mediaDevices.getSupportedConstraints()["resizeMode"],
    "resizeMode should be supported");
  const stream = await navigator.mediaDevices.getUserMedia(
      { video: {resizeMode: {exact: 'none'}}});
  const [track] = stream.getVideoTracks();
  t.add_cleanup(() => track.stop());
  assert_equals(track.getSettings().resizeMode, 'none');
}, 'getUserMedia() supports setting none as resizeMode.');

promise_test(async t => {
  assert_true(navigator.mediaDevices.getSupportedConstraints()["resizeMode"],
    "resizeMode should be supported");
  const stream = await navigator.mediaDevices.getUserMedia(
      { video: {resizeMode: {exact: 'crop-and-scale'}}});
  const [track] = stream.getVideoTracks();
  t.add_cleanup(() => track.stop());
  assert_equals(track.getSettings().resizeMode, 'crop-and-scale');
}, 'getUserMedia() supports setting crop-and-scale as resizeMode.');

promise_test(async t => {
  assert_true(navigator.mediaDevices.getSupportedConstraints()["resizeMode"],
    "resizeMode should be supported");
  try {
    const stream = await navigator.mediaDevices.getUserMedia(
        { video: {resizeMode: {exact: 'INVALID'}}});
    t.add_cleanup(() => stream.getVideoTracks()[0].stop());
    t.unreached_func('getUserMedia() should fail with invalid resizeMode')();
  } catch (e) {
    assert_equals(e.name, 'OverconstrainedError');
    assert_equals(e.constraint, 'resizeMode');
  }
}, 'getUserMedia() fails with exact invalid resizeMode.');
</script>
</body>
</html>
