diff options
Diffstat (limited to 'testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-sinkid-constructor.https.html')
-rw-r--r-- | testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-sinkid-constructor.https.html | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-sinkid-constructor.https.html b/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-sinkid-constructor.https.html new file mode 100644 index 0000000000..2dedd6cd36 --- /dev/null +++ b/testing/web-platform/tests/webaudio/the-audio-api/the-audiocontext-interface/audiocontext-sinkid-constructor.https.html @@ -0,0 +1,122 @@ +<!DOCTYPE html> +<head> +<title>Test AudioContext constructor with sinkId options</title> +</head> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +"use strict"; + +let outputDeviceList = null; +let firstDeviceId = null; + +navigator.mediaDevices.getUserMedia({audio: true}).then(() => { + navigator.mediaDevices.enumerateDevices().then((deviceList) => { + outputDeviceList = + deviceList.filter(({kind}) => kind === 'audiooutput'); + assert_greater_than(outputDeviceList.length, 1, + 'the system must have more than 1 device.'); + firstDeviceId = outputDeviceList[1].deviceId; + + // Run async tests concurrently. + async_test(t => testDefaultSinkId(t), + 'Setting sinkId to the empty string at construction should ' + + 'succeed.'); + async_test(t => testValidSinkId(t), + 'Setting sinkId with a valid device identifier at ' + + 'construction should succeed.'); + async_test(t => testAudioSinkOptions(t), + 'Setting sinkId with an AudioSinkOptions at construction ' + + 'should succeed.'); + async_test(t => testExceptions(t), + 'Invalid sinkId arguments should throw an appropriate ' + + 'exception.') + }); +}); + +// 1.2.1. AudioContext constructor +// https://webaudio.github.io/web-audio-api/#AudioContext-constructors + +// Step 10.1.1. If sinkId is equal to [[sink ID]], abort these substeps. +const testDefaultSinkId = (t) => { + // The initial `sinkId` is the empty string. This will cause the same value + // check. + const audioContext = new AudioContext({sinkId: ''}); + audioContext.addEventListener('statechange', () => { + t.step(() => { + assert_equals(audioContext.sinkId, ''); + assert_equals(audioContext.state, 'running'); + }); + audioContext.close(); + t.done(); + }, {once: true}); +}; + +// Step 10.1.2~3: See "Validating sinkId" tests below. + +// Step 10.1.4. If sinkId is a type of DOMString, set [[sink ID]] to sinkId and +// abort these substeps. +const testValidSinkId = (t) => { + const audioContext = new AudioContext({sinkId: firstDeviceId}); + audioContext.addEventListener('statechange', () => { + t.step(() => { + assert_true(audioContext.sinkId === firstDeviceId, + 'the context sinkId should match the given sinkId.'); + }); + audioContext.close(); + t.done(); + }, {once: true}); + t.step_timeout(t.unreached_func('onstatechange not fired or assert failed'), + 100); +}; + +// Step 10.1.5. If sinkId is a type of AudioSinkOptions, set [[sink ID]] to a +// new instance of AudioSinkInfo created with the value of type of sinkId. +const testAudioSinkOptions = (t) => { + const audioContext = new AudioContext({sinkId: {type: 'none'}}); + // The only signal we can use for the sinkId change after construction is + // `statechange` event. + audioContext.addEventListener('statechange', () => { + t.step(() => { + assert_equals(typeof audioContext.sinkId, 'object'); + assert_equals(audioContext.sinkId.type, 'none'); + }); + audioContext.close(); + t.done(); + }, {once: true}); + t.step_timeout(t.unreached_func('onstatechange not fired or assert failed'), + 100); +}; + +// 1.2.4. Validating sinkId +// https://webaudio.github.io/web-audio-api/#validating-sink-identifier + +// Step 3. If document is not allowed to use the feature identified by +// "speaker-selection", return a new DOMException whose name is +// "NotAllowedError". +// TODO: Due to the lack of implementation, this step is not tested. + +const testExceptions = (t) => { + t.step(() => { + // The wrong AudioSinkOption.type should cause a TypeError. + assert_throws_js(TypeError, () => { + const audioContext = new AudioContext({sinkId: {type: 'something_else'}}); + audioContext.close(); + }, 'An invalid AudioSinkOptions.type value should throw a TypeError ' + + 'exception.'); + }); + + t.step(() => { + // Step 4. If sinkIdArg is a type of DOMString but it is not equal to the + // empty string or it does not match any audio output device identified by + // the result that would be provided by enumerateDevices(), return a new + // DOMException whose name is "NotFoundError". + assert_throws_dom('NotFoundError', () => { + const audioContext = new AudioContext({sinkId: 'some_random_device_id'}); + audioContext.close(); + }, 'An invalid device identifier should throw a NotFoundError exception.'); + }); + t.done(); +}; +</script> +</html> |