4 <title>Test for Bug
833386 - HTMLTrackElement
</title>
5 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
6 <script type=
"text/javascript" src=
"manifest.js"></script>
7 <link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css"/>
10 <video id=
"v" src=
"seek.webm" preload=
"metadata">
11 <track src=
"basic.vtt" kind=
"subtitles" id=
"default" default
>
13 <script type=
"text/javascript">
15 * This test is used to test the VTTCue's different behaviors and check whether
16 * cues would be activatived correctly during video playback.
18 var video
= document
.getElementById("v");
19 var trackElement
= document
.getElementById("default");
21 async
function runTest() {
22 await
waitUntiTrackLoaded();
24 checkFirstCueParsedContent();
25 checkCueStartTimeAndEndtime();
26 checkCueSizeAndPosition();
27 checkCueSnapToLines();
28 checkCueAlignmentAndWritingDirection();
30 checkCreatingNewCue();
31 checkRemoveNonExistCue();
34 await
checkCActiveCuesDuringVideoPlaying();
38 SimpleTest
.waitForExplicitFinish();
43 * The following are test helper functions.
45 async
function waitUntiTrackLoaded() {
46 if (trackElement
.readyState
!= 2) {
47 info(`wait until the track finishes loading`);
48 await
once(trackElement
, "load");
50 is(trackElement
.readyState
, 2, "Track::ReadyState should be set to LOADED.");
51 is(trackElement
.track
.cues
.length
, 6, "Cue list length should be 6.");
54 function checkCueDefinition() {
55 // Check that the typedef of TextTrackCue works in Gecko.
56 isnot(window
.TextTrackCue
, undefined, "TextTrackCue should be defined.");
57 isnot(window
.VTTCue
, undefined, "VTTCue should be defined.");
60 function checkFirstCueParsedContent() {
61 // Check if first cue was parsed correctly.
62 const cue
= trackElement
.track
.cues
[0];
63 ok(cue
instanceof TextTrackCue
, "Cue should be an instanceof TextTrackCue.");
64 ok(cue
instanceof VTTCue
, "Cue should be an instanceof VTTCue.");
65 is(cue
.id
, "1", "Cue's ID should be 1.");
66 is(cue
.startTime
, 0.5, "Cue's start time should be 0.5.");
67 is(cue
.endTime
, 0.7, "Cue's end time should be 0.7.");
68 is(cue
.pauseOnExit
, false, "Cue's pause on exit flag should be false.");
69 is(cue
.text
, "This", "Cue's text should be set correctly.");
70 is(cue
.track
, trackElement
.track
, "Cue's track should be defined.");
72 isnot(cue
.track
, null, "Cue's track should not be able to be set.");
75 function checkCueStartTimeAndEndtime() {
76 const cueList
= trackElement
.track
.cues
;
77 // Check that all cue times were not rounded
78 is(cueList
[1].startTime
, 1.2, "Second cue's start time should be 1.2.");
79 is(cueList
[1].endTime
, 2.4, "Second cue's end time should be 2.4.");
80 is(cueList
[2].startTime
, 2, "Third cue's start time should be 2.");
81 is(cueList
[2].endTime
, 3.5, "Third cue's end time should be 3.5.");
82 is(cueList
[3].startTime
, 2.71, "Fourth cue's start time should be 2.71.");
83 is(cueList
[3].endTime
, 2.91, "Fourth cue's end time should be 2.91.");
84 is(cueList
[4].startTime
, 3.217, "Fifth cue's start time should be 3.217.");
85 is(cueList
[4].endTime
, 3.989, "Fifth cue's end time should be 3.989.");
86 is(cueList
[5].startTime
, 3.217, "Sixth cue's start time should be 3.217.");
87 is(cueList
[5].endTime
, 3.989, "Sixth cue's end time should be 3.989.");
89 // Check that Cue setters are working correctly.
90 const cue
= trackElement
.track
.cues
[0];
92 is(cue
.id
, "Cue 01", "Cue's ID should be 'Cue 01'.");
94 is(cue
.startTime
, 0.51, "Cue's start time should be 0.51.");
96 is(cue
.endTime
, 0.71, "Cue's end time should be 0.71.");
97 cue
.pauseOnExit
= true;
98 is(cue
.pauseOnExit
, true, "Cue's pause on exit flag should be true.");
99 video
.addEventListener("pause", function() {
104 function checkCueSizeAndPosition() {
105 function checkPercentageValue(prop
, initialVal
) {
106 ok(prop
in cue
, prop
+ " should be a property on VTTCue.");
107 cue
[prop
] = initialVal
;
108 is(cue
[prop
], initialVal
, `Cue's ${prop} should initially be ${initialVal}`);
109 [ 101, -1 ].forEach(function(val
) {
110 let exceptionHappened
= false;
114 exceptionHappened
= true;
115 is(e
.name
, "IndexSizeError", "Should have thrown IndexSizeError.");
117 ok(exceptionHappened
, "Exception should have happened.");
121 const cue
= trackElement
.track
.cues
[0];
122 checkPercentageValue("size", 100.0);
124 is(cue
.size
, 50.5, "Cue's size should be 50.5.")
126 // Check cue.position
127 checkPercentageValue("position", "auto");
129 is(cue
.position
, 50.5, "Cue's position value should now be 50.5.");
132 function checkCueSnapToLines() {
133 const cue
= trackElement
.track
.cues
[0];
134 ok(cue
.snapToLines
, "Cue's snapToLines should be set by set.");
135 cue
.snapToLines
= false;
136 ok(!cue
.snapToLines
, "Cue's snapToLines should not be set.");
139 function checkCueAlignmentAndWritingDirection() {
140 function checkEnumValue(prop
, initialVal
, acceptedValues
) {
141 ok(prop
in cue
, `${prop} should be a property on VTTCue.`);
142 is(cue
[prop
], initialVal
, `Cue's ${prop} should be ${initialVal}`);
144 is(cue
[prop
], initialVal
, `Cue's ${prop} should be ${initialVal}`);
145 acceptedValues
.forEach(function(val
) {
147 is(cue
[prop
], val
, `Cue's ${prop} should be ${val}`);
148 if (typeof val
=== "string") {
149 cue
[prop
] = val
.toUpperCase();
150 is(cue
[prop
], val
, `Cue's ${prop} should be ${val}`);
155 const cue
= trackElement
.track
.cues
[0];
156 checkEnumValue("align", "center", [ "start", "left", "center", "right", "end" ]);
157 checkEnumValue("lineAlign", "start", [ "start", "center", "end" ]);
158 checkEnumValue("vertical", "", [ "", "lr", "rl" ]);
160 cue
.lineAlign
= "center";
161 is(cue
.lineAlign
, "center", "Cue's line align should be center.");
162 cue
.lineAlign
= "START";
163 is(cue
.lineAlign
, "center", "Cue's line align should be center.");
164 cue
.lineAlign
= "end";
165 is(cue
.lineAlign
, "end", "Cue's line align should be end.");
167 // Check that cue position align works properly
168 is(cue
.positionAlign
, "auto", "Cue's default position alignment should be auto.");
170 cue
.positionAlign
= "line-left";
171 is(cue
.positionAlign
, "line-left", "Cue's position align should be line-left.");
172 cue
.positionAlign
= "auto";
173 is(cue
.positionAlign
, "auto", "Cue's position align should be auto.");
174 cue
.positionAlign
= "line-right";
175 is(cue
.positionAlign
, "line-right", "Cue's position align should be line-right.");
178 function checkCueLine() {
179 const cue
= trackElement
.track
.cues
[0];
181 is(cue
.line
, "auto", "Cue's line value should initially be auto.");
183 is(cue
.line
, 0.5, "Cue's line value should now be 0.5.");
185 is(cue
.line
, "auto", "Cue's line value should now be auto.");
188 function checkCreatingNewCue() {
189 const cueList
= trackElement
.track
.cues
;
191 // Check that we can create and add new VTTCues
192 let vttCue
= new VTTCue(3.999, 4, "foo");
193 is(vttCue
.track
, null, "Cue's track should be null.");
194 trackElement
.track
.addCue(vttCue
);
195 is(vttCue
.track
, trackElement
.track
, "Cue's track should be defined.");
196 is(cueList
.length
, 7, "Cue list length should now be 7.");
198 // Check that new VTTCue was added correctly
199 let cue
= cueList
[6];
200 is(cue
.startTime
, 3.999, "Cue's start time should be 3.999.");
201 is(cue
.endTime
, 4, "Cue's end time should be 4.");
202 is(cue
.text
, "foo", "Cue's text should be foo.");
204 // Adding the same cue again should not increase the cue count.
205 trackElement
.track
.addCue(vttCue
);
206 is(cueList
.length
, 7, "Cue list length should be 7.");
208 // Check that we are able to remove cues.
209 trackElement
.track
.removeCue(cue
);
210 is(cueList
.length
, 6, "Cue list length should be 6.");
213 function checkRemoveNonExistCue() {
214 is(trackElement
.track
.cues
.length
, 6, "Cue list length should be 6.");
215 let exceptionHappened
= false;
217 // We should not be able to remove a cue that is not in the list.
218 trackElement
.track
.removeCue(new VTTCue(1, 2, "foo"));
220 // "NotFoundError" should be thrown when trying to remove a cue that is
222 is(e
.name
, "NotFoundError", "Should have thrown NotFoundError.");
223 exceptionHappened
= true;
225 // If this is false then we did not throw an error and probably removed a cue
226 // when we shouln't have.
227 ok(exceptionHappened
, "Exception should have happened.");
228 is(trackElement
.track
.cues
.length
, 6, "Cue list length should still be 6.");
231 function checkActiveCues() {
232 video
.currentTime
= 2;
233 isnot(trackElement
.track
.activeCues
, null);
235 trackElement
.track
.mode
= "disabled";
236 is(trackElement
.track
.activeCues
, null, "No active cue when track is disabled.");
237 trackElement
.track
.mode
= "showing";
240 function checkCueRegion() {
242 { lines
: 2, width
: 30 },
243 { lines
: 4, width
: 20 },
244 { lines
: 2, width
: 30 }
247 for (let i
= 0; i
< regionInfo
.length
; i
++) {
248 let cue
= trackElement
.track
.cues
[i
];
249 isnot(cue
.region
, null, `Cue at ${i} should have a region.`);
250 for (let key
in regionInfo
[i
]) {
251 is(cue
.region
[key
], regionInfo
[i
][key
],
252 `Region should have a ${key} property with a value of ${regionInfo[i][key]}`);
257 async
function checkCActiveCuesDuringVideoPlaying() {
258 // Test TextTrack::ActiveCues.
260 { startTime
: 0.51, endTime
: 0.71, ids
: ["Cue 01"] },
261 { startTime
: 0.72, endTime
: 1.19, ids
: [] },
262 { startTime
: 1.2, endTime
: 1.9, ids
: [2] },
263 { startTime
: 2, endTime
: 2.4, ids
: [2, 2.5] },
264 { startTime
: 2.41, endTime
: 2.70, ids
: [2.5] },
265 { startTime
: 2.71, endTime
: 2.91, ids
: [2.5, 3] },
266 { startTime
: 2.92, endTime
: 3.216, ids
: [2.5] },
267 { startTime
: 3.217, endTime
: 3.5, ids
: [2.5, 4, 5] },
268 { startTime
: 3.51, endTime
: 3.989, ids
: [4, 5] },
269 { startTime
: 3.99, endTime
: 4, ids
: [] }
272 video
.addEventListener("timeupdate", function() {
273 let activeCues
= trackElement
.track
.activeCues
,
274 playbackTime
= video
.currentTime
;
276 for (let i
= 0; i
< cueInfo
.length
; i
++) {
277 let cue
= cueInfo
[i
];
278 if (playbackTime
>= cue
.startTime
&& playbackTime
< cue
.endTime
) {
279 is(activeCues
.length
, cue
.ids
.length
, `There should be ${cue.ids.length} currently active cue(s).`);
280 for (let j
= 0; j
< cue
.ids
.length
; j
++) {
281 isnot(activeCues
.getCueById(cue
.ids
[j
]), undefined,
282 `The cue with ID ${cue.ids[j]} should be active.`);
289 info(`start video from 0s.`);
290 video
.currentTime
= 0;
292 await
once(video
, "playing");
293 info(`video starts playing.`);
294 await
once(video
, "ended");