summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/audio-output/setSinkId-manual.https.html
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/audio-output/setSinkId-manual.https.html')
-rw-r--r--testing/web-platform/tests/audio-output/setSinkId-manual.https.html132
1 files changed, 132 insertions, 0 deletions
diff --git a/testing/web-platform/tests/audio-output/setSinkId-manual.https.html b/testing/web-platform/tests/audio-output/setSinkId-manual.https.html
new file mode 100644
index 0000000000..a083cdf092
--- /dev/null
+++ b/testing/web-platform/tests/audio-output/setSinkId-manual.https.html
@@ -0,0 +1,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>