Bug 1550633 - part13.5 - wait text track element's 'load' event. r=jya

This patch do two things in order to trigger loading for track element and wait for correct event to check track's and cues' status after loading finished.

(1) listen track element's load event
There are some tests listening video's loadedmetadata, but it's wrong. The loading process of media element and track element are completely non-related.
If you would like to check track element's status, you should wait for track element's load event.

(2) enable track explictly
If the text track which has default attribute is added to the media element before the media element starts running automatic track selection [1], then it would be enable by the media element.
Otherwise, you have to enable track explicitly by changing its track mode.

[1] https://html.spec.whatwg.org/multipage/media.html#sourcing-out-of-band-text-tracks:text-track-7

Differential Revision: https://phabricator.services.mozilla.com/D31913

--HG--
extra : moz-landing-system : lando
This commit is contained in:
alwu 2019-05-23 09:03:14 +00:00
Родитель ca2b2b41e4
Коммит 580e319c3d
6 изменённых файлов: 391 добавлений и 350 удалений

Просмотреть файл

@ -10,34 +10,26 @@
<track src="bug883173.vtt" kind="subtitles" id="default" default>
</video>
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
let video = document.getElementById("v");
video.addEventListener("loadedmetadata",
function run_tests() {
let trackElement = document.getElementById("default");
// Re-queue run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
function runTest() {
let trackElement = document.getElementById("default");
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
var expected = [[1, 3], [1, 2], [2, 4], [2, 3], [3, 4]];
var cueList = trackElement.track.cues;
is(cueList.length, expected.length, "Cue list length should be 5.");
var expected = [[1, 3], [1, 2], [2, 4], [2, 3], [3, 4]];
var cueList = trackElement.track.cues;
is(cueList.length, expected.length, "Cue list length should be 5.");
for (var i = 0; i < expected.length; i++) {
is(cueList[i].startTime, expected[i][0], "Cue's start time should be " + expected[i][0]);
is(cueList[i].endTime, expected[i][1], "Cue's end time should be " + expected[i][1]);
}
SimpleTest.finish();
for (var i = 0; i < expected.length; i++) {
is(cueList[i].startTime, expected[i][0], "Cue's start time should be " + expected[i][0]);
is(cueList[i].endTime, expected[i][1], "Cue's end time should be " + expected[i][1]);
}
);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
onload = runTest;
</script>
</body>
</html>

Просмотреть файл

@ -3,6 +3,7 @@
<head>
<title>Test for Bug 895091 - Integrating vtt.js</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -11,17 +12,13 @@
<track src="long.vtt" kind="subtitles" id="track2">
</video>
<script type="text/javascript">
SimpleTest.waitForExplicitFinish();
let video = document.getElementById("v");
video.addEventListener("loadedmetadata", function run_tests() {
let trackElement = document.getElementById("track1");
let trackElementTwo = document.getElementById("track2");
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1 || trackElementTwo.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
var trackElement = document.getElementById("track1");
var trackElementTwo = document.getElementById("track2");
async function runTest() {
enableBothTracks();
await waitUntilBothTracksLoaded();
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
@ -34,7 +31,26 @@ video.addEventListener("loadedmetadata", function run_tests() {
is(trackElementTwo.track.cues.length, 2000, "Cue list length should be 2000.");
SimpleTest.finish();
});
}
SimpleTest.waitForExplicitFinish();
onload = runTest;
/**
* The following are test helper functions.
*/
function enableBothTracks() {
// All tracks are `disable` on default. As we won't start loading for disabled
// tracks, we have to change their mode in order to start loading.
trackElement.track.mode = "hidden";
trackElementTwo.track.mode = "hidden";
}
async function waitUntilBothTracksLoaded() {
info(`wait until both tracks finish loading`);
await Promise.all([once(trackElement, "load"), once(trackElementTwo, "load")]);
}
</script>
</body>
</html>

Просмотреть файл

@ -3,13 +3,16 @@
<head>
<title>Test for Bug 833386 - TextTrackList</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<video id="v">
<script type="text/javascript">
function runTest() {
var enabledTrackElement = null;
async function runTest() {
var video = document.getElementById("v");
isnot(video.textTracks, undefined, "HTMLMediaElement::TextTrack() property should be available.")
@ -18,6 +21,10 @@ function runTest() {
is(trackList.length, 0, "Length should be 0.");
ok(typeof video.addTextTrack == "function", "HTMLMediaElement::AddTextTrack() function should be available.")
// Insert some tracks in an order that is not sorted, we will test if they
// are sorted later.
info(`- Add a track element with label 'third' -`);
video.addTextTrack("subtitles", "third", "en-CA");
is(trackList.length, 1, "Length should be 1.");
@ -51,68 +58,84 @@ function runTest() {
is(textTrack.mode, value, message);
}
// Insert some tracks in an order that is not sorted, we will test if they
// are sorted later.
info(`- Add a track element with label 'first' -`);
var trackOne = document.createElement("track");
trackOne.label = "first";
trackOne.src = "basic.vtt";
trackOne.default = true;
trackOne.id = "2";
// The automatic track selection would choose the first track element with
// `default` attribute, so this track would be enable later.
enabledTrackElement = trackOne;
video.appendChild(trackOne);
info(`- Add a track element with label 'fourth' -`);
video.addTextTrack("subtitles", "fourth", "en-CA");
info(`- Add a track element with label 'second' -`);
var trackTwo = document.createElement("track");
trackTwo.label = "second";
trackTwo.src = "basic.vtt";
// Although this track has `default` attribute as well, it won't be enable by
// the automatic track selection because it's not the first default track in
// the media element's track list.
trackTwo.default = true;
video.appendChild(trackTwo);
video.src = "seek.webm";
video.preload = "metadata";
video.addEventListener("loadedmetadata", function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackOne.readyState == 1 || trackTwo.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackOne.readyState, 2, "First Track::ReadyState should be set to LOADED.");
is(trackTwo.readyState, 2, "Second Track::ReadyState should be set to LOADED.");
// We're testing two things here, firstly that tracks created from a track
// element have a default mode 'disabled' and tracks created with the
// 'addTextTrack' method have a default mode of 'hidden'.
// Secondly we're testing that the tracks are sorted properly.
// For the tracks to be sorted the first two tracks, added through a
// TrackElement, must occupy the first two indexes in their TrackElement
// tree order. The second two tracks, added through the 'addTextTrack'
// method, will occupy the last two indexes in the order that they were
// added in.
var trackData = [
{ label: "first", mode: "showing", id: "2" },
{ label: "second", mode: "disabled", id: "" },
{ label: "third", mode: "hidden", id: "" },
{ label: "fourth", mode: "hidden", id: "" }
];
is(video.textTracks.length, trackData.length, "TextTracks length should be " + trackData.length);
for (var i = 0; i < trackData.length; i++) {
var track = video.textTracks[i];
isnot(track, null, "Video should have a text track at index " + i);
var info = trackData[i];
for (var key in info) {
is(track[key], info[key], "Track at index " + i + " should have a '" + key + "'' property " +
"with a value of '" + info[key] + "'.");
}
}
SimpleTest.finish();
});
startLoadingVideo();
await waitUntilEnableTrackLoaded();
checkTracksStatus();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
onload = runTest;
/**
* The following are test helper functions.
*/
function startLoadingVideo() {
let video = document.getElementById("v");
video.src = "seek.webm";
video.preload = "metadata";
}
async function waitUntilEnableTrackLoaded() {
info(`wait until the enabled track finishes loading`);
await once(enabledTrackElement, "load");
is(enabledTrackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
}
function checkTracksStatus() {
// We're testing two things here,
// (1) the tracks created from a track element have a default mode 'disabled'
// and tracks created from 'addTextTrack' method have a default
// mode of 'hidden'.
// (2) we're testing that the tracks are sorted properly. For the tracks to
// be sorted the first two tracks, added through a TrackElement, must occupy
// the first two indexes in their TrackElement tree order. The second two
// tracks, added through the 'addTextTrack' method, will occupy the last two
// indexes in the order that they were added in.
let trackData = [
{ label: "first", mode: "showing", id: "2" },
{ label: "second", mode: "disabled", id: "" },
{ label: "third", mode: "hidden", id: "" },
{ label: "fourth", mode: "hidden", id: "" }
];
let video = document.getElementById("v");
is(video.textTracks.length, trackData.length,
`TextTracks length should be ${trackData.length}`);
for (let i = 0; i < trackData.length; i++) {
let track = video.textTracks[i];
isnot(track, null, `Video should have a text track at index ${i}`);
let info = trackData[i];
for (let key in info) {
is(track[key], info[key],
`Track at index ${i} should have a '${key}' property with a value of '${info[key]}'.`);
}
}
}
</script>
</body>
</html>

Просмотреть файл

@ -3,13 +3,14 @@
<head>
<title>Test for Bug 881976 - TextTrackCue Computed Position</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<video id="v" src="seek.webm" preload="metadata">
<script type="text/javascript">
function runTest() {
async function runTest() {
var video = document.getElementById("v");
// Check if adding a text track manually sets the TextTrackList correctly.
@ -22,31 +23,34 @@ function runTest() {
video.textTracks,
"The Track's TextTrackList should be the Video's TextTrackList.");
var trackElement = document.createElement("track");
trackElement.src = "basic.vtt";
trackElement.kind = "subtitles";
video.appendChild(trackElement);
video.addEventListener("loadedmetadata", function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == HTMLTrackElement.LOADING) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, HTMLTrackElement.LOADED,
"Track::ReadyState should be set to LOADED.");
is(SpecialPowers.unwrap(SpecialPowers.wrap(trackElement.track).textTrackList),
video.textTracks,
"TrackElement's Track's TextTrackList should be the Video's TextTrackList.");
SimpleTest.finish();
});
await addTrackViaTrackElement();
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
onload = runTest;
/**
* The following are test helper functions.
*/
async function addTrackViaTrackElement() {
// Check if loading a Track via a TrackElement sets the TextTrackList correctly.
let trackElement = document.createElement("track");
trackElement.src = "basic.vtt";
trackElement.kind = "subtitles";
trackElement.default = true;
video.appendChild(trackElement);
info(`wait until the track finishes loading`);
await once(trackElement, "load");
is(trackElement.readyState, HTMLTrackElement.LOADED,
"Track::ReadyState should be set to LOADED.");
is(SpecialPowers.unwrap(SpecialPowers.wrap(trackElement.track).textTrackList),
video.textTracks,
"TrackElement's Track's TextTrackList should be the Video's TextTrackList.");
}
</script>
</body>
</html>

Просмотреть файл

@ -3,6 +3,7 @@
<head>
<title>Test for Bug 833386 - HTMLTrackElement</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -10,245 +11,248 @@
<track src="basic.vtt" kind="subtitles" id="default" default>
</video>
<script type="text/javascript">
var video = document.getElementById("v");
var trackElement = document.getElementById("default");
function runTest() {
var trackElement = document.getElementById("default");
async function runTest() {
await waitUntiTrackLoaded();
video.addEventListener("loadedmetadata", function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
var cueList = trackElement.track.cues;
is(cueList.length, 6, "Cue list length should be 6.");
var cueList = trackElement.track.cues;
is(cueList.length, 6, "Cue list length should be 6.");
// Check that the typedef of TextTrackCue works in Gecko.
isnot(window.TextTrackCue, undefined, "TextTrackCue should be defined.");
isnot(window.VTTCue, undefined, "VTTCue should be defined.");
// Check that the typedef of TextTrackCue works in Gecko.
isnot(window.TextTrackCue, undefined, "TextTrackCue should be defined.");
isnot(window.VTTCue, undefined, "VTTCue should be defined.");
// Check if first cue was parsed correctly.
var cue = cueList[0];
ok(cue instanceof TextTrackCue, "Cue should be an instanceof TextTrackCue.");
ok(cue instanceof VTTCue, "Cue should be an instanceof VTTCue.");
is(cue.id, "1", "Cue's ID should be 1.");
is(cue.startTime, 0.5, "Cue's start time should be 0.5.");
is(cue.endTime, 0.7, "Cue's end time should be 0.7.");
is(cue.pauseOnExit, false, "Cue's pause on exit flag should be false.");
is(cue.text, "This", "Cue's text should be set correctly.");
is(cue.track, trackElement.track, "Cue's track should be defined.");
// Check if first cue was parsed correctly.
var cue = cueList[0];
ok(cue instanceof TextTrackCue, "Cue should be an instanceof TextTrackCue.");
ok(cue instanceof VTTCue, "Cue should be an instanceof VTTCue.");
is(cue.id, "1", "Cue's ID should be 1.");
is(cue.startTime, 0.5, "Cue's start time should be 0.5.");
is(cue.endTime, 0.7, "Cue's end time should be 0.7.");
is(cue.pauseOnExit, false, "Cue's pause on exit flag should be false.");
is(cue.text, "This", "Cue's text should be set correctly.");
is(cue.track, trackElement.track, "Cue's track should be defined.");
cue.track = null;
isnot(cue.track, null, "Cue's track should not be able to be set.");
cue.track = null;
isnot(cue.track, null, "Cue's track should not be able to be set.");
// Check that all cue times were not rounded
is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
is(cueList[2].startTime, 2, "Third cue's start time should be 2.");
is(cueList[2].endTime, 3.5, "Third cue's end time should be 3.5.");
is(cueList[3].startTime, 2.71, "Fourth cue's start time should be 2.71.");
is(cueList[3].endTime, 2.91, "Fourth cue's end time should be 2.91.");
is(cueList[4].startTime, 3.217, "Fifth cue's start time should be 3.217.");
is(cueList[4].endTime, 3.989, "Fifth cue's end time should be 3.989.");
is(cueList[5].startTime, 3.217, "Sixth cue's start time should be 3.217.");
is(cueList[5].endTime, 3.989, "Sixth cue's end time should be 3.989.");
// Check that Cue setters are working correctly.
cue.id = "Cue 01";
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
cue.startTime = 0.51;
is(cue.startTime, 0.51, "Cue's start time should be 0.51.");
cue.endTime = 0.71;
is(cue.endTime, 0.71, "Cue's end time should be 0.71.");
cue.pauseOnExit = true;
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
video.addEventListener("pause", function() {
video.play();
}, {once: true});
var exceptionHappened;
function checkPercentageValue(prop, initialVal) {
ok(prop in cue, prop + " should be a property on VTTCue.");
cue[prop] = initialVal;
is(cue[prop], initialVal, "Cue's " + prop + " should initially be " + initialVal);
[ 101, -1 ].forEach(function(val) {
exceptionHappened = false;
try {
cue[prop] = val;
} catch(e) {
exceptionHappened = true;
is(e.name, "IndexSizeError", "Should have thrown IndexSizeError.");
}
ok(exceptionHappened, "Exception should have happened.");
});
}
checkPercentageValue("size", 100.0);
cue.size = 50.5;
is(cue.size, 50.5, "Cue's size should be 50.5.")
// Check cue.position
checkPercentageValue("position", "auto");
cue.position = 50.5;
is(cue.position, 50.5, "Cue's position value should now be 50.5.");
ok(cue.snapToLines, "Cue's snapToLines should be set by set.");
cue.snapToLines = false;
ok(!cue.snapToLines, "Cue's snapToLines should not be set.");
function checkEnumValue(prop, initialVal, acceptedValues) {
ok(prop in cue, prop + " should be a property on VTTCue.");
is(cue[prop], initialVal, "Cue's " + prop + " should be " + initialVal);
cue[prop] = "bogus";
is(cue[prop], initialVal, "Cue's " + prop + " should be " + initialVal);
acceptedValues.forEach(function(val) {
cue[prop] = val;
is(cue[prop], val, "Cue's " + prop + " should be " + val);
if (typeof val === "string") {
cue[prop] = val.toUpperCase();
is(cue[prop], val, "Cue's " + prop + " should be " + val);
}
});
}
checkEnumValue("align", "center", [ "start", "left", "center", "right", "end" ]);
checkEnumValue("lineAlign", "start", [ "start", "center", "end" ]);
checkEnumValue("vertical", "", [ "", "lr", "rl" ]);
cue.lineAlign = "center";
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "START";
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "end";
is(cue.lineAlign, "end", "Cue's line align should be end.");
// Check that cue position align works properly
is(cue.positionAlign, "auto", "Cue's default position alignment should be auto.");
cue.positionAlign = "line-left";
is(cue.positionAlign, "line-left", "Cue's position align should be line-left.");
cue.positionAlign = "auto";
is(cue.positionAlign, "auto", "Cue's position align should be auto.");
cue.positionAlign = "line-right";
is(cue.positionAlign, "line-right", "Cue's position align should be line-right.");
// Check cue.line
is(cue.line, "auto", "Cue's line value should initially be auto.");
cue.line = 0.5;
is(cue.line, 0.5, "Cue's line value should now be 0.5.");
cue.line = "auto";
is(cue.line, "auto", "Cue's line value should now be auto.");
// Check that we can create and add new VTTCues
var vttCue = new VTTCue(3.999, 4, "foo");
is(vttCue.track, null, "Cue's track should be null.");
trackElement.track.addCue(vttCue);
is(cue.track, trackElement.track, "Cue's track should be defined.");
is(cueList.length, 7, "Cue list length should now be 7.");
// Check that new VTTCue was added correctly
cue = cueList[6];
is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
is(cue.endTime, 4, "Cue's end time should be 4.");
is(cue.text, "foo", "Cue's text should be foo.");
// Adding the same cue again should not increase the cue count.
trackElement.track.addCue(vttCue);
is(cueList.length, 7, "Cue list length should be 7.");
// Check that we are able to remove cues.
trackElement.track.removeCue(cue);
is(cueList.length, 6, "Cue list length should be 6.");
exceptionHappened = false;
try {
// We should not be able to remove a cue that is not in the list.
cue = new VTTCue(1, 2, "foo");
trackElement.track.removeCue(cue);
} catch (e) {
// "NotFoundError" should be thrown when trying to remove a cue that is
// not in the list.
is(e.name, "NotFoundError", "Should have thrown NotFoundError.");
exceptionHappened = true;
}
// If this is false then we did not throw an error and probably removed a cue
// when we shouln't have.
ok(exceptionHappened, "Exception should have happened.");
is(cueList.length, 6, "Cue list length should be 6.");
video.currentTime = 2;
isnot(trackElement.track.activeCues, null);
trackElement.track.mode = "disabled";
is(trackElement.track.activeCues, null);
trackElement.track.mode = "showing";
video.currentTime = 0;
var regionInfo = [
{ lines: 2, width: 30 },
{ lines: 4, width: 20 },
{ lines: 2, width: 30 }
];
for (var i = 0; i < regionInfo.length; i++) {
var cue = cueList[i];
isnot(cue.region, null, "Cue at " + i + " should have a region.");
for (var key in regionInfo[i]) {
is(cue.region[key], regionInfo[i][key], "Region should have a " + key +
" property with a value of " + regionInfo[i][key])
}
}
// Test TextTrack::ActiveCues.
var cueInfo = [
{ startTime: 0.51, endTime: 0.71, ids: ["Cue 01"] },
{ startTime: 0.72, endTime: 1.19, ids: [] },
{ startTime: 1.2, endTime: 1.9, ids: [2] },
{ startTime: 2, endTime: 2.4, ids: [2, 2.5] },
{ startTime: 2.41, endTime: 2.70, ids: [2.5] },
{ startTime: 2.71, endTime: 2.91, ids: [2.5, 3] },
{ startTime: 2.92, endTime: 3.216, ids: [2.5] },
{ startTime: 3.217, endTime: 3.5, ids: [2.5, 4, 5] },
{ startTime: 3.51, endTime: 3.989, ids: [4, 5] },
{ startTime: 3.99, endTime: 4, ids: [] }
];
video.addEventListener("timeupdate", function() {
var activeCues = trackElement.track.activeCues,
found = false,
playbackTime = video.currentTime;
for (var i = 0; i < cueInfo.length; i++) {
var cue = cueInfo[i];
if (playbackTime >= cue.startTime && playbackTime < cue.endTime) {
is(activeCues.length, cue.ids.length, "There should be " + cue.ids.length + " currently active cue(s).");
for (var j = 0; j < cue.ids.length; j++) {
isnot(activeCues.getCueById(cue.ids[j]), undefined, "The cue with ID " + cue.ids[j] + " should be active.");
}
break;
}
}
});
video.addEventListener("ended", function(){
SimpleTest.finish();
});
// Check that all cue times were not rounded
is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
is(cueList[2].startTime, 2, "Third cue's start time should be 2.");
is(cueList[2].endTime, 3.5, "Third cue's end time should be 3.5.");
is(cueList[3].startTime, 2.71, "Fourth cue's start time should be 2.71.");
is(cueList[3].endTime, 2.91, "Fourth cue's end time should be 2.91.");
is(cueList[4].startTime, 3.217, "Fifth cue's start time should be 3.217.");
is(cueList[4].endTime, 3.989, "Fifth cue's end time should be 3.989.");
is(cueList[5].startTime, 3.217, "Sixth cue's start time should be 3.217.");
is(cueList[5].endTime, 3.989, "Sixth cue's end time should be 3.989.");
// Check that Cue setters are working correctly.
cue.id = "Cue 01";
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
cue.startTime = 0.51;
is(cue.startTime, 0.51, "Cue's start time should be 0.51.");
cue.endTime = 0.71;
is(cue.endTime, 0.71, "Cue's end time should be 0.71.");
cue.pauseOnExit = true;
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
video.addEventListener("pause", function() {
video.play();
}, {once: true});
var exceptionHappened;
function checkPercentageValue(prop, initialVal) {
ok(prop in cue, prop + " should be a property on VTTCue.");
cue[prop] = initialVal;
is(cue[prop], initialVal, "Cue's " + prop + " should initially be " + initialVal);
[ 101, -1 ].forEach(function(val) {
exceptionHappened = false;
try {
cue[prop] = val;
} catch(e) {
exceptionHappened = true;
is(e.name, "IndexSizeError", "Should have thrown IndexSizeError.");
}
ok(exceptionHappened, "Exception should have happened.");
});
}
checkPercentageValue("size", 100.0);
cue.size = 50.5;
is(cue.size, 50.5, "Cue's size should be 50.5.")
// Check cue.position
checkPercentageValue("position", "auto");
cue.position = 50.5;
is(cue.position, 50.5, "Cue's position value should now be 50.5.");
ok(cue.snapToLines, "Cue's snapToLines should be set by set.");
cue.snapToLines = false;
ok(!cue.snapToLines, "Cue's snapToLines should not be set.");
function checkEnumValue(prop, initialVal, acceptedValues) {
ok(prop in cue, prop + " should be a property on VTTCue.");
is(cue[prop], initialVal, "Cue's " + prop + " should be " + initialVal);
cue[prop] = "bogus";
is(cue[prop], initialVal, "Cue's " + prop + " should be " + initialVal);
acceptedValues.forEach(function(val) {
cue[prop] = val;
is(cue[prop], val, "Cue's " + prop + " should be " + val);
if (typeof val === "string") {
cue[prop] = val.toUpperCase();
is(cue[prop], val, "Cue's " + prop + " should be " + val);
}
});
}
checkEnumValue("align", "center", [ "start", "left", "center", "right", "end" ]);
checkEnumValue("lineAlign", "start", [ "start", "center", "end" ]);
checkEnumValue("vertical", "", [ "", "lr", "rl" ]);
cue.lineAlign = "center";
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "START";
is(cue.lineAlign, "center", "Cue's line align should be center.");
cue.lineAlign = "end";
is(cue.lineAlign, "end", "Cue's line align should be end.");
// Check that cue position align works properly
is(cue.positionAlign, "auto", "Cue's default position alignment should be auto.");
cue.positionAlign = "line-left";
is(cue.positionAlign, "line-left", "Cue's position align should be line-left.");
cue.positionAlign = "auto";
is(cue.positionAlign, "auto", "Cue's position align should be auto.");
cue.positionAlign = "line-right";
is(cue.positionAlign, "line-right", "Cue's position align should be line-right.");
// Check cue.line
is(cue.line, "auto", "Cue's line value should initially be auto.");
cue.line = 0.5;
is(cue.line, 0.5, "Cue's line value should now be 0.5.");
cue.line = "auto";
is(cue.line, "auto", "Cue's line value should now be auto.");
// Check that we can create and add new VTTCues
var vttCue = new VTTCue(3.999, 4, "foo");
is(vttCue.track, null, "Cue's track should be null.");
trackElement.track.addCue(vttCue);
is(cue.track, trackElement.track, "Cue's track should be defined.");
is(cueList.length, 7, "Cue list length should now be 7.");
// Check that new VTTCue was added correctly
cue = cueList[6];
is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
is(cue.endTime, 4, "Cue's end time should be 4.");
is(cue.text, "foo", "Cue's text should be foo.");
// Adding the same cue again should not increase the cue count.
trackElement.track.addCue(vttCue);
is(cueList.length, 7, "Cue list length should be 7.");
// Check that we are able to remove cues.
trackElement.track.removeCue(cue);
is(cueList.length, 6, "Cue list length should be 6.");
exceptionHappened = false;
try {
// We should not be able to remove a cue that is not in the list.
cue = new VTTCue(1, 2, "foo");
trackElement.track.removeCue(cue);
} catch (e) {
// "NotFoundError" should be thrown when trying to remove a cue that is
// not in the list.
is(e.name, "NotFoundError", "Should have thrown NotFoundError.");
exceptionHappened = true;
}
// If this is false then we did not throw an error and probably removed a cue
// when we shouln't have.
ok(exceptionHappened, "Exception should have happened.");
is(cueList.length, 6, "Cue list length should be 6.");
video.currentTime = 2;
isnot(trackElement.track.activeCues, null);
trackElement.track.mode = "disabled";
is(trackElement.track.activeCues, null);
trackElement.track.mode = "showing";
video.currentTime = 0;
var regionInfo = [
{ lines: 2, width: 30 },
{ lines: 4, width: 20 },
{ lines: 2, width: 30 }
];
for (var i = 0; i < regionInfo.length; i++) {
var cue = cueList[i];
isnot(cue.region, null, "Cue at " + i + " should have a region.");
for (var key in regionInfo[i]) {
is(cue.region[key], regionInfo[i][key], "Region should have a " + key +
" property with a value of " + regionInfo[i][key])
}
}
// Test TextTrack::ActiveCues.
var cueInfo = [
{ startTime: 0.51, endTime: 0.71, ids: ["Cue 01"] },
{ startTime: 0.72, endTime: 1.19, ids: [] },
{ startTime: 1.2, endTime: 1.9, ids: [2] },
{ startTime: 2, endTime: 2.4, ids: [2, 2.5] },
{ startTime: 2.41, endTime: 2.70, ids: [2.5] },
{ startTime: 2.71, endTime: 2.91, ids: [2.5, 3] },
{ startTime: 2.92, endTime: 3.216, ids: [2.5] },
{ startTime: 3.217, endTime: 3.5, ids: [2.5, 4, 5] },
{ startTime: 3.51, endTime: 3.989, ids: [4, 5] },
{ startTime: 3.99, endTime: 4, ids: [] }
];
video.addEventListener("timeupdate", function() {
var activeCues = trackElement.track.activeCues,
found = false,
playbackTime = video.currentTime;
for (var i = 0; i < cueInfo.length; i++) {
var cue = cueInfo[i];
if (playbackTime >= cue.startTime && playbackTime < cue.endTime) {
is(activeCues.length, cue.ids.length, "There should be " + cue.ids.length + " currently active cue(s).");
for (var j = 0; j < cue.ids.length; j++) {
isnot(activeCues.getCueById(cue.ids[j]), undefined, "The cue with ID " + cue.ids[j] + " should be active.");
}
break;
}
}
});
video.addEventListener("ended", function(){
SimpleTest.finish();
});
video.play();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
runTest);
/**
* The following are test helper functions.
*/
async function waitUntiTrackLoaded() {
info(`wait until the track finishes loading`);
await once(trackElement, "load");
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
is(trackElement.track.cues.length, 6, "Cue list length should be 6.");
}
</script>
</body>
</html>

Просмотреть файл

@ -3,6 +3,7 @@
<head>
<title>Test for Bug 917945 - VTTRegion</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="manifest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -10,42 +11,43 @@
<track src="region.vtt" kind="subtitles" id="default" default>
</video>
<script type="text/javascript">
var trackElement = document.getElementById("default");
function runTest() {
var video = document.getElementById("v");
var trackElement = document.getElementById("default");
video.addEventListener("loadedmetadata", function run_tests() {
// Re-que run_tests() at the end of the event loop until the track
// element has loaded its data.
if (trackElement.readyState == 1) {
setTimeout(run_tests, 0);
return;
}
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
async function runTest() {
await waitUntiTrackLoaded();
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
var cues = trackElement.track.cues;
is(cues.length, 1, "Cue list length should be 1.");
// Set mode to hidden so that the active cue lists are being updated.
trackElement.track.mode = "hidden";
var region = cues[0].region;
isnot(region, null, "Region should not be null.");
is(region.width, 62, "Region width should be 50.");
is(region.lines, 5, "Region lines should be 5.");
is(region.regionAnchorX, 4, "Region regionAnchorX should be 4.");
is(region.regionAnchorY, 78, "Region regionAnchorY should be 78.");
is(region.viewportAnchorX, 10, "Region viewportAnchorX should be 10.");
is(region.viewportAnchorY, 90, "Region viewportAnchorY should be 90.");
is(region.scroll, "up", "Region scroll should be 'up'");
var cues = trackElement.track.cues;
is(cues.length, 1, "Cue list length should be 1.");
SimpleTest.finish();
});
var region = cues[0].region;
isnot(region, null, "Region should not be null.");
is(region.width, 62, "Region width should be 50.");
is(region.lines, 5, "Region lines should be 5.");
is(region.regionAnchorX, 4, "Region regionAnchorX should be 4.");
is(region.regionAnchorY, 78, "Region regionAnchorY should be 78.");
is(region.viewportAnchorX, 10, "Region viewportAnchorX should be 10.");
is(region.viewportAnchorY, 90, "Region viewportAnchorY should be 90.");
is(region.scroll, "up", "Region scroll should be 'up'");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
runTest);
/**
* The following are test helper functions.
*/
async function waitUntiTrackLoaded() {
info(`wait until the track finishes loading`);
await once(trackElement, "load");
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
}
</script>
</body>