| <!DOCTYPE HTML> |
| <html> |
| <head> |
| <script src="../../resources/testharness.js"></script> |
| <script src="../../resources/testharnessreport.js"></script> |
| </head> |
| <body> |
| <script> |
| |
| // Formatting of promises is done according to |
| // https://www.chromium.org/blink/serviceworker/testing#TOC-Layout-Tests-Style |
| |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia({}) |
| .then(function(s) { |
| assert_unreached('getUserMedia should have failed'); |
| }) |
| .catch(function(e) { |
| assert_equals(e.name, 'TypeError'); |
| }); |
| }, 'getUserMedia() without any media types should fail'); |
| |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia({'audio': true}) |
| .then(function(s) { |
| // do nothing |
| }) |
| .catch(function(e) { |
| assert_unreached('getUserMedia should have succeeded'); |
| }); |
| }, 'getUserMedia() with audio=true should succeed'); |
| |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia( |
| {audio: {'mandatory': { 'valid_but_unsupported_1': 0}}}) |
| .then(function(s) { |
| assert_unreached('getUserMedia should have failed'); |
| }) |
| .catch(function(e) { |
| assert_equals(e.name, 'OverconstrainedError'); |
| assert_equals(e.constraint, 'valid_but_unsupported_1'); |
| }); |
| }, 'getUserMedia() with unsupported mandatory constraint should fail'); |
| |
| // The next tests document existing behavior. They seem non-conformant |
| // with the specs. |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia({video: {}}) |
| .then(function(s) { |
| assert_unreached('getUserMedia should have failed'); |
| }) |
| .catch(function(e) { |
| assert_equals(e.name, 'Error'); |
| }); |
| }, 'getUserMedia() with empty constraints (neither mandatory nor optional) should fail with Error'); |
| |
| // The following set of tests verify behavior when trying to use the |
| // dictionary form of constraints. The behaviors currently expected are: |
| // - Unknown names in dictionary: ignored - which means pass |
| // - Known names and legal syntax for value: pass |
| // All constraints allow a primitive value (boolean, string or number), |
| // and Javascript is capable of coercing just about anything into those values, |
| // so we never get TypeError thrown here. |
| // |
| // Tests that the values are parsed and returned correctly are in |
| // MediaStreamTrack-getConstraints.html. |
| |
| function check_constraints_fail(name, constraints, expected_error) { |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia({'video': constraints}) |
| .then(() => assert_unreached('getUserMedia should have failed'), |
| e => assert_equals(e.name, expected_error)); |
| }, name); |
| } |
| |
| function check_constraints_pass(name, constraints) { |
| promise_test(function() { |
| return navigator.mediaDevices.getUserMedia({'video': constraints}); |
| }, name); |
| } |
| |
| check_constraints_pass( |
| 'Constraint with unsupported name gets ignored', |
| {'unsupported_name': 47}); |
| |
| check_constraints_pass( |
| 'Constraint with exact Long value should be parsed', |
| {'height': {exact: 47}}); |
| check_constraints_pass( |
| 'Constraint with Long naked value should be parsed', |
| {height: 47}); |
| |
| check_constraints_pass( |
| 'echoCancellation constraint with boolean value should be parsed', |
| {'echoCancellation': {exact: true}}); |
| check_constraints_pass( |
| 'echoCancellation constraint with boolean naked value should be parsed', |
| {'echoCancellation': true}); |
| |
| check_constraints_pass( |
| 'autoGainControl constraint with boolean value should be parsed', |
| {'autoGainControl': {exact: true}}); |
| check_constraints_pass( |
| 'autoGainControl constraint with boolean naked value should be parsed', |
| {'autoGainControl': true}); |
| |
| check_constraints_pass( |
| 'noiseSuppression constraint with boolean value should be parsed', |
| {'noiseSuppression': {exact: true}}); |
| check_constraints_pass( |
| 'noiseSuppression constraint with boolean naked value should be parsed', |
| {'noiseSuppression': true}); |
| |
| check_constraints_pass( |
| 'Constraint with string value should work on exact with array', |
| {'facingMode': {ideal: ['user']}}); |
| |
| check_constraints_pass( |
| 'Constraint with exact string value should work', |
| {'facingMode': {ideal: 'user'}}); |
| |
| check_constraints_pass( |
| 'Constraint with naked string value should be parsed', |
| {'facingMode': 'user'}); |
| |
| check_constraints_fail( |
| 'Using both mandatory and height should give TypeError', |
| {'mandatory': {'height': '270'}, 'height': '270'}, 'TypeError'); |
| |
| promise_test(async t => { |
| let stream = await navigator.mediaDevices.getUserMedia( |
| {video: {width: 639, height: 479}}); |
| let track = stream.getVideoTracks()[0]; |
| let settings = track.getSettings(); |
| assert_equals(settings.width, 639); |
| assert_equals(settings.height, 479); |
| assert_equals(settings.resizeMode, "crop-and-scale"); |
| track.stop(); |
| |
| stream = await navigator.mediaDevices.getUserMedia( |
| {video: {width: 639, height: 479, resizeMode: {exact: "none"}}}); |
| track = stream.getVideoTracks()[0]; |
| settings = track.getSettings(); |
| // With rescaling disabled, a native resolution is used. |
| assert_equals(settings.width, 640); |
| assert_equals(settings.height, 480); |
| assert_equals(settings.resizeMode, "none"); |
| track.stop(); |
| |
| try { |
| stream = await navigator.mediaDevices.getUserMedia( |
| {video: {width: {exact: 639}, resizeMode: {exact: "none"}}}); |
| t.add_cleanup(()=>stream.getVideoTracks()[0].stop()); |
| t.step(() => assert_unreached('applyConstraints should have failed')); |
| } catch(e) { |
| assert_equals(e.name, 'OverconstrainedError'); |
| assert_equals(e.constraint, 'width'); |
| } |
| }, 'getUserMedia() resizeMode constraint'); |
| |
| </script> |
| </body> |
| </html> |