summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/audio-output/setSinkId-manual.https.html
blob: a083cdf09232110039d3bb825e207c678b336114 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!doctype html>
<html>
<head>
<title>Test setSinkId behavior with permissions / device changes</title>
<link rel="author" title="Dominique Hazael-Massieux" href="mailto:dom@w3.org"/>
<link rel="help" href="https://www.w3.org/TR/audio-output/#dom-htmlmediaelement-setsinkid">
<meta name="timeout" content="long">

</head>
<body>
<h1 class="instructions">Description</h1>
<p class="instructions">This test checks that <code>setSinkId</code> follows the algorithm, this includes manually checking the proper rendering on new output devices.</p>
<p class="instructions">When prompted to access microphones, please accept as this is the only current way to get permissions for associated output devices.</p>
<p class="instructions">For each authorized output device, check that selecting it makes the audio beat rendered on the corresponding device.</p>
<p>Available but unauthorized devices (only those for which we can gain permission can be selected):</p>
<ul id="available"></ul>
<p>Authorized  devices:</p>
<ul id="authorized"></ul>
<audio controls id="beat" src="/media/sound_5.mp3" loop></audio>

<div id='log'></div>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
"use strict";

const is_output = d => d.kind === "audiooutput";
const by_id = (id) => d => d.groupId === id;
const is_input = d => d.kind === "audioinput";
const audio = document.getElementById("beat");
const available = document.getElementById("available");
const authorized = document.getElementById("authorized");

let outputList;

const selectDeviceTester = (t) => (e) => {
    const groupId = e.target.dataset["groupid"];
    const device = outputList.find(by_id(groupId));
    if (audio.paused) audio.play();
    promise_test(pt => audio.setSinkId(device.deviceId).then(() => {
        assert_equals(device.deviceId, audio.sinkId);

        const pass = document.createElement("button");
        const fail = document.createElement("button");

        const result = (bool) => () => {
            assert_true(bool, "Sound rendered on right device");
            fail.remove();
            pass.remove();
            audio.pause();
            e.target.checked = false;
            e.target.disabled = true;
            t.done();
        };

        pass.style.backgroundColor = "#0f0";
        pass.textContent = "\u2713 Sound plays on " + device.label;
        pass.addEventListener("click", result(true));

        fail.style.backgroundColor = "#f00";
        fail.textContent = "\u274C Sound doesn't play on " + device.label;
        fail.addEventListener("click", result(true));

        const container = e.target.parentNode.parentNode;
        container.appendChild(pass);
        container.appendChild(fail);
    }), "setSinkId for " + device.label + " resolves");
};

const addAuthorizedDevice = (groupId) => {
    const device = outputList.find(by_id(groupId));
    const async_t = async_test("Selecting output device " + device.label + " makes the audio rendered on the proper device");
    const li = document.createElement("li");
    const label = document.createElement("label");
    const input = document.createElement("input");
    input.type = "radio";
    input.name = "device";
    input.dataset["groupid"] = device.groupId;
    input.addEventListener("change", selectDeviceTester(async_t));
    const span = document.createElement("span");
    span.textContent = device.label;
    label.appendChild(input);
    label.appendChild(span);
    li.appendChild(label);
    authorized.appendChild(li);
};

const authorizeDeviceTester = (t) => (e) => {
    const groupId = e.target.dataset["groupid"];
    navigator.mediaDevices.getUserMedia({audio: {groupId}})
        .then( () => {
            addAuthorizedDevice(groupId);
            t.done();
        });
};

promise_test(gum =>
             navigator.mediaDevices.getUserMedia({audio: true}).then(
                 () => {
                     promise_test(t =>
                                  navigator.mediaDevices.enumerateDevices().then(list => {
                                      assert_not_equals(list.find(is_output), undefined, "media device list includes at least one audio output device");
                                      outputList = list.filter(is_output);
                                      outputList.forEach(d => {
                                          const li = document.createElement("li");
                                          assert_not_equals(d.label, "", "Audio Output Device Labels are available after permission grant");
                                          li.textContent = d.label;
                                          // Check permission
                                          promise_test(perm => navigator.permissions.query({name: "speaker", deviceId: d.deviceId}).then(({state}) => {
                                              if (state === "granted") {
                                                  addAuthorizedDevice(d.groupId);
                                              } else if (state === "prompt") {
                                                  const inp = list.find(inp => inp.kind === "audioinput" && inp.groupId === d.groupId);
                                                  if (inp || true) {
                                                      const async_t = async_test("Authorizing output devices via permission requests for microphones works");
                                                      const button = document.createElement("button");
                                                      button.textContent = "Authorize access";
                                                      button.dataset["groupid"] = d.groupId;
                                                      button.addEventListener("click", async_t.step_func_done(authorizeDeviceTester(async_t)));
                                                      li.appendChild(button);
                                                  }
                                                  available.appendChild(li);
                                              }
                                          }, () => {
                                                           // if we can't query the permission, we assume it's granted :/
                                                           addAuthorizedDevice(d.groupId);
                                                       })
                                                       , "Query permission to use " + d.label);
                                      });
                                  }), "List media devices");
                 }), "Authorize mike access");
</script>