Update getUserMedia W3C conformance tests.
This CL updates these tests to the spec as of http://dev.w3.org/2011/webrtc/editor/archives/20130824/getusermedia.html There are still a lot of functionality that lacks testing. I've put a bunch of TODOs in there but I'm unlikely to get time to implement them all any time soon... TEST=local testing with Chrome Canary. BUG= R=phoglund@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2639004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5090 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
8bad50e845
commit
c4225b63bb
@ -1,7 +1,16 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
||||
<!--
|
||||
Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
|
||||
Use of this source code is governed by a BSD-style license
|
||||
that can be found in the LICENSE file in the root of the source
|
||||
tree. An additional intellectual property rights grant can be found
|
||||
in the file PATENTS. All contributing project authors may
|
||||
be found in the AUTHORS file in the root of the source tree.
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>GetUserMedia Browser Conformance Test</title>
|
||||
<title>getUserMedia Browser Conformance Test</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
@ -18,328 +27,37 @@ Notice that this requires the site you're browsing to use HTTPS.
|
||||
<p>This page contains a foundation of conformance tests that can be expanded
|
||||
to cover most things in the W3C specification of the Media Capture and Streams
|
||||
API.</p>
|
||||
<p>VERSION: These tests are based on the W3C Editor's Draft of 25 September
|
||||
2012.
|
||||
<p>VERSION: These tests are based on the W3C Editor's Draft of August 24th,
|
||||
2013
|
||||
(<a href="http://dev.w3.org/2011/webrtc/editor/archives/20130824/getusermedia.html">http://dev.w3.org/2011/webrtc/editor/archives/20130824/getusermedia.html</a>)
|
||||
<p>STATUS: In its current state, it only performs simple checks on the various
|
||||
attributes and methods of the objects exposed by the API. There's not much
|
||||
functionality tested so far.</p>
|
||||
<p>PREREQUISITES: You must have a webcam available on the machine that the
|
||||
test is executed at.</p>
|
||||
<p>PREFIX: These tests currently utilizes the <pre>webkit</pre> prefix, so
|
||||
that will have to changed in order to to test conformance with the actual
|
||||
standard!</p>
|
||||
<p>SPEC: <a href="http://dev.w3.org/2011/webrtc/editor/getusermedia.html">
|
||||
http://dev.w3.org/2011/webrtc/editor/getusermedia.html</a></p>
|
||||
functionality tested so far. The spec doesn't define if an attribute shall be
|
||||
owned by the object itself (<code>assert_own_propety</code>) or if it shall be
|
||||
inherited (<code>assert_inherits</code>). Since testharness.js doesn't offer
|
||||
any generic function that covers both, the method for verification is
|
||||
currently chosen according to the current Chrome implementation.</p>
|
||||
<p>PREFIXES: These tests currently utilizes the <code>adapter.js</code>
|
||||
script, which handle the prefixes used by different browsers.</p>
|
||||
<p>HOW TO RUN: The easiest way is to tell your browser to:
|
||||
<ul>
|
||||
<li>Provide a fake webcam (<code>--use-fake-ui-for-media-stream</code> in
|
||||
Chrome)</li>
|
||||
<li>Automatically allow access to the webcam
|
||||
(<code>--use-fake-device-for-media-stream</code> in Chrome)</li>
|
||||
<li>Allow loading HTML files from disk
|
||||
(<code>--allow-file-access-from-files</code> in Chrome)</li>
|
||||
</ul>
|
||||
Then just load this HTML file to execute the tests.</p>
|
||||
|
||||
<div id="log"></div>
|
||||
<video width="320" height="240" id="local-view" autoplay="autoplay"
|
||||
muted="true"></video>
|
||||
|
||||
<script src="https://w3c-test.org/resources/testharness.js"></script>
|
||||
<!-- Load the polyfill to switch-hit between Chrome and Firefox -->
|
||||
<script src="https://webrtc.googlecode.com/svn/stable/webrtc/test/manual/adapter.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
setup({timeout:10000});
|
||||
|
||||
// Helper functions to minimize code duplication.
|
||||
function failedCallback(test) {
|
||||
return test.step_func(function (error) {
|
||||
assert_unreached('Should not get an error callback');
|
||||
});
|
||||
}
|
||||
function invokeGetUserMedia(test, okCallback) {
|
||||
navigator.webkitGetUserMedia({ video: true, audio: true }, okCallback,
|
||||
failedCallback(test));
|
||||
}
|
||||
|
||||
// MediaStream.
|
||||
var mediaStreamTest = async_test('4.2 MediaStream');
|
||||
function verifyMediaStream(stream) {
|
||||
test(function () {
|
||||
assert_own_property(stream, 'label');
|
||||
assert_true(typeof stream.label === 'string');
|
||||
assert_readonly(stream, 'label');
|
||||
}, "MediaStream label attribute");
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'audioTracks');
|
||||
assert_true(typeof stream.audioTracks === 'object',
|
||||
'audioTracks is a MediaStreamTrackList');
|
||||
assert_readonly(stream, 'audioTracks');
|
||||
}, "MediaStream audioTracks attribute");
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'videoTracks');
|
||||
assert_true(typeof stream.videoTracks === 'object',
|
||||
'videoTracks is a MediaStreamTrackList');
|
||||
assert_readonly(stream, 'videoTracks');
|
||||
}, "MediaStream videoTracks attribute");
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'ended');
|
||||
assert_true(typeof stream.ended === 'boolean');
|
||||
assert_false(stream.ended);
|
||||
}, "MediaStream ended attribute");
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'onended');
|
||||
assert_true(stream.onended === null);
|
||||
}, "MediaStream onended EventHandler");
|
||||
}
|
||||
mediaStreamTest.step(function() {
|
||||
var okCallback = mediaStreamTest.step_func(function (localStream) {
|
||||
verifyMediaStream(localStream);
|
||||
|
||||
// Verify event handlers are working.
|
||||
localStream.onended = onendedCallback
|
||||
assert_false(localStream.ended);
|
||||
localStream.stop();
|
||||
});
|
||||
var onendedCallback = mediaStreamTest.step_func(function () {
|
||||
assert_true(localStream.ended);
|
||||
mediaStreamTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTest, okCallback);;
|
||||
});
|
||||
|
||||
// LocalMediaStream.
|
||||
var localMediaStreamTest = async_test('4.3 LocalMediaStream');
|
||||
localMediaStreamTest.step(function() {
|
||||
var okCallback = localMediaStreamTest.step_func(function (localStream) {
|
||||
assert_own_property(localStream, 'stop');
|
||||
assert_true(typeof localStream.stop === 'function');
|
||||
localMediaStreamTest.done();
|
||||
});
|
||||
invokeGetUserMedia(localMediaStreamTest, okCallback);
|
||||
});
|
||||
|
||||
// MediaStreamTrack.
|
||||
var mediaStreamTrackTest = async_test('4.4 MediaStreamTrack');
|
||||
function verifyTrack(type, track) {
|
||||
test(function () {
|
||||
assert_own_property(track, 'kind');
|
||||
assert_readonly(track, 'kind');
|
||||
}, 'MediaStreamTrack (' + type + ') kind attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'label');
|
||||
assert_true(typeof track.label === 'string',
|
||||
'label is an object (DOMString)');
|
||||
assert_readonly(track, 'label');
|
||||
}, 'MediaStreamTrack (' + type + ') label attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'enabled');
|
||||
assert_true(typeof track.enabled === 'boolean',
|
||||
'enabled is an object (DOMString)');
|
||||
assert_true(track.enabled, 'enabled property must be true initially');
|
||||
}, 'MediaStreamTrack (' + type + ') enabled attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'readyState');
|
||||
assert_true(typeof track.readyState === 'number');
|
||||
assert_readonly(track, 'readyState');
|
||||
assert_equals(track.readyState, track.LIVE,
|
||||
'readyState must be LIVE initially');
|
||||
}, 'MediaStreamTrack (' + type + ') readyState attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onmute');
|
||||
assert_true(track.onmute === null);
|
||||
}, 'MediaStreamTrack (' + type + ') onmute EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onunmute');
|
||||
assert_true(track.onunmute === null);
|
||||
}, 'MediaStreamTrack (' + type + ') onunmute EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onended');
|
||||
assert_true(track.onended === null);
|
||||
}, 'MediaStreamTrack (' + type + ') onended EventHandler');
|
||||
}
|
||||
mediaStreamTrackTest.step(function() {
|
||||
var okCallback = mediaStreamTrackTest.step_func(function (localStream) {
|
||||
verifyTrack('audio', localStream.audioTracks[0]);
|
||||
verifyTrack('video', localStream.videoTracks[0]);
|
||||
mediaStreamTrackTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTrackTest, okCallback);
|
||||
});
|
||||
|
||||
// URL tests.
|
||||
var createObjectURLTest = async_test('4.5 URL createObjectURL method');
|
||||
createObjectURLTest.step(function() {
|
||||
var okCallback = createObjectURLTest.step_func(function (localStream) {
|
||||
var url = webkitURL.createObjectURL(localStream);
|
||||
assert_true(typeof url === 'string');
|
||||
createObjectURLTest.done();
|
||||
});
|
||||
invokeGetUserMedia(createObjectURLTest, okCallback);
|
||||
});
|
||||
|
||||
// MediaStreamTrackList tests.
|
||||
var mediaStreamTrackListTest = async_test('4.6 MediaStreamTrackList');
|
||||
function verifyTrackList(type, trackList) {
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'length');
|
||||
assert_true(typeof trackList.length === 'number');
|
||||
assert_true(trackList.length === 1);
|
||||
}, 'MediaStreamTrackList (' + type + ') length attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'item');
|
||||
assert_true(typeof trackList.item === 'function');
|
||||
assert_true(trackList.item(0) !== null);
|
||||
}, 'MediaStreamTrackList (' + type + ') item() method');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'add');
|
||||
assert_true(typeof trackList.add === 'function');
|
||||
}, 'MediaStreamTrackList (' + type + ') add() method');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'remove');
|
||||
assert_true(typeof trackList.remove === 'function');
|
||||
}, 'MediaStreamTrackList (' + type + ') remove() method');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'onaddtrack');
|
||||
assert_true(trackList.onaddtrack === null);
|
||||
}, 'MediaStreamTrackList (' + type + ') onaddtrack EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(trackList, 'onremovetrack');
|
||||
assert_true(trackList.onremovetrack === null);
|
||||
}, 'MediaStreamTrackList (' + type + ') onremovetrack EventHandler');
|
||||
}
|
||||
mediaStreamTrackListTest.step(function() {
|
||||
var okCallback = mediaStreamTrackListTest.step_func(function (localStream) {
|
||||
verifyTrackList('audioTracks', localStream.audioTracks);
|
||||
verifyTrackList('videoTracks', localStream.videoTracks);
|
||||
mediaStreamTrackListTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTrackListTest, okCallback);
|
||||
});
|
||||
|
||||
// MediaStreams as Media Elements.
|
||||
var mediaElementsTest = async_test('4.7 MediaStreams as Media Elements');
|
||||
mediaElementsTest.step(function() {
|
||||
var okCallback = mediaElementsTest.step_func(function (localStream) {
|
||||
var url = webkitURL.createObjectURL(localStream);
|
||||
var videoTag = document.getElementById('local-view');
|
||||
videoTag.src = url;
|
||||
assert_equals(videoTag.currentSrc, url);
|
||||
assert_false(videoTag.preload);
|
||||
assert_equals(videoTag.buffered.length, 1);
|
||||
assert_equals(videoTag.buffered.start(0), 0);
|
||||
assert_equals(videoTag.buffered.end(0), 0);
|
||||
// Attempts to alter currentTime shall be ignored.
|
||||
assert_true(videoTag.currentTime >= 0);
|
||||
var time = videoTag.currentTime;
|
||||
videoTag.currentTime = time - 100;
|
||||
assert_true(videoTag.currentTime >= time);
|
||||
|
||||
assert_equals(videoTag.duration, infinity);
|
||||
assert_false(videoTag.seeking);
|
||||
assert_equals(videoTag.defaultPlaybackRate, 1.0);
|
||||
// Attempts to alter defaultPlaybackRate shall fail.
|
||||
assert_throws(videoTag.defaultPlaybackRate = 2.0);
|
||||
|
||||
assert_equals(videoTag.playbackRate, 1.0);
|
||||
// Attempts to alter playbackRate shall fail.
|
||||
assert_throws(videoTag.playbackRate = 2.0);
|
||||
|
||||
assert_equals(videoTag.played.length, 1);
|
||||
assert_equals(videoTag.played.start(0), 0);
|
||||
assert_true(videoTag.played.end(0) >= videoTag.currentTime);
|
||||
assert_equals(videoTag.seekable.length, 0);
|
||||
assert_equals(videoTag.seekable.start(), videoTag.currentTime);
|
||||
assert_equals(videoTag.seekable.end(), videoTag.currentTime);
|
||||
assert_equals(videoTag.startOffsetTime, NaN);
|
||||
assert_false(videoTag.loop);
|
||||
mediaElementsTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaElementsTest, okCallback);
|
||||
});
|
||||
|
||||
// NavigatorUserMedia.
|
||||
var getUserMediaTest = async_test('5.1 NavigatorUserMedia');
|
||||
getUserMediaTest.step(function() {
|
||||
var okCallback = getUserMediaTest.step_func(function (localStream) {
|
||||
assert_true(localStream !== null);
|
||||
getUserMediaTest.done();
|
||||
});
|
||||
|
||||
// boolean parameters, without failure callback:
|
||||
navigator.webkitGetUserMedia({ video: true, audio: true }, okCallback);
|
||||
navigator.webkitGetUserMedia({ video: true, audio: false }, okCallback);
|
||||
navigator.webkitGetUserMedia({ video: false, audio: true }, okCallback);
|
||||
|
||||
// boolean parameters, with failure callback:
|
||||
navigator.webkitGetUserMedia({ video: true, audio: true }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
navigator.webkitGetUserMedia({ video: true, audio: false }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
navigator.webkitGetUserMedia({ video: false, audio: true }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
});
|
||||
|
||||
// MediaStreamConstraints.
|
||||
var constraintsTest =
|
||||
async_test('5.2 MediaStreamConstraints');
|
||||
constraintsTest.step(function() {
|
||||
var okCallback = constraintsTest.step_func(function (localStream) {
|
||||
assert_true(localStream !== null);
|
||||
constraintsTest.done();
|
||||
});
|
||||
|
||||
// Constraints on video.
|
||||
// See http://code.google.com/p/webrtc-samples/source/browse/trunk/demos/html/constraints-and-stats.html
|
||||
// for more examples of constraints.
|
||||
var constraints = {};
|
||||
constraints.audio = true;
|
||||
constraints.video = { mandatory: {}, optional: [] };
|
||||
constraints.video.mandatory.minWidth = 640;
|
||||
constraints.video.mandatory.minHeight = 480;
|
||||
constraints.video.mandatory.minFrameRate = 15;
|
||||
|
||||
navigator.webkitGetUserMedia(constraints, okCallback,
|
||||
failedCallback(constraintsTest));
|
||||
});
|
||||
|
||||
// NavigatorUserMediaSuccessCallback.
|
||||
var successCallbackTest =
|
||||
async_test('5.3 NavigatorUserMediaSuccessCallback');
|
||||
successCallbackTest.step(function() {
|
||||
var okCallback = successCallbackTest.step_func(function (localStream) {
|
||||
assert_true(localStream !== null);
|
||||
assert_own_property(localStream, 'stop');
|
||||
successCallbackTest.done();
|
||||
});
|
||||
invokeGetUserMedia(successCallbackTest, okCallback);
|
||||
});
|
||||
|
||||
// NavigatorUserMediaError and NavigatorUserMediaErrorCallback.
|
||||
var errorCallbackTest =
|
||||
async_test('5.4 NavigatorUserMediaError and ' +
|
||||
'NavigatorUserMediaErrorCallback');
|
||||
errorCallbackTest.step(function() {
|
||||
var okCallback = errorCallbackTest.step_func(function (localStream) {
|
||||
assert_unreached('Should not get a success callback');
|
||||
});
|
||||
var errorCallback = errorCallbackTest.step_func(function (error) {
|
||||
assert_own_property(error, 'PERMISSION_DENIED');
|
||||
assert_readonly(error.PERMISSION_DENIED);
|
||||
assert_true(typeof error.PERMISSION_DENIED === 'number');
|
||||
assert_own_property(error, 'code');
|
||||
assert_readonly(error.code);
|
||||
assert_true(typeof error.code === 'number');
|
||||
|
||||
});
|
||||
// Setting both audio and video to false triggers an error callback.
|
||||
// TODO(kjellander): Figure out if there's a way in the spec to trigger an
|
||||
// error callback.
|
||||
navigator.webkitGetUserMedia({ video: false, audio: false }, okCallback,
|
||||
errorCallback);
|
||||
});
|
||||
</script>
|
||||
<video width="640" height="480" id="local-view" autoplay="autoplay"></video>
|
||||
<script src="getusermedia_conformance_test.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
451
webrtc/test/w3c/getusermedia_conformance_test.js
Normal file
451
webrtc/test/w3c/getusermedia_conformance_test.js
Normal file
@ -0,0 +1,451 @@
|
||||
// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
setup({timeout:10000});
|
||||
|
||||
// Helper functions to minimize code duplication.
|
||||
function failedCallback(test) {
|
||||
return test.step_func(function (error) {
|
||||
assert_unreached('Should not get an error callback');
|
||||
});
|
||||
}
|
||||
function invokeGetUserMedia(test, okCallback) {
|
||||
getUserMedia({ video: true, audio: true }, okCallback,
|
||||
failedCallback(test));
|
||||
}
|
||||
|
||||
// 4.2 MediaStream.
|
||||
var mediaStreamTest = async_test('4.2 MediaStream');
|
||||
|
||||
function verifyMediaStream(stream) {
|
||||
// TODO(kjellander): Add checks for default values where applicable.
|
||||
test(function () {
|
||||
assert_own_property(stream, 'id');
|
||||
assert_true(typeof stream.id === 'string');
|
||||
assert_readonly(stream, 'id');
|
||||
}, '[MediaStream] id attribute');
|
||||
|
||||
test(function () {
|
||||
assert_inherits(stream, 'getAudioTracks');
|
||||
assert_true(typeof stream.getAudioTracks === 'function');
|
||||
}, '[MediaStream] getAudioTracks function');
|
||||
|
||||
test(function () {
|
||||
assert_inherits(stream, 'getVideoTracks');
|
||||
assert_true(typeof stream.getVideoTracks === 'function');
|
||||
}, '[MediaStream] getVideoTracks function');
|
||||
|
||||
test(function () {
|
||||
assert_inherits(stream, 'getTrackById');
|
||||
assert_true(typeof stream.getTrackById === 'function');
|
||||
}, '[MediaStream] getTrackById function');
|
||||
|
||||
test(function () {
|
||||
assert_inherits(stream, 'addTrack');
|
||||
assert_true(typeof stream.addTrack === 'function');
|
||||
}, '[MediaStream] addTrack function');
|
||||
|
||||
test(function () {
|
||||
assert_inherits(stream, 'removeTrack');
|
||||
assert_true(typeof stream.removeTrack === 'function');
|
||||
}, '[MediaStream] removeTrack function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(stream, 'clone');
|
||||
assert_true(typeof stream.clone === 'function');
|
||||
}, '[MediaStream] clone function');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'ended');
|
||||
assert_true(typeof stream.ended === 'boolean');
|
||||
assert_readonly(stream, 'ended');
|
||||
}, '[MediaStream] ended attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'onended');
|
||||
assert_true(stream.onended === null);
|
||||
}, '[MediaStream] onended EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'onaddtrack');
|
||||
assert_true(stream.onaddtrack === null);
|
||||
}, '[MediaStream] onaddtrack EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(stream, 'onremovetrack');
|
||||
assert_true(stream.onremovetrack === null);
|
||||
}, '[MediaStream] onremovetrack EventHandler');
|
||||
}
|
||||
|
||||
mediaStreamTest.step(function() {
|
||||
var okCallback = mediaStreamTest.step_func(function (stream) {
|
||||
verifyMediaStream(stream);
|
||||
|
||||
var videoTracks = stream.getVideoTracks();
|
||||
assert_true(videoTracks.length > 0);
|
||||
|
||||
// Verify event handlers are working.
|
||||
stream.onaddtrack = onAddTrackCallback
|
||||
stream.onremovetrack = onRemoveTrackCallback
|
||||
stream.removeTrack(videoTracks[0]);
|
||||
stream.addTrack(videoTracks[0]);
|
||||
mediaStreamTest.done();
|
||||
});
|
||||
var onAddTrackCallback = mediaStreamTest.step_func(function () {
|
||||
// TODO(kjellander): verify number of tracks.
|
||||
mediaStreamTest.done();
|
||||
});
|
||||
var onRemoveTrackCallback = mediaStreamTest.step_func(function () {
|
||||
// TODO(kjellander): verify number of tracks.
|
||||
mediaStreamTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTest, okCallback);;
|
||||
});
|
||||
|
||||
// 4.3 MediaStreamTrack.
|
||||
var mediaStreamTrackTest = async_test('4.3 MediaStreamTrack');
|
||||
|
||||
function verifyTrack(type, track) {
|
||||
test(function () {
|
||||
assert_own_property(track, 'kind');
|
||||
assert_readonly(track, 'kind');
|
||||
assert_true(typeof track.kind === 'string',
|
||||
'kind is an object (DOMString)');
|
||||
}, '[MediaStreamTrack (' + type + ')] kind attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'id');
|
||||
assert_readonly(track, 'id');
|
||||
assert_true(typeof track.id === 'string',
|
||||
'id is an object (DOMString)');
|
||||
}, '[MediaStreamTrack (' + type + ')] id attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'label');
|
||||
assert_readonly(track, 'label');
|
||||
assert_true(typeof track.label === 'string',
|
||||
'label is an object (DOMString)');
|
||||
}, '[MediaStreamTrack (' + type + ')] label attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'enabled');
|
||||
assert_true(typeof track.enabled === 'boolean');
|
||||
assert_true(track.enabled, 'enabled property must be true initially');
|
||||
}, '[MediaStreamTrack (' + type + ')] enabled attribute');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_own_property(track, 'muted');
|
||||
assert_readonly(track, 'muted');
|
||||
assert_true(typeof track.muted === 'boolean');
|
||||
assert_false(track.muted, 'muted property must be false initially');
|
||||
}, '[MediaStreamTrack (' + type + ')] muted attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onmute');
|
||||
assert_true(track.onmute === null);
|
||||
}, '[MediaStreamTrack (' + type + ')] onmute EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onunmute');
|
||||
assert_true(track.onunmute === null);
|
||||
}, '[MediaStreamTrack (' + type + ')] onunmute EventHandler');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_own_property(track, '_readonly');
|
||||
assert_readonly(track, '_readonly');
|
||||
assert_true(typeof track._readonly === 'boolean');
|
||||
}, '[MediaStreamTrack (' + type + ')] _readonly attribute');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_own_property(track, 'remote');
|
||||
assert_readonly(track, 'remote');
|
||||
assert_true(typeof track.remote === 'boolean');
|
||||
}, '[MediaStreamTrack (' + type + ')] remote attribute');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'readyState');
|
||||
assert_readonly(track, 'readyState');
|
||||
assert_true(typeof track.readyState === 'string');
|
||||
// TODO(kjellander): verify the initial state.
|
||||
}, '[MediaStreamTrack (' + type + ')] readyState attribute');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_own_property(track, 'onstarted');
|
||||
assert_true(track.onstarted === null);
|
||||
}, '[MediaStreamTrack (' + type + ')] onstarted EventHandler');
|
||||
|
||||
test(function () {
|
||||
assert_own_property(track, 'onended');
|
||||
assert_true(track.onended === null);
|
||||
}, '[MediaStreamTrack (' + type + ')] onended EventHandler');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'getSourceInfos');
|
||||
assert_true(typeof track.getSourceInfos === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')]: getSourceInfos function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'constraints');
|
||||
assert_true(typeof track.constraints === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')]: constraints function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'states');
|
||||
assert_true(typeof track.states === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')]: states function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'capabilities');
|
||||
assert_true(typeof track.capabilities === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')]: capabilities function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'applyConstraints');
|
||||
assert_true(typeof track.applyConstraints === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')]: applyConstraints function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_own_property(track, 'onoverconstrained');
|
||||
assert_true(track.onoverconstrained === null);
|
||||
}, '[MediaStreamTrack (' + type + ')] onoverconstrained EventHandler');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'clone');
|
||||
assert_true(typeof track.clone === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')] clone function');
|
||||
|
||||
test(function () {
|
||||
// Missing in Chrome.
|
||||
assert_inherits(track, 'stop');
|
||||
assert_true(typeof track.stop === 'function');
|
||||
}, '[MediaStreamTrack (' + type + ')] stop function');
|
||||
};
|
||||
mediaStreamTrackTest.step(function() {
|
||||
var okCallback = mediaStreamTrackTest.step_func(function (stream) {
|
||||
verifyTrack('audio', stream.getAudioTracks()[0]);
|
||||
verifyTrack('video', stream.getVideoTracks()[0]);
|
||||
mediaStreamTrackTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTrackTest, okCallback);
|
||||
});
|
||||
|
||||
mediaStreamTrackTest.step(function() {
|
||||
var okCallback = mediaStreamTrackTest.step_func(function (stream) {
|
||||
// Verify event handlers are working.
|
||||
var track = stream.getVideoTracks()[0];
|
||||
track.onended = onendedCallback
|
||||
track.stop();
|
||||
mediaStreamTrackTest.done();
|
||||
});
|
||||
var onendedCallback = mediaStreamTrackTest.step_func(function () {
|
||||
assert_true(track.ended);
|
||||
mediaStreamTrackTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTrackTest, okCallback);
|
||||
});
|
||||
|
||||
// 4.4 MediaStreamTrackEvent tests.
|
||||
var mediaStreamTrackEventTest = async_test('4.4 MediaStreamTrackEvent');
|
||||
mediaStreamTrackEventTest.step(function() {
|
||||
var okCallback = mediaStreamTrackEventTest.step_func(function (stream) {
|
||||
// TODO(kjellander): verify attributes
|
||||
mediaStreamTrackEventTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaStreamTrackEventTest, okCallback);
|
||||
});
|
||||
|
||||
// 4.5 Video and Audio Tracks tests.
|
||||
var avTracksTest = async_test('4.5 Video and Audio Tracks');
|
||||
avTracksTest.step(function() {
|
||||
var okCallback = avTracksTest.step_func(function (stream) {
|
||||
// TODO(kjellander): verify attributes
|
||||
avTracksTest.done();
|
||||
});
|
||||
invokeGetUserMedia(avTracksTest, okCallback);
|
||||
});
|
||||
|
||||
// 5. The model: sources, sinks, constraints, and states
|
||||
|
||||
// 6. Source states
|
||||
// 6.1 Dictionary MediaSourceStates Members
|
||||
|
||||
// 7. Source capabilities
|
||||
// 7.1 Dictionary CapabilityRange Members
|
||||
// 7.2 CapabilityList array
|
||||
// 7.3 Dictionary AllVideoCapabilities Members
|
||||
// 7.4 Dictionary AllAudioCapabilities Members
|
||||
|
||||
// 8. URL tests.
|
||||
var createObjectURLTest = async_test('8.1 URL createObjectURL method');
|
||||
createObjectURLTest.step(function() {
|
||||
var okCallback = createObjectURLTest.step_func(function (stream) {
|
||||
var url = webkitURL.createObjectURL(stream);
|
||||
assert_true(typeof url === 'string');
|
||||
createObjectURLTest.done();
|
||||
});
|
||||
invokeGetUserMedia(createObjectURLTest, okCallback);
|
||||
});
|
||||
|
||||
// 9. MediaStreams as Media Elements.
|
||||
var mediaElementsTest = async_test('9. MediaStreams as Media Elements');
|
||||
|
||||
function verifyVideoTagWithStream(videoTag) {
|
||||
test(function () {
|
||||
assert_equals(videoTag.buffered.length, 0);
|
||||
}, '[Video tag] buffered attribute');
|
||||
|
||||
test(function () {
|
||||
// Attempts to alter currentTime shall be ignored.
|
||||
assert_true(videoTag.currentTime >= 0);
|
||||
assert_throws('InvalidStateError',
|
||||
function () { videoTag.currentTime = 1234; },
|
||||
'Attempts to modify currentTime shall throw ' +
|
||||
'InvalidStateError');
|
||||
}, '[Video tag] currentTime attribute');
|
||||
|
||||
test(function () {
|
||||
assert_equals(videoTag.duration, Infinity, 'videoTag.duration');
|
||||
}, '[Video tag] duration attribute');
|
||||
|
||||
test(function () {
|
||||
assert_false(videoTag.seeking, 'videoTag.seeking');
|
||||
}, '[Video tag] seeking attribute');
|
||||
|
||||
test(function () {
|
||||
assert_equals(videoTag.defaultPlaybackRate, 1.0);
|
||||
assert_throws('DOMException',
|
||||
function () { videoTag.defaultPlaybackRate = 2.0; },
|
||||
'Attempts to alter videoTag.defaultPlaybackRate MUST fail');
|
||||
}, '[Video tag] defaultPlaybackRate attribute');
|
||||
|
||||
test(function () {
|
||||
assert_equals(videoTag.playbackRate, 1.0);
|
||||
assert_throws('DOMException',
|
||||
function () { videoTag.playbackRate = 2.0; },
|
||||
'Attempts to alter videoTag.playbackRate MUST fail');
|
||||
}, '[Video tag] playbackRate attribute');
|
||||
|
||||
test(function () {
|
||||
assert_equals(videoTag.played.length, 1, 'videoTag.played.length');
|
||||
assert_equals(videoTag.played.start(0), 0);
|
||||
assert_true(videoTag.played.end(0) >= videoTag.currentTime);
|
||||
}, '[Video tag] played attribute');
|
||||
|
||||
test(function () {
|
||||
assert_equals(videoTag.seekable.length, 0);
|
||||
assert_equals(videoTag.seekable.start(), videoTag.currentTime);
|
||||
assert_equals(videoTag.seekable.end(), videoTag.currentTime);
|
||||
assert_equals(videoTag.startDate, NaN, 'videoTag.startDate');
|
||||
}, '[Video tag] seekable attribute');
|
||||
|
||||
test(function () {
|
||||
assert_false(videoTag.loop);
|
||||
}, '[Video tag] loop attribute');
|
||||
};
|
||||
|
||||
mediaElementsTest.step(function() {
|
||||
var okCallback = mediaElementsTest.step_func(function (stream) {
|
||||
var videoTag = document.getElementById('local-view');
|
||||
// Call the polyfill wrapper to attach the media stream to this element.
|
||||
attachMediaStream(videoTag, stream);
|
||||
verifyVideoTagWithStream(videoTag);
|
||||
mediaElementsTest.done();
|
||||
});
|
||||
invokeGetUserMedia(mediaElementsTest, okCallback);
|
||||
});
|
||||
|
||||
// 11. Obtaining local multimedia content.
|
||||
|
||||
// 11.1 NavigatorUserMedia.
|
||||
var getUserMediaTest = async_test('11.1 NavigatorUserMedia');
|
||||
getUserMediaTest.step(function() {
|
||||
var okCallback = getUserMediaTest.step_func(function (stream) {
|
||||
assert_true(stream !== null);
|
||||
getUserMediaTest.done();
|
||||
});
|
||||
|
||||
// boolean parameters, without failure callback:
|
||||
getUserMedia({ video: true, audio: true }, okCallback);
|
||||
getUserMedia({ video: true, audio: false }, okCallback);
|
||||
getUserMedia({ video: false, audio: true }, okCallback);
|
||||
|
||||
// boolean parameters, with failure callback:
|
||||
getUserMedia({ video: true, audio: true }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
getUserMedia({ video: true, audio: false }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
getUserMedia({ video: false, audio: true }, okCallback,
|
||||
failedCallback(getUserMediaTest));
|
||||
});
|
||||
|
||||
// 11.2 MediaStreamConstraints.
|
||||
var constraintsTest = async_test('11.2 MediaStreamConstraints');
|
||||
constraintsTest.step(function() {
|
||||
var okCallback = constraintsTest.step_func(function (stream) {
|
||||
assert_true(stream !== null);
|
||||
constraintsTest.done();
|
||||
});
|
||||
|
||||
// Constraints on video.
|
||||
// See http://webrtc.googlecode.com/svn/trunk/samples/js/demos/html/constraints-and-stats.html
|
||||
// for more examples of constraints.
|
||||
var constraints = {};
|
||||
constraints.audio = true;
|
||||
constraints.video = { mandatory: {}, optional: [] };
|
||||
constraints.video.mandatory.minWidth = 640;
|
||||
constraints.video.mandatory.minHeight = 480;
|
||||
constraints.video.mandatory.minFrameRate = 15;
|
||||
|
||||
getUserMedia(constraints, okCallback, failedCallback(constraintsTest));
|
||||
});
|
||||
|
||||
// 11.3 NavigatorUserMediaSuccessCallback.
|
||||
var successCallbackTest =
|
||||
async_test('11.3 NavigatorUserMediaSuccessCallback');
|
||||
successCallbackTest.step(function() {
|
||||
var okCallback = successCallbackTest.step_func(function (stream) {
|
||||
assert_true(stream !== null);
|
||||
successCallbackTest.done();
|
||||
});
|
||||
invokeGetUserMedia(successCallbackTest, okCallback);
|
||||
});
|
||||
|
||||
// 11.4 NavigatorUserMediaError and NavigatorUserMediaErrorCallback.
|
||||
var errorCallbackTest = async_test('11.4 NavigatorUserMediaError and ' +
|
||||
'NavigatorUserMediaErrorCallback');
|
||||
errorCallbackTest.step(function() {
|
||||
var okCallback = errorCallbackTest.step_func(function (stream) {
|
||||
assert_unreached('Should not get a success callback');
|
||||
});
|
||||
var errorCallback = errorCallbackTest.step_func(function (error) {
|
||||
assert_own_property(error, 'name');
|
||||
assert_readonly(error.name);
|
||||
assert_true(typeof error.name === 'string');
|
||||
assert_equals(error.name, 'ConstraintNotSatisfiedError', 'error.name');
|
||||
errorCallbackTest.done();
|
||||
});
|
||||
// Setting both audio and video to false triggers an error callback.
|
||||
// TODO(kjellander): Figure out if there's a way in the spec to trigger an
|
||||
// error callback.
|
||||
|
||||
// TODO(kjellander): Investigate why the error callback is not called when
|
||||
// false/false is provided in Chrome.
|
||||
getUserMedia({ video: false, audio: false }, okCallback, errorCallback);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user