<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Test passing capture device IDs to getUserMedia</title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script>
    let deviceIds = [];

    if (window.testRunner)
        testRunner.setUserMediaPermission(true);

    promise_test(async (test) => {
        const devices = await navigator.mediaDevices.enumerateDevices();
        assert_true(devices.length <= 2, "before getting permission, at most 1 camera and 1 microphone are exposed");
        devices.forEach((device) => {
            assert_true(device.deviceId.length == 0 , "device.deviceId is empty before permission to capture");
        });
    }, "Device IDs should be empty initially");

    promise_test((test) => {
        return navigator.mediaDevices.getUserMedia({ audio:true, video:true })
            .then((stream) => {
                return navigator.mediaDevices.enumerateDevices();
            }).then(devices => {
                devices.forEach((device) => {
                    if (device.kind == "audiooutput")
                        return;
                    let kind = device.kind == "audioinput" ? "audio" : "video";
                    deviceIds.push({ type: kind, id : device.deviceId});
                });
            });
    }, "Collect device IDs");

    let constraints = { };

    promise_test((test) => {
        deviceIds.forEach((info) => {
            constraints[info.type] = { deviceId: { exact: info.id } };
        });
    
        var audioTrack, videoTrack;
        return navigator.mediaDevices.getUserMedia(constraints)
            .then((stream) => {
                assert_equals(stream.getAudioTracks().length, 1, "correct number of audio tracks");
                assert_equals(stream.getVideoTracks().length, 1, "correct number of audio tracks");

                videoTrack = stream.getVideoTracks()[0];
                audioTrack = stream.getAudioTracks()[0];
                return navigator.mediaDevices.enumerateDevices();
            }).then(devices => {
                var ids = devices.map(device => device.deviceId);
                assert_true(ids.indexOf(videoTrack.getSettings().deviceId) !== -1 , "deviceId for video track should be respected");
                assert_true(ids.indexOf(audioTrack.getSettings().deviceId) !== -1 , "deviceId for audio track should be respected");
            })

    }, "Pass device IDs as exact constraints");
    
    promise_test((test) => {
        deviceIds.forEach((info) => {
            constraints[info.type] = { deviceId: info.id };
        });
    
        return navigator.mediaDevices.getUserMedia(constraints)
            .then((stream) => {
                assert_equals(stream.getAudioTracks().length, 1, "correct number of audio tracks");
                assert_equals(stream.getVideoTracks().length, 1, "correct number of video tracks");
            })

    }, "Pass device IDs as optional constraints");

    promise_test(async (test) => {
        await navigator.mediaDevices.getUserMedia({ audio: {deviceId: {exact: ""}}});
        await navigator.mediaDevices.getUserMedia({ video: {deviceId: {exact: [""]}}});
        await navigator.mediaDevices.getUserMedia({ audio: {deviceId: {exact: undefined}}});

        await navigator.mediaDevices.getUserMedia({ audio: {deviceId: {exact: null}}}).then(assert_unreached, () => { });
        await navigator.mediaDevices.getUserMedia({ audio: {deviceId: {exact: "test"}}}).then(assert_unreached, () => { });
    }, "Exact device IDs with special values: empty string, null, undefined");

    promise_test(async (test) => {
        await navigator.mediaDevices.getUserMedia({video: true});
        const devices  = await navigator.mediaDevices.enumerateDevices();
        for (let device of devices) {
            if (device.kind === "audioinput") {
                const stream = await navigator.mediaDevices.getUserMedia({audio: {deviceId: device.deviceId}});
                assert_equals(stream.getAudioTracks()[0].getSettings().deviceId, device.deviceId, "Matching audio device id");
            } else if (device.kind === "videoinput") {
                const stream = await navigator.mediaDevices.getUserMedia({video: {deviceId: device.deviceId}});
                assert_equals(stream.getVideoTracks()[0].getSettings().deviceId, device.deviceId, "Matching video device id");
            }
        }
    }, "Ideal deviceId constraints");

    </script>
</head>
<body>
</body>
</html>
