summaryrefslogtreecommitdiffstats
path: root/dom/media/webvtt/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /dom/media/webvtt/test
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--dom/media/webvtt/test/crashtests/1304948.html33
-rw-r--r--dom/media/webvtt/test/crashtests/1319486.html27
-rw-r--r--dom/media/webvtt/test/crashtests/1533909.html17
-rw-r--r--dom/media/webvtt/test/crashtests/882549.html13
-rw-r--r--dom/media/webvtt/test/crashtests/894104.html20
-rw-r--r--dom/media/webvtt/test/crashtests/crashtests.list5
-rw-r--r--dom/media/webvtt/test/mochitest/bad-signature.vtt1
-rw-r--r--dom/media/webvtt/test/mochitest/basic.vtt29
-rw-r--r--dom/media/webvtt/test/mochitest/bug883173.vtt16
-rw-r--r--dom/media/webvtt/test/mochitest/long.vtt8001
-rw-r--r--dom/media/webvtt/test/mochitest/manifest.js27
-rw-r--r--dom/media/webvtt/test/mochitest/mochitest.ini50
-rw-r--r--dom/media/webvtt/test/mochitest/parser.vtt6
-rw-r--r--dom/media/webvtt/test/mochitest/region.vtt6
-rw-r--r--dom/media/webvtt/test/mochitest/sequential.vtt10
-rw-r--r--dom/media/webvtt/test/mochitest/test_bug1018933.html50
-rw-r--r--dom/media/webvtt/test/mochitest/test_bug1242594.html46
-rw-r--r--dom/media/webvtt/test/mochitest/test_bug883173.html39
-rw-r--r--dom/media/webvtt/test/mochitest/test_bug895091.html60
-rw-r--r--dom/media/webvtt/test/mochitest/test_bug957847.html30
-rw-r--r--dom/media/webvtt/test/mochitest/test_testtrack_cors_no_response.html41
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrack.html158
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrack_cors_preload_none.html40
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrack_mode_change_during_loading.html75
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrack_moz.html60
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrackcue.html298
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrackcue_moz.html34
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrackevents_video.html91
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttracklist.html51
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttracklist_moz.html34
-rw-r--r--dom/media/webvtt/test/mochitest/test_texttrackregion.html57
-rw-r--r--dom/media/webvtt/test/mochitest/test_trackelementevent.html77
-rw-r--r--dom/media/webvtt/test/mochitest/test_trackelementsrc.html53
-rw-r--r--dom/media/webvtt/test/mochitest/test_trackevent.html69
-rw-r--r--dom/media/webvtt/test/mochitest/test_vttparser.html44
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_empty_displaystate.html98
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_event_same_time.html63
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_infinite_processing_loop.html49
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_overlapping_time.html100
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_positionalign.html113
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_seeking.html110
-rw-r--r--dom/media/webvtt/test/mochitest/test_webvtt_update_display_after_adding_or_removing_cue.html93
-rw-r--r--dom/media/webvtt/test/mochitest/vttPositionAlign.vtt86
-rw-r--r--dom/media/webvtt/test/reftest/black.mp4bin0 -> 15036 bytes
-rw-r--r--dom/media/webvtt/test/reftest/cues_time_overlapping.webvtt7
-rw-r--r--dom/media/webvtt/test/reftest/reftest.list3
-rw-r--r--dom/media/webvtt/test/reftest/vtt_overlapping_time-ref.html29
-rw-r--r--dom/media/webvtt/test/reftest/vtt_overlapping_time.html30
-rw-r--r--dom/media/webvtt/test/reftest/vtt_reflow_display-ref.html28
-rw-r--r--dom/media/webvtt/test/reftest/vtt_reflow_display.css33
-rw-r--r--dom/media/webvtt/test/reftest/vtt_reflow_display.html37
-rw-r--r--dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue.html36
-rw-r--r--dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue_ref.html6
-rw-r--r--dom/media/webvtt/test/reftest/white.webmbin0 -> 10880 bytes
-rw-r--r--dom/media/webvtt/test/xpcshell/test_parser.js158
-rw-r--r--dom/media/webvtt/test/xpcshell/xpcshell.ini3
56 files changed, 10750 insertions, 0 deletions
diff --git a/dom/media/webvtt/test/crashtests/1304948.html b/dom/media/webvtt/test/crashtests/1304948.html
new file mode 100644
index 0000000000..667a13d06a
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/1304948.html
@@ -0,0 +1,33 @@
+<html class="reftest-wait">
+<head>
+ <title> Bug 1304948 : Crash if a texttrack remove a cue not belongs to it. </title>
+</head>
+<meta charset="utf-8">
+<script type="text/javascript">
+
+window.onload = function() {
+ var a = document.createElementNS('http://www.w3.org/1999/xhtml', 'video');
+ a.src = "";
+ document.body.appendChild(a);
+ var b = a.addTextTrack('chapters', "AAAAAAAAAAAAAAAA", "de");
+ var c = new VTTCue(0.6, 0.3, "AA");
+ b.addCue(c);
+ var d = document.createElementNS('http://www.w3.org/1999/xhtml', 'video');
+ var e = d.addTextTrack('chapters', "AAAA", "en-US");
+ a.currentTime = 2;
+ a.play();
+ try {
+ // This will queue a TimeMarchesOn task on mainthread, so use
+ // timer to wait the TimeMarchesOn crash.
+ e.removeCue(c);
+ } catch (e) {
+ if (e.name == "NotFoundError") {
+ setTimeout(function() {
+ document.documentElement.removeAttribute("class");}, 0);
+ }
+ }
+};
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/crashtests/1319486.html b/dom/media/webvtt/test/crashtests/1319486.html
new file mode 100644
index 0000000000..74bdb2147c
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/1319486.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title> Bug 1319486 : Crash if a texttrackcue added to different texttracks. </title>
+</head>
+<body>
+<video id=v1></video>
+<video id=v2></video>
+</body>
+<meta charset="utf-8">
+<script type="text/javascript">
+
+addEventListener('DOMContentLoaded', function(){
+ let cue,tt1,tt2;
+ v1.play();
+ tt1 = v1.addTextTrack('metadata', "", "");
+ v1.play();
+ v1.currentTime = 8;
+ cue = new VTTCue(0, 0.5, "");
+ tt1.addCue(cue);
+ tt2 = v2.addTextTrack('captions', "", "");
+ tt2.addCue(cue);
+ tt2.removeCue(cue);
+ tt1.addCue(new VTTCue(0.7, 2, ""));
+});
+</script>
+</html>
diff --git a/dom/media/webvtt/test/crashtests/1533909.html b/dom/media/webvtt/test/crashtests/1533909.html
new file mode 100644
index 0000000000..ee73ecb7b8
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/1533909.html
@@ -0,0 +1,17 @@
+<script>
+function eh1() {
+ d.track.addCue(new VTTCue(0.01, 0.69, "Y"))
+}
+function eh2() {
+ a.currentTime = 0.43
+ c.addEventListener("DOMNodeRemoved", eh1)
+ a.append(b)
+ a.appendChild(c)
+}
+</script>
+<canvas id="c">
+<q id="b">
+</canvas>
+<audio id="a" src="data:audio/mpeg;base64,/+M4wAAAAAAAAAAAAEluZm8AAAAPAAAAAwAAAbAAqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV////////////////////////////////////////////AAAAAExhdmM1Ny4zOAAAAAAAAAAAAAAAACQAAAAAAAAAAAGwU/hwzwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/+MYxAAMkI7huAhMDGQAndv+H5jfIAPmPzGBGeTAZNN7yjsnqd6Fny79M+o4UifnMu/TlDiIP5Q5l9Z/Kdv6VY0gE3JIAAwE/+MYxAgMYJr6WBhGIivjMy/CEK+zM39VVXjMArKgq6DQdrBV0THlqBp0ShrBp8qGsTPw7lXZFVZZY6GytZZYGChgYIGZaiJI/+MYxBEMUJnAABmMYUigMQLIE1yVpphA1UQMRVVVV000iVu000VVVX///6aaVUxBTUUzLjk5LjVVVVVVVVVVVVVVVVVVVVVV">
+<track id="d"></track>
+<iframe onload="eh2()">
diff --git a/dom/media/webvtt/test/crashtests/882549.html b/dom/media/webvtt/test/crashtests/882549.html
new file mode 100644
index 0000000000..8a720c3e11
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/882549.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
+ var o0 = new VTTCue(0.000, 1.000, 'Bug882549');
+ var o1 = o0.getCueAsHTML();
+ </script>
+ </head>
+ <body>
+ </body>
+</html>
+<script>
+</script>
diff --git a/dom/media/webvtt/test/crashtests/894104.html b/dom/media/webvtt/test/crashtests/894104.html
new file mode 100644
index 0000000000..d021994e74
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/894104.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+
+function boom()
+{
+ var frame = document.getElementById("f");
+ var frameWin = frame.contentWindow;
+ frameWin.VTTCue;
+ document.body.removeChild(frame);
+ new frameWin.VTTCue(0, 1, "Bug 894104").getCueAsHTML();
+}
+
+</script>
+</head>
+
+<body onload="boom();"><iframe id="f" src="data:text/html,1"></iframe></body>
+</html>
diff --git a/dom/media/webvtt/test/crashtests/crashtests.list b/dom/media/webvtt/test/crashtests/crashtests.list
new file mode 100644
index 0000000000..c9776984bc
--- /dev/null
+++ b/dom/media/webvtt/test/crashtests/crashtests.list
@@ -0,0 +1,5 @@
+load 1304948.html
+load 1319486.html
+load 1533909.html
+load 882549.html
+load 894104.html
diff --git a/dom/media/webvtt/test/mochitest/bad-signature.vtt b/dom/media/webvtt/test/mochitest/bad-signature.vtt
new file mode 100644
index 0000000000..c9a59b35e9
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/bad-signature.vtt
@@ -0,0 +1 @@
+WEB
diff --git a/dom/media/webvtt/test/mochitest/basic.vtt b/dom/media/webvtt/test/mochitest/basic.vtt
new file mode 100644
index 0000000000..45646ab868
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/basic.vtt
@@ -0,0 +1,29 @@
+WEBVTT
+REGION
+id:testOne lines:2 width:30%
+REGION
+id:testTwo lines:4 width:20%
+
+1
+00:00.500 --> 00:00.700 region:testOne
+This
+
+2
+00:01.200 --> 00:02.400 region:testTwo
+Is
+
+2.5
+00:02.000 --> 00:03.500 region:testOne
+(Over here?!)
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+5
+00:03.217 --> 00:03.989
+And more!
diff --git a/dom/media/webvtt/test/mochitest/bug883173.vtt b/dom/media/webvtt/test/mochitest/bug883173.vtt
new file mode 100644
index 0000000000..61f086bcce
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/bug883173.vtt
@@ -0,0 +1,16 @@
+WEBVTT
+
+00:03.000 --> 00:04.000
+Should display fifth.
+
+00:01.000 --> 00:02.000
+Should display first.
+
+00:01.000 --> 00:03.000
+Should display second.
+
+00:02.000 --> 00:04.000
+Should display forth.
+
+00:02.000 --> 00:03.000
+Should display third.
diff --git a/dom/media/webvtt/test/mochitest/long.vtt b/dom/media/webvtt/test/mochitest/long.vtt
new file mode 100644
index 0000000000..23984b0c8d
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/long.vtt
@@ -0,0 +1,8001 @@
+WEBVTT
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
+
+1
+00:00.500 --> 00:00.700
+This
+
+2
+00:01.200 --> 00:02.400
+Is
+
+3
+00:02.710 --> 00:02.910
+A
+
+4
+00:03.217 --> 00:03.989
+Test
diff --git a/dom/media/webvtt/test/mochitest/manifest.js b/dom/media/webvtt/test/mochitest/manifest.js
new file mode 100644
index 0000000000..91c481feb9
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/manifest.js
@@ -0,0 +1,27 @@
+// Force releasing decoder to avoid timeout in waiting for decoding resource.
+function removeNodeAndSource(n) {
+ n.remove();
+ // reset |srcObject| first since it takes precedence over |src|.
+ n.srcObject = null;
+ n.removeAttribute("src");
+ n.load();
+ while (n.firstChild) {
+ n.firstChild.remove();
+ }
+}
+
+function once(target, name, cb) {
+ var p = new Promise(function (resolve, reject) {
+ target.addEventListener(
+ name,
+ function () {
+ resolve();
+ },
+ { once: true }
+ );
+ });
+ if (cb) {
+ p.then(cb);
+ }
+ return p;
+}
diff --git a/dom/media/webvtt/test/mochitest/mochitest.ini b/dom/media/webvtt/test/mochitest/mochitest.ini
new file mode 100644
index 0000000000..ee905144b8
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/mochitest.ini
@@ -0,0 +1,50 @@
+[DEFAULT]
+subsuite = media
+tags = webvtt
+skip-if = (os == "win" && processor == "aarch64") # aarch64 due to 1536604
+support-files =
+ ../../../test/gizmo.mp4
+ ../../../test/seek.webm
+ ../../../test/vp9cake.webm
+ bad-signature.vtt
+ basic.vtt
+ bug883173.vtt
+ long.vtt
+ manifest.js
+ parser.vtt
+ region.vtt
+ sequential.vtt
+ vttPositionAlign.vtt
+
+[test_bug1018933.html]
+[test_bug1242594.html]
+[test_bug883173.html]
+skip-if = (android_version == '25' && debug) # android(bug 1232305)
+[test_bug895091.html]
+skip-if = (android_version == '25' && debug) # android(bug 1232305)
+[test_bug957847.html]
+skip-if = (android_version == '25' && debug) # android(bug 1232305)
+[test_trackelementevent.html]
+[test_trackelementsrc.html]
+[test_texttrack.html]
+[test_texttrackcue.html]
+[test_texttrackcue_moz.html]
+[test_trackevent.html]
+[test_texttrackevents_video.html]
+[test_texttracklist.html]
+[test_texttracklist_moz.html]
+[test_texttrackregion.html]
+[test_testtrack_cors_no_response.html]
+[test_texttrack_cors_preload_none.html]
+[test_texttrack_mode_change_during_loading.html]
+skip-if = true
+ toolkit == 'android' # Bug 1636572, android(bug 1562021)
+[test_texttrack_moz.html]
+[test_vttparser.html]
+[test_webvtt_empty_displaystate.html]
+[test_webvtt_event_same_time.html]
+[test_webvtt_infinite_processing_loop.html]
+[test_webvtt_overlapping_time.html]
+[test_webvtt_positionalign.html]
+[test_webvtt_seeking.html]
+[test_webvtt_update_display_after_adding_or_removing_cue.html]
diff --git a/dom/media/webvtt/test/mochitest/parser.vtt b/dom/media/webvtt/test/mochitest/parser.vtt
new file mode 100644
index 0000000000..2a56c65f80
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/parser.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+
+00:00.500 --> 00:00.700
+Test
+00:00.500 --> 00:00.700
+Stuff
diff --git a/dom/media/webvtt/test/mochitest/region.vtt b/dom/media/webvtt/test/mochitest/region.vtt
new file mode 100644
index 0000000000..1e351dbcfb
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/region.vtt
@@ -0,0 +1,6 @@
+WEBVTT
+REGION
+id:fred width:62% lines:5 regionanchor:4%,78% viewportanchor:10%,90% scroll:up
+
+00:01.000 --> 00:02.000 region:fred
+Test here.
diff --git a/dom/media/webvtt/test/mochitest/sequential.vtt b/dom/media/webvtt/test/mochitest/sequential.vtt
new file mode 100644
index 0000000000..94e92e38ae
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/sequential.vtt
@@ -0,0 +1,10 @@
+WEBVTT
+
+00:01.000 --> 00:02.000
+This
+
+00:03.000 --> 00:04.000
+Is
+
+00:05.000 --> 00:06.000
+A Test
diff --git a/dom/media/webvtt/test/mochitest/test_bug1018933.html b/dom/media/webvtt/test/mochitest/test_bug1018933.html
new file mode 100644
index 0000000000..bff1db6021
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_bug1018933.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1018933
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Regression test for bug 1018933 - HTMLTrackElement should create only one TextTrack</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+video.src = "seek.webm";
+video.preload = "auto";
+
+var trackElement = document.createElement("track");
+trackElement.src = "basic.vtt";
+trackElement.kind = "subtitles";
+
+document.getElementById("content").appendChild(video);
+video.appendChild(trackElement);
+
+// Accessing the track now would have caused the bug as the track element
+// shouldn't have had time to bind to the tree yet.
+trackElement.track.mode = 'showing';
+
+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(video.textTracks.length, 1, "Video should have one TextTrack.");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_bug1242594.html b/dom/media/webvtt/test/mochitest/test_bug1242594.html
new file mode 100644
index 0000000000..25c47948bb
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_bug1242594.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1242594
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Bug 1242594 - Unbind a video element with HTMLTrackElement
+ should not remove the TextTrack</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+video.src = "seek.webm";
+video.preload = "auto";
+
+var trackElement = document.createElement("track");
+trackElement.src = "basic.vtt";
+trackElement.kind = "subtitles";
+
+document.getElementById("content").appendChild(video);
+video.appendChild(trackElement);
+
+// Bug 1242599, access video.textTracks.length immediately after
+// the track element binds into the media element.
+is(video.textTracks.length, 1, "Video should have one TextTrack.");
+var parent = video.parentNode;
+parent.removeChild(video);
+is(video.textTracks.length, 1, "After unbind the video element, should have one TextTrack.");
+parent.appendChild(video);
+is(video.textTracks.length, 1, "After bind the video element, should have one TextTrack.");
+SimpleTest.finish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_bug883173.html b/dom/media/webvtt/test/mochitest/test_bug883173.html
new file mode 100644
index 0000000000..6e95f4e3ca
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_bug883173.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 883173 - TextTrackCue(List) Sorting</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<video id="v" src="seek.webm" preload="metadata">
+ <track src="bug883173.vtt" kind="subtitles" id="default" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to ensure that the cues in the cue list should be sorted by
+ * cues' start time and end time, not the present order in the file.
+ */
+function runTest() {
+ let trackElement = document.getElementById("default");
+ is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
+
+ let expected = [[1, 3], [1, 2], [2, 4], [2, 3], [3, 4]];
+ let cueList = trackElement.track.cues;
+ is(cueList.length, expected.length, "Cue list length should be 5.");
+
+ for (let 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>
diff --git a/dom/media/webvtt/test/mochitest/test_bug895091.html b/dom/media/webvtt/test/mochitest/test_bug895091.html
new file mode 100644
index 0000000000..6fa2629283
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_bug895091.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<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>
+<video id="v" src="seek.webm" preload="metadata">
+ <track src="long.vtt" kind="subtitles" id="track1">
+ <track src="long.vtt" kind="subtitles" id="track2">
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to ensure that we can load two track elements with large
+ * amount of cues at same time. In this test, both tracks are disable by default,
+ * we have to enable them in order to start loading.
+ */
+var trackElement = document.getElementById("track1");
+var trackElementTwo = document.getElementById("track2");
+
+async function runTest() {
+ enableBothTracks();
+ await waitUntilBothTracksLoaded();
+ checkTrackReadyStateShouldBeLoaded();
+ checkCuesAmount();
+ 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")]);
+}
+
+function checkTrackReadyStateShouldBeLoaded() {
+ is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
+ is(trackElementTwo.readyState, 2, "Track::ReadyState should be set to LOADED.");
+}
+
+function checkCuesAmount() {
+ is(trackElement.track.cues.length, 2000, "Cue list length should be 2000.");
+ is(trackElementTwo.track.cues.length, 2000, "Cue list length should be 2000.");
+}
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_bug957847.html b/dom/media/webvtt/test/mochitest/test_bug957847.html
new file mode 100644
index 0000000000..8bbea81bf9
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_bug957847.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=957847
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Regression test for bug 957847 - Crash on TextTrack::AddCue </title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var trackElement = document.createElement('track');
+trackElement.track.addCue(new VTTCue(0, 1, "A"));
+
+// We need to assert something for Mochitest to be happy.
+ok(true);
+SimpleTest.finish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_testtrack_cors_no_response.html b/dom/media/webvtt/test/mochitest/test_testtrack_cors_no_response.html
new file mode 100644
index 0000000000..e047f74eb3
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_testtrack_cors_no_response.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Should not load CORS vtt file when server doesn't respond with correct CORS header</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 preload="none" crossorigin="anonymous">
+ <track src="http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/media/webvtt/test/mochitest/basic.vtt&type=text/vtt" kind="subtitles" id="default" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to ensure that we shouldn't load CORS resource if server
+ * doesn't respond with correct CORS header. In this situation, loading should
+ * be expected to fail.
+ */
+async function runTest() {
+ await waitUntiTrackLoadError();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+runTest();
+
+/**
+ * The following are test helper functions.
+ */
+async function waitUntiTrackLoadError() {
+ const trackElement = document.getElementById("default");
+ if (trackElement.readyState != 3) {
+ info(`wait until receiving error event`);
+ await once(trackElement, "error");
+ }
+ is(trackElement.readyState, 3, "Track::ReadyState should be set to ERROR.");
+ is(trackElement.track.cues.length, 0, "Cue list length should be 0.");
+}
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrack.html b/dom/media/webvtt/test/mochitest/test_texttrack.html
new file mode 100644
index 0000000000..69c4f24bec
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrack.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+<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">
+/**
+ * This test is used to check different things.
+ * (1) the default value of track element's attributes
+ * (2) readonly attributes can't be modifted
+ * (3) the order of tracks in the media element's track list
+ */
+var enabledTrackElement = null;
+
+async function runTest() {
+ addFourTextTrackElementsToVideo();
+ startLoadingVideo();
+ await waitUntilEnableTrackLoaded();
+ checkTracksStatus();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = runTest;
+
+/**
+ * The following are test helper functions.
+ */
+function addFourTextTrackElementsToVideo() {
+ let video = document.getElementById("v");
+ isnot(video.textTracks, undefined,
+ "HTMLMediaElement::TextTrack() property should be available.")
+
+ let trackList = video.textTracks;
+ 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.");
+
+ let textTrack = video.textTracks[0];
+ checkAttributesDefaultValue(textTrack);
+ checkTextTrackMode(textTrack);
+ checkReadOnlyAttributes(textTrack);
+
+ info(`- Add a track element with label 'first' -`);
+ let trackOne = document.createElement("track");
+ video.appendChild(trackOne);
+ 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;
+
+ info(`- Add a track element with label 'fourth' -`);
+ video.addTextTrack("subtitles", "fourth", "en-CA");
+
+ info(`- Add a track element with label 'second' -`);
+ let trackTwo = document.createElement("track");
+ video.appendChild(trackTwo);
+ 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;
+}
+
+function checkAttributesDefaultValue(track) {
+ is(track.label, "third", "Label should be set to third.");
+ is(track.language, "en-CA", "Language should be en-CA.");
+ is(track.kind, "subtitles", "Default kind should be subtitles.");
+ is(track.mode, "hidden", "Default mode should be hidden.");
+}
+
+function checkTextTrackMode(track) {
+ // Mode should not allow a bogus value.
+ track.mode = 'bogus';
+ is(track.mode, 'hidden', "Mode should be not allow a bogus value.");
+
+ // Should allow all these values for mode.
+ changeTextTrackMode("showing");
+ changeTextTrackMode("disabled");
+ changeTextTrackMode("hidden");
+
+ function changeTextTrackMode(mode) {
+ track.mode = mode;
+ is(track.mode, mode, `Mode should allow \"${mode}\"`);
+ }
+}
+
+function checkReadOnlyAttributes(track) {
+ // All below are read-only properties and so should not allow setting.
+ track.label = "French subtitles";
+ is(track.label, "third", "Label is read-only so should still be \"label\".");
+ track.language = "en";
+ is(track.language, "en-CA", "Language is read-only so should still be \"en-CA\".");
+ track.kind = "captions";
+ is(track.kind, "subtitles", "Kind is read-only so should still be \"subtitles\"");
+}
+
+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>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrack_cors_preload_none.html b/dom/media/webvtt/test/mochitest/test_texttrack_cors_preload_none.html
new file mode 100644
index 0000000000..6743e8c4cd
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrack_cors_preload_none.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>load CORS Text track correctly when its parent media element's preload is none</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 preload="none" crossorigin="anonymous">
+ <track src="http://example.com/tests/dom/canvas/test/crossorigin/video.sjs?name=tests/dom/media/webvtt/test/mochitest/basic.vtt&type=text/vtt&cors=anonymous" kind="subtitles" id="default" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to test the text track element with CORS resource can starts
+ * loaded correctly when its parent media element's preload attribute is none.
+ */
+async function runTest() {
+ await waitUntiTrackLoaded();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+runTest();
+
+/**
+ * The following are test helper functions.
+ */
+async function waitUntiTrackLoaded() {
+ let trackElement = document.getElementById("default");
+ if (trackElement.readyState != 2) {
+ 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>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrack_mode_change_during_loading.html b/dom/media/webvtt/test/mochitest/test_texttrack_mode_change_during_loading.html
new file mode 100644
index 0000000000..974f452092
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrack_mode_change_during_loading.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebVTT : changing track's mode during loading</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="manifest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+/**
+ * This test is to ensure that we won't get `error` event when we change track's
+ * mode during loading. In this test, track element starts loading after setting
+ * the src and we would start another load later just after the channel which is
+ * used to fetch data starts. The second load is triggered by mode changes, and
+ * it should stop the prevous load and won't generate any error.
+ */
+async function startTest() {
+ const video = createVideo();
+ const trackElement = createAndAppendtrackElemententToVideo(video);
+
+ await changeTrackModeDuringLoading(trackElement);
+ await waitUntilTrackLoaded(trackElement);
+
+ removeNodeAndSource(video);
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.testing.events", true]]},
+ startTest);
+
+/**
+ * The following are test helper functions.
+ */
+function createVideo() {
+ info(`create video`);
+ let video = document.createElement("video");
+ video.src = "gizmo.mp4";
+ document.body.appendChild(video);
+ return video;
+}
+
+function createAndAppendtrackElemententToVideo(video) {
+ let trackElement = document.createElement("track");
+ trackElement.default = true;
+ video.append(trackElement);
+ return trackElement;
+}
+
+async function changeTrackModeDuringLoading(trackElement) {
+ info(`set src to start loading`);
+ trackElement.src = "basic.vtt";
+
+ info(`wait until starting loading resource.`);
+ await once(trackElement, "mozStartedLoadingTextTrack");
+
+ info(`changeing track's mode during loading should not cause loading failed.`);
+ trackElement.onerror = () => {
+ ok(false, `Should not get error event!`);
+ }
+ trackElement.track.mode = "hidden";
+}
+
+async function waitUntilTrackLoaded(trackElement) {
+ if (trackElement.readyState != 2) {
+ 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>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrack_moz.html b/dom/media/webvtt/test/mochitest/test_texttrack_moz.html
new file mode 100644
index 0000000000..b39562b3a4
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrack_moz.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 881976 - 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" src="seek.webm" preload="metadata">
+<script type="text/javascript">
+/**
+ * This test is used to ensure the text track list we got from video is as same
+ * as the one in the text track.
+ */
+var video = document.getElementById("v");
+
+async function runTest() {
+ addTrackViaAddTrackAPI();
+ await addTrackViaTrackElement();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = runTest;
+
+/**
+ * The following are test helper functions.
+ */
+function addTrackViaAddTrackAPI() {
+ // Check if adding a text track manually sets the TextTrackList correctly.
+ video.addTextTrack("subtitles", "", "");
+ // TextTrack.textTrackList is an extension available only to privileged code,
+ // so we need to access it through the SpecialPowers object.
+ is(SpecialPowers.unwrap(SpecialPowers.wrap(video.textTracks[0]).textTrackList),
+ video.textTracks,
+ "The Track's TextTrackList should be the Video's TextTrackList.");
+}
+
+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>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrackcue.html b/dom/media/webvtt/test/mochitest/test_texttrackcue.html
new file mode 100644
index 0000000000..3d9783c07d
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrackcue.html
@@ -0,0 +1,298 @@
+<!DOCTYPE HTML>
+<html>
+<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>
+<video id="v" src="seek.webm" preload="metadata">
+ <track src="basic.vtt" kind="subtitles" id="default" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to test the VTTCue's different behaviors and check whether
+ * cues would be activatived correctly during video playback.
+ */
+var video = document.getElementById("v");
+var trackElement = document.getElementById("default");
+
+async function runTest() {
+ await waitUntiTrackLoaded();
+ checkCueDefinition();
+ checkFirstCueParsedContent();
+ checkCueStartTimeAndEndtime();
+ checkCueSizeAndPosition();
+ checkCueSnapToLines();
+ checkCueAlignmentAndWritingDirection();
+ checkCueLine();
+ checkCreatingNewCue();
+ checkRemoveNonExistCue();
+ checkActiveCues();
+ checkCueRegion();
+ await checkCActiveCuesDuringVideoPlaying();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
+ runTest);
+/**
+ * The following are test helper functions.
+ */
+async function waitUntiTrackLoaded() {
+ if (trackElement.readyState != 2) {
+ 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.");
+}
+
+function checkCueDefinition() {
+ // 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.");
+}
+
+function checkFirstCueParsedContent() {
+ // Check if first cue was parsed correctly.
+ const cue = trackElement.track.cues[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.");
+}
+
+function checkCueStartTimeAndEndtime() {
+ const cueList = trackElement.track.cues;
+ // 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.
+ const cue = trackElement.track.cues[0];
+ 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});
+}
+
+function checkCueSizeAndPosition() {
+ 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) {
+ let exceptionHappened = false;
+ try {
+ cue[prop] = val;
+ } catch(e) {
+ exceptionHappened = true;
+ is(e.name, "IndexSizeError", "Should have thrown IndexSizeError.");
+ }
+ ok(exceptionHappened, "Exception should have happened.");
+ });
+ }
+
+ const cue = trackElement.track.cues[0];
+ 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.");
+}
+
+function checkCueSnapToLines() {
+ const cue = trackElement.track.cues[0];
+ 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 checkCueAlignmentAndWritingDirection() {
+ 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}`);
+ }
+ });
+ }
+
+ const cue = trackElement.track.cues[0];
+ 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.");
+}
+
+function checkCueLine() {
+ const cue = trackElement.track.cues[0];
+ // 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.");
+}
+
+function checkCreatingNewCue() {
+ const cueList = trackElement.track.cues;
+
+ // Check that we can create and add new VTTCues
+ let vttCue = new VTTCue(3.999, 4, "foo");
+ is(vttCue.track, null, "Cue's track should be null.");
+ trackElement.track.addCue(vttCue);
+ is(vttCue.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
+ let 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.");
+}
+
+function checkRemoveNonExistCue() {
+ is(trackElement.track.cues.length, 6, "Cue list length should be 6.");
+ let exceptionHappened = false;
+ try {
+ // We should not be able to remove a cue that is not in the list.
+ trackElement.track.removeCue(new VTTCue(1, 2, "foo"));
+ } 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(trackElement.track.cues.length, 6, "Cue list length should still be 6.");
+}
+
+function checkActiveCues() {
+ video.currentTime = 2;
+ isnot(trackElement.track.activeCues, null);
+
+ trackElement.track.mode = "disabled";
+ is(trackElement.track.activeCues, null, "No active cue when track is disabled.");
+ trackElement.track.mode = "showing";
+}
+
+function checkCueRegion() {
+ let regionInfo = [
+ { lines: 2, width: 30 },
+ { lines: 4, width: 20 },
+ { lines: 2, width: 30 }
+ ];
+
+ for (let i = 0; i < regionInfo.length; i++) {
+ let cue = trackElement.track.cues[i];
+ isnot(cue.region, null, `Cue at ${i} should have a region.`);
+ for (let key in regionInfo[i]) {
+ is(cue.region[key], regionInfo[i][key],
+ `Region should have a ${key} property with a value of ${regionInfo[i][key]}`);
+ }
+ }
+}
+
+async function checkCActiveCuesDuringVideoPlaying() {
+ // Test TextTrack::ActiveCues.
+ let 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() {
+ let activeCues = trackElement.track.activeCues,
+ playbackTime = video.currentTime;
+
+ for (let i = 0; i < cueInfo.length; i++) {
+ let 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 (let 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;
+ }
+ }
+ });
+
+ info(`start video from 0s.`);
+ video.currentTime = 0;
+ video.play();
+ await once(video, "playing");
+ info(`video starts playing.`);
+ await once(video, "ended");
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrackcue_moz.html b/dom/media/webvtt/test/mochitest/test_texttrackcue_moz.html
new file mode 100644
index 0000000000..29f6661f85
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrackcue_moz.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=967157
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Test for Bug 967157 - Setting TextTrackCue::DisplayState should set TextTrackCue::HasBeenReset to false</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ var cue = SpecialPowers.wrap(new VTTCue(0, 1, "Some text."));
+ is(cue.hasBeenReset, false, "Cue's hasBeenReset flag should be false.");
+ is(cue.displayState, null, "Cue's displayState should be null.");
+
+ cue.startTime = 0.5;
+ is(cue.hasBeenReset, true, "Cue's hasBeenReset flag should now be true.");
+
+ cue.displayState = document.createElement("div");
+ is(cue.hasBeenReset, false, "Cue's hasBeenReset flag should now be false.");
+
+ SimpleTest.finish();
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrackevents_video.html b/dom/media/webvtt/test/mochitest/test_texttrackevents_video.html
new file mode 100644
index 0000000000..83104633a4
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrackevents_video.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for TextTrack DOM Events</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+video.src = "vp9cake.webm";
+video.preload = "auto";
+video.controls = true;
+var trackElement = document.createElement("track");
+trackElement.src = "sequential.vtt";
+trackElement.kind = "subtitles";
+trackElement.default = true;
+document.getElementById("content").appendChild(video);
+video.appendChild(trackElement);
+
+var trackElementCueChangeCount = 0;
+var trackCueChangeCount = 0;
+var cueEnterCount = 0;
+var cueExitCount = 0;
+
+video.addEventListener("loadedmetadata", function run_tests() {
+ // 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.");
+ ok('oncuechange' in trackElement.track, "Track::OnCueChange should exist.");
+
+ var textTrack = trackElement.track;
+ is(textTrack.cues.length, 3, "textTrack.cues.length should 3.");
+ textTrack.cues[0].onenter = function() {
+ ++cueEnterCount;
+ };
+ textTrack.cues[0].onexit = function() {
+ ++cueExitCount;
+ };
+ textTrack.cues[1].onenter = function() {
+ ++cueEnterCount;
+ };
+ textTrack.cues[1].onexit = function() {
+ ++cueExitCount;
+ };
+ textTrack.cues[2].onenter = function() {
+ ++cueEnterCount;
+ };
+ textTrack.cues[2].onexit = function() {
+ ++cueExitCount;
+ };
+
+ trackElement.track.oncuechange = function() {
+ ++trackElementCueChangeCount;
+ };
+
+ trackElement.addEventListener("cuechange", function() {
+ ++trackCueChangeCount;
+ });
+
+ video.play();
+});
+
+video.addEventListener('ended', function() {
+ // Should be fired 1 to 6 times, as there are 3 cues,
+ // with a change event for when it is activated/deactivated
+ // (6 events at most).
+ isnot(trackElementCueChangeCount, 0, "TrackElement should fire cue change at least one time.");
+ ok(trackElementCueChangeCount <= 6, 'trackElementCueChangeCount should <= 6');
+ isnot(trackCueChangeCount, 0, "TrackElement.track should fire cue change at least one time.");
+ ok(trackCueChangeCount <= 6, 'trackCueChangeCount should <= 6');
+ is(cueEnterCount, 3, "cueEnterCount should fire three times.");
+ is(cueExitCount, 3, "cueExitCount should fire three times.");
+ SimpleTest.finish()
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttracklist.html b/dom/media/webvtt/test/mochitest/test_texttracklist.html
new file mode 100644
index 0000000000..c1d2296289
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttracklist.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=882703
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Media test: TextTrackList change event</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+let video = document.createElement("video");
+
+isnot(video.textTracks, null, "Video should have a list of TextTracks.");
+
+video.addTextTrack("subtitles", "", "");
+
+let track = video.textTracks[0];
+video.textTracks.addEventListener("change", changed);
+
+is(track.mode, "hidden", "New TextTrack's mode should be hidden.");
+track.mode = "showing";
+// Bug882674: change the mode again to see if we receive only one
+// change event.
+track.mode = "hidden";
+
+var eventCount = 0;
+function changed(event) {
+ eventCount++;
+ is(eventCount, 1, "change event dispatched multiple times.");
+ is(event.target, video.textTracks, "change event's target should be video.textTracks.");
+ ok(event instanceof window.Event, "change event should be a simple event.");
+ ok(!event.bubbles, "change event should not bubble.");
+ ok(event.isTrusted, "change event should be trusted.");
+ ok(!event.cancelable, "change event should not be cancelable.");
+
+ // Delay the finish function call for testing the change event count.
+ setTimeout(SimpleTest.finish, 0);
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttracklist_moz.html b/dom/media/webvtt/test/mochitest/test_texttracklist_moz.html
new file mode 100644
index 0000000000..6cae8323fd
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttracklist_moz.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=881976
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Test for Bug 881976 - TextTrackCue Computed Position</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+var trackList = video.textTracks;
+ok(trackList instanceof TextTrackList,
+ "Video's textTracks should be a TextTrackList");
+var trackParent = SpecialPowers.unwrap(
+ SpecialPowers.wrap(trackList).mediaElement
+);
+is(trackParent, video,
+ "Video's TextTrackList's MediaElement reference should be set to the video.");
+SimpleTest.finish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_texttrackregion.html b/dom/media/webvtt/test/mochitest/test_texttrackregion.html
new file mode 100644
index 0000000000..f41c404445
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_texttrackregion.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<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>
+<video id="v" src="seek.webm" preload="auto">
+ <track src="region.vtt" kind="subtitles" id="default" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is used to ensure that we can parse VTT region attributes correctly
+ * from vtt file.
+ */
+var trackElement = document.getElementById("default");
+
+async function runTest() {
+ await waitUntiTrackLoaded();
+ checkRegionAttributes();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
+ runTest);
+/**
+ * The following are test helper functions.
+ */
+async function waitUntiTrackLoaded() {
+ if (trackElement.readyState != 2) {
+ info(`wait until the track finishes loading`);
+ await once(trackElement, "load");
+ }
+ is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
+}
+
+function checkRegionAttributes() {
+ let cues = trackElement.track.cues;
+ is(cues.length, 1, "Cue list length should be 1.");
+
+ let 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'");
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_trackelementevent.html b/dom/media/webvtt/test/mochitest/test_trackelementevent.html
new file mode 100644
index 0000000000..f78033a89d
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_trackelementevent.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 882677 - Implement the 'sourcing out of band text tracks' algorithm</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="auto">
+<script type="text/javascript">
+/**
+ * This test is used to ensure that we can load resource from vtt files correctly
+ * and will dispatch `error` event for invalid vtt files.
+ */
+var video = document.getElementById("v");
+
+async function runTest() {
+ let tracks = createTextTrackElements();
+ appendTracksToVideo(tracks);
+ await waitUntilsTrackLoadedOrGetError(tracks);
+ SimpleTest.finish()
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = runTest;
+
+/**
+ * The following are test helper functions.
+ */
+function createTextTrackElements() {
+ // Only first track has valid vtt resource, other tracks should get the error
+ // event because of invalid vtt resources.
+ let trackOne = document.createElement("track");
+ trackOne.src = "basic.vtt";
+ trackOne.kind = "subtitles";
+ trackOne.expectedLoaded = true;
+
+ let trackTwo = document.createElement("track");
+ trackTwo.src = "bad-signature.vtt";
+ trackTwo.kind = "captions";
+ trackTwo.expectedLoaded = false;
+
+ let trackThree = document.createElement("track");
+ trackThree.src = "bad.vtt";
+ trackThree.kind = "chapters";
+ trackThree.expectedLoaded = false;
+
+ return [trackOne, trackTwo, trackThree];
+}
+
+function appendTracksToVideo(tracks) {
+ for (let track of tracks) {
+ video.appendChild(track);
+ }
+}
+
+async function waitUntilsTrackLoadedOrGetError(tracks) {
+ let promises = [];
+ for (let track of tracks) {
+ // explictly enable those track in order to start loading.
+ track.track.mode = "hidden";
+ if (track.expectedLoaded) {
+ info(`adding 'load' event to wait list.`);
+ promises.push(once(track, "load"));
+ } else {
+ info(`adding 'error' event to wait list.`);
+ promises.push(once(track, "error"));
+ }
+ }
+ info(`wait until tracks finish loading or get error.`);
+ await Promise.all(promises);
+ ok(true, "all tracks finish loading or get error.");
+}
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_trackelementsrc.html b/dom/media/webvtt/test/mochitest/test_trackelementsrc.html
new file mode 100644
index 0000000000..f98e79c605
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_trackelementsrc.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1281418 - Change the src attribue for TrackElement.</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.regions.enabled", true]]},
+ function() {
+ var video = document.createElement("video");
+ video.src = "seek.webm";
+ video.preload = "metadata";
+ var trackElement = document.createElement("track");
+ trackElement.src = "basic.vtt";
+ trackElement.default = true;
+
+ document.getElementById("content").appendChild(video);
+ video.appendChild(trackElement);
+
+ video.addEventListener("loadedmetadata", function metadata() {
+ if (trackElement.readyState <= 1) {
+ setTimeout(metadata, 0);
+ return;
+ }
+ is(video.textTracks.length, 1, "Length should be 1.");
+ is(video.textTracks[0].cues.length, 6, "Cue length should be 6.");
+
+ trackElement.src = "sequential.vtt";
+ trackElement.track.mode = "showing";
+ video.play();
+ });
+
+ video.addEventListener("ended", function end() {
+ is(trackElement.readyState, 2, "readyState should be 2.")
+ is(video.textTracks.length, 1, "Length should be 1.");
+ is(video.textTracks[0].cues.length, 3, "Cue length should be 3.");
+ SimpleTest.finish();
+ });
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_trackevent.html b/dom/media/webvtt/test/mochitest/test_trackevent.html
new file mode 100644
index 0000000000..ffba7d33ec
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_trackevent.html
@@ -0,0 +1,69 @@
+
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 893309 - Implement TrackEvent</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+isnot(video.textTracks, undefined, "HTMLMediaElement::TextTrack() property should be available.")
+ok(typeof video.addTextTrack == "function", "HTMLMediaElement::AddTextTrack() function should be available.")
+
+var trackList = video.textTracks;
+is(trackList.length, 0, "Length should be 0.");
+
+var evtTextTrack, numOfCalls = 0, tt;
+trackList.onaddtrack = function(event) {
+ ok(event instanceof TrackEvent, "Fired event from onaddtrack should be a TrackEvent");
+ is(event.type, "addtrack", "Event type should be addtrack");
+ ok(event.isTrusted, "Event should be trusted!");
+ ok(!event.bubbles, "Event shouldn't bubble!");
+ ok(!event.cancelable, "Event shouldn't be cancelable!");
+
+ evtTextTrack = event.track;
+ tt = textTrack[numOfCalls].track || textTrack[numOfCalls];
+
+ ok(tt === evtTextTrack, "Text tracks should be the same");
+ is(evtTextTrack.label, label[numOfCalls], "Label should be set to "+ label[numOfCalls]);
+ is(evtTextTrack.language, language[numOfCalls], "Language should be " + language[numOfCalls]);
+ is(evtTextTrack.kind, kind[numOfCalls], "Kind should be " + kind[numOfCalls]);
+
+ if (++numOfCalls == 4) {
+ SimpleTest.finish();
+ }
+};
+
+var label = ["Oasis", "Coldplay", "t.A.T.u", ""];
+var language = ["en-CA", "en-GB", "ru", ""];
+var kind = ["subtitles", "captions", "chapters", "subtitles"];
+
+var textTrack = new Array(4);
+for (var i = 0; i < 3; ++i) {
+ textTrack[i] = video.addTextTrack(kind[i], label[i], language[i]);
+ is(trackList.length, i + 1, "Length should be " + (i+1));
+}
+
+video.src = "seek.webm";
+video.preload = "auto";
+var trackElement = document.createElement("track");
+trackElement.src = "basic.vtt";
+textTrack[3] = trackElement;
+
+document.getElementById("content").appendChild(video);
+video.appendChild(trackElement);
+
+//TODO: Tests for removetrack event to be added along with bug 882677
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_vttparser.html b/dom/media/webvtt/test/mochitest/test_vttparser.html
new file mode 100644
index 0000000000..419723a1d4
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_vttparser.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>WebVTT Parser Regression Tests</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+video.src = "seek.webm";
+video.preload = "auto";
+
+var trackElement = document.createElement("track");
+trackElement.src = "parser.vtt";
+trackElement.kind = "subtitles";
+trackElement.default = true;
+
+document.getElementById("content").appendChild(video);
+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 == 1) {
+ setTimeout(run_tests, 0);
+ return;
+ }
+
+ is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
+ is(trackElement.track.cues.length, 2, "Track should have two Cues.");
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_empty_displaystate.html b/dom/media/webvtt/test/mochitest/test_webvtt_empty_displaystate.html
new file mode 100644
index 0000000000..e1a8ddc555
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_empty_displaystate.html
@@ -0,0 +1,98 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>WebVTT : cue's displaystate should be empty when its active flag is unset</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="content">
+</div>
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var isReceivedOnEnterEvent = false;
+var isReceivedOnExitEvent = false;
+
+function checkCueEvents() {
+ ok(isReceivedOnEnterEvent, "Already received cue's onEnter event.");
+ ok(isReceivedOnExitEvent, "Already received cue's onExit event.");
+ SimpleTest.finish();
+}
+
+function checkCueDisplayState(cue, expectedState) {
+ var cueChrome = SpecialPowers.wrap(cue);
+ if (expectedState) {
+ ok(cueChrome.displayState, "Cue's displayState shouldn't be empty.");
+ } else {
+ ok(!cueChrome.displayState, "Cue's displayState should be empty.");
+ }
+}
+
+function runTest() {
+ info("--- create video ---");
+ var video = document.createElement("video");
+ video.src = "seek.webm";
+ video.autoplay = true;
+ document.getElementById("content").appendChild(video);
+
+ video.onended = function () {
+ video.onended = null;
+ checkCueEvents();
+ };
+
+ video.onpause = function () {
+ video.onpause = null;
+ checkCueEvents();
+ }
+
+ video.onloadedmetadata = function () {
+ ok(video.duration > 2, "video.duration should larger than 2");
+ }
+
+ info("--- create the type of track ---");
+ isnot(window.TextTrack, undefined, "TextTrack should be defined.");
+
+ var track = video.addTextTrack("subtitles", "A", "en");
+ track.mode = "showing";
+ ok(track instanceof TextTrack, "Track should be an instanceof TextTrack.");
+
+ info("--- check the type of cue ---");
+ isnot(window.TextTrackCue, undefined, "TextTrackCue should be defined.");
+ isnot(window.VTTCue, undefined, "VTTCue should be defined.");
+
+ var cue = new VTTCue(1, 2, "Test cue");
+ ok(cue instanceof TextTrackCue, "Cue should be an instanceof TextTrackCue.");
+ ok(cue instanceof VTTCue, "Cue should be an instanceof VTTCue.");
+
+ info("--- add cue ---");
+ track.addCue(cue);
+ video.ontimeupdate = function () {
+ info("--- video.currentTime is " + video.currentTime);
+ };
+ cue.onenter = function () {
+ cue.onenter = null;
+ isReceivedOnEnterEvent = true;
+ var cueChrome = SpecialPowers.wrap(cue);
+ info("cueChrome.getActive " + cueChrome.getActive);
+ if (cueChrome.getActive) {
+ checkCueDisplayState(cue, true /* has display-state */);
+ } else {
+ info("This is a missing cue, video.currentTime is "+ video.currentTime);
+ }
+
+ cue.onexit = function () {
+ cue.onexit = null;
+ isReceivedOnExitEvent = true;
+ checkCueDisplayState(cue, false /* no display-state */);
+ video.pause();
+ }
+ }
+}
+
+onload = runTest;
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_event_same_time.html b/dom/media/webvtt/test/mochitest/test_webvtt_event_same_time.html
new file mode 100644
index 0000000000..e70ff558e1
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_event_same_time.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>WebVTT : cue's onenter/onexit event order </title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="content">
+</div>
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var c1exit = false;
+var c3enter = false;
+
+function runTest() {
+ info("--- create video ---");
+ var video = document.createElement("video");
+ video.src = "seek.webm";
+ video.autoplay = true;
+ document.getElementById("content").appendChild(video);
+
+ var track = video.addTextTrack("subtitles", "A", "en");
+ track.mode = "showing";
+
+ var cue1 = new VTTCue(1, 2, "Test cue1");
+ var cue2 = new VTTCue(2, 3, "Test cue2");
+ track.addCue(cue1);
+ track.addCue(cue2);
+
+ cue1.onexit = function () {
+ cue1.onexit = null;
+ c1exit = true;
+ }
+ cue2.onenter = function () {
+ cue2.onenter = null;
+ ok(c1exit, "cue1 onexit event before than cue2 onenter");
+ video.pause();
+ SimpleTest.finish();
+ }
+
+ var cue3 = new VTTCue(1, 2, "Test cue3");
+ var cue4 = new VTTCue(1, 2, "Test cue4");
+ track.addCue(cue3);
+ track.addCue(cue4);
+
+ cue3.onenter = function () {
+ cue3.onenter = null;
+ c3enter = true;
+ }
+ cue4.onenter = function () {
+ cue4.onenter = null;
+ ok(c3enter, "cue3 onenter event before than cue4 onenter");
+ }
+}
+
+onload = runTest;
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_infinite_processing_loop.html b/dom/media/webvtt/test/mochitest/test_webvtt_infinite_processing_loop.html
new file mode 100644
index 0000000000..c8a9380ca2
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_infinite_processing_loop.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Bug 1580015 - video hangs infinitely during playing subtitle</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"/>
+ <style>
+ .container {
+ width: 500px;
+ height: 300px;
+ background: pink;
+ display: flex;
+ justify-content: center;
+ }
+
+ video {
+ min-width: 95%;
+ max-width: 95%;
+ max-height: 95%;
+ }
+ </style>
+</head>
+<body>
+<div class="container">
+<video id="v" src="gizmo.mp4" controls>
+ <track src="basic.vtt" kind="subtitles" default>
+</video>
+</div>
+<script type="text/javascript">
+/**
+ * This test is used to ensure that we don't go into an infinite processing loop
+ * during playing subtitle when setting those CSS properties on video.
+ */
+SimpleTest.waitForExplicitFinish();
+
+let video = document.getElementById("v");
+// We don't need to play whole video, in order to reduce test time, we can start
+// from the half, which can also reproduce the issue.
+video.currentTime = 3.0;
+video.play();
+video.onended = () => {
+ ok(true, "video ends without entering an infinite processing loop");
+ SimpleTest.finish();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_overlapping_time.html b/dom/media/webvtt/test/mochitest/test_webvtt_overlapping_time.html
new file mode 100644
index 0000000000..5ce08ae77a
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_overlapping_time.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebVTT : cues with overlapping time should be displayed correctly </title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="manifest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<video id ="v" src="gizmo.mp4" controls>
+<script class="testbody" type="text/javascript">
+/**
+ * This test is used to ensure that when cues with overlapping times, the one
+ * with earlier end timestamp should disappear when the media time reaches its
+ * end time. In this test, we have two cues with overlapping time, when the video
+ * starts, both cues should be displayed. When the time passes 1 seconds, the
+ * first cue should disappear and the second cues should be still displayed.
+ */
+var CUES_INFO = [
+ { id: 0, startTime: 0, endTime: 1, text: "This is cue 0."},
+ { id: 1, startTime: 0, endTime: 6, text: "This is cue 1."},
+];
+
+var video = document.getElementById("v");
+
+async function startTest() {
+ const cues = createCues();
+ await startVideo();
+
+ await waitUntilCueIsShowing(cues[0]);
+ await waitUntilCueIsShowing(cues[1]);
+
+ await waitUntilCueIsHiding(cues[0]);
+ await waitUntilCueIsShowing(cues[1]);
+ IsVideoStillPlaying();
+
+ endTestAndClearVideo();
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = startTest;
+
+/**
+ * The following are test helper functions.
+ */
+function createCues() {
+ let track = video.addTextTrack("subtitles");
+ track.mode = "showing";
+ let cue0 = new VTTCue(CUES_INFO[0].startTime, CUES_INFO[0].endTime,
+ CUES_INFO[0].text);
+ cue0.id = CUES_INFO[0].id;
+ let cue1 = new VTTCue(CUES_INFO[1].startTime, CUES_INFO[1].endTime,
+ CUES_INFO[1].text);
+ cue1.id = CUES_INFO[1].id;
+ track.addCue(cue0);
+ track.addCue(cue1);
+ // Convert them to chrome objects in order to use chrome privilege APIs.
+ cue0 = SpecialPowers.wrap(cue0);
+ cue1 = SpecialPowers.wrap(cue1);
+ return [cue0, cue1];
+}
+
+async function startVideo() {
+ info(`start play video`);
+ const played = video && await video.play().then(() => true, () => false);
+ ok(played, "video has started playing");
+}
+
+async function waitUntilCueIsShowing(cue) {
+ info(`wait until cue ${cue.id} is showing`);
+ // cue has not been showing yet.
+ if (!cue.getActive) {
+ await once(cue, "enter");
+ }
+ info(`video current time=${video.currentTime}`);
+ ok(cue.getActive, `cue ${cue.id} is showing`);
+}
+
+async function waitUntilCueIsHiding(cue) {
+ info(`wait until cue ${cue.id} is hiding`);
+ // cue has not been hidden yet.
+ if (cue.getActive) {
+ await once(cue, "exit");
+ }
+ info(`video current time=${video.currentTime}`);
+ ok(!cue.getActive, `cue ${cue.id} is hidding`);
+}
+
+function IsVideoStillPlaying() {
+ ok(!video.paused, `video is still playing, currentTime=${video.currentTime}`);
+}
+
+function endTestAndClearVideo() {
+ removeNodeAndSource(video);
+ SimpleTest.finish();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_positionalign.html b/dom/media/webvtt/test/mochitest/test_webvtt_positionalign.html
new file mode 100644
index 0000000000..267fd52f93
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_positionalign.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>WebVTT : position align test</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="content">
+</div>
+<script class="testbody" type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+var video = document.createElement("video");
+var trackElement = document.createElement("track");
+var cuesNumber = 22;
+
+function isTrackElemenLoaded() {
+ // Re-que isTrackElemenLoaded() at the end of the event loop until the track
+ // element has loaded its data.
+ if (trackElement.readyState == 1) {
+ setTimeout(isTrackElemenLoaded, 0);
+ return;
+ }
+
+ is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
+ runTest();
+}
+
+function runTest() {
+ info("--- check cues number ---");
+ var cues = trackElement.track.cues;
+ is(cues.length, cuesNumber, "Cues number is correct.");
+
+ info("--- check the typedef of TextTrackCue and VTTCue ---");
+ isnot(window.TextTrackCue, undefined, "TextTrackCue should be defined.");
+ isnot(window.VTTCue, undefined, "VTTCue should be defined.");
+
+ info("--- check the type of first parsed cue ---");
+ ok(cues[0] instanceof TextTrackCue, "Cue should be an instanceof TextTrackCue.");
+ ok(cues[0] instanceof VTTCue, "Cue should be an instanceof VTTCue.");
+
+ info("--- check the cue's position alignment ---");
+ let expectedAlignment = ["auto", "line-left", "center", "line-right", "auto"];
+ let idx = 0;
+ for (;idx < expectedAlignment.length; idx++) {
+ is(cues[idx].positionAlign, expectedAlignment[idx], cues[idx].text);
+ }
+
+ info("--- check the cue's computed position alignment ---");
+ // The "computedPositionAlign" is the chrome-only attributes, we need to get
+ // the chrome privilege for cues.
+ let cuesChrome = SpecialPowers.wrap(cues);
+ expectedAlignment.push("line-left", "line-right", "center");
+ for (;idx < expectedAlignment.length; idx++) {
+ is(cuesChrome[idx].computedPositionAlign, expectedAlignment[idx],
+ cuesChrome[idx].text);
+ }
+
+ info(`test only setting text alignment with "start"`);
+ expectedAlignment.push("line-left", "line-right", "line-left", "line-right",
+ "line-left", "line-left", "line-right");
+ for (;idx < expectedAlignment.length; idx++) {
+ is(cuesChrome[idx].computedPositionAlign, expectedAlignment[idx],
+ cuesChrome[idx].text);
+ }
+
+ info(`test only setting text alignment with "end"`);
+ expectedAlignment.push("line-right", "line-left", "line-right", "line-left",
+ "line-right", "line-right", "line-left");
+ for (;idx < expectedAlignment.length; idx++) {
+ is(cuesChrome[idx].computedPositionAlign, expectedAlignment[idx],
+ cuesChrome[idx].text);
+ }
+ is(idx, cuesNumber, "finished checking all cues");
+
+ info("--- check the cue's computed position alignment from DOM API ---");
+ is(cuesChrome[0].computedPositionAlign, "center", "Cue's computedPositionAlign align is center.");
+
+ cuesChrome[0].positionAlign = "auto";
+ is(cuesChrome[0].positionAlign, "auto", "Change cue's position align to \"auto\"");
+
+ cuesChrome[0].align = "left";
+ is(cuesChrome[0].align, "left", "Change cue's align to \"left\".");
+
+ is(cuesChrome[0].computedPositionAlign, "line-left", "Cue's computedPositionAlign becomes to \"line-left\"");
+
+ info("--- finish test ---");
+ SimpleTest.finish();
+}
+
+function setupTest() {
+ info("--- setup test ---");
+ video.src = "seek.webm";
+ video.preload = "auto";
+
+ trackElement.src = "vttPositionAlign.vtt";
+ trackElement.kind = "subtitles";
+ trackElement.default = true;
+
+ document.getElementById("content").appendChild(video);
+ video.appendChild(trackElement);
+ video.addEventListener("loadedmetadata", function() {
+ isTrackElemenLoaded();
+ }, {once: true});
+}
+
+onload = setupTest;
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_seeking.html b/dom/media/webvtt/test/mochitest/test_webvtt_seeking.html
new file mode 100644
index 0000000000..1f85969743
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_seeking.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebVTT : cue should be displayed properly after seeking</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="manifest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+/**
+ * This test is used to ensure that the cue should be showed or hid correctly
+ * after seeking. In this test, we have two cues which are not overlapped, so
+ * there should only have one cue showing at a time.
+ */
+var CUES_INFO = [
+ { id: 0, startTime: 1, endTime: 3, text: "This is cue 0."},
+ { id: 1, startTime: 4, endTime: 6, text: "This is cue 1."},
+];
+
+async function startTest() {
+ const video = createVideo();
+ const cues = createCues(video);
+ await startVideo(video);
+
+ await seekVideo(video, cues[0].startTime);
+ await waitUntilCueIsShowing(cues[0]);
+ checkActiveCueAndInactiveCue(cues[0], cues[1]);
+
+ await seekVideo(video, cues[1].startTime);
+ await waitUntilCueIsShowing(cues[1]);
+ checkActiveCueAndInactiveCue(cues[1], cues[0]);
+
+ // seek forward again
+ await seekVideo(video, cues[0].startTime);
+ await waitUntilCueIsShowing(cues[0]);
+ checkActiveCueAndInactiveCue(cues[0], cues[1]);
+
+ removeNodeAndSource(video);
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = startTest;
+/**
+ * The following are test helper functions.
+ */
+function checkActiveCueAndInactiveCue(activeCue, inactiveCue) {
+ ok(activeCue.getActive,
+ `cue ${activeCue.id} [${activeCue.startTime}:${activeCue.endTime}] is active`);
+ ok(!inactiveCue.getActive,
+ `cue ${inactiveCue.id} [${inactiveCue.startTime}:${inactiveCue.endTime}] is inactive`);
+}
+
+function createVideo() {
+ let video = document.createElement("video");
+ video.src = "gizmo.mp4";
+ video.controls = true;
+ document.body.appendChild(video);
+ return video;
+}
+
+function createCues(video) {
+ let track = video.addTextTrack("subtitles");
+ track.mode = "showing";
+ let cue0 = new VTTCue(CUES_INFO[0].startTime, CUES_INFO[0].endTime,
+ CUES_INFO[0].text);
+ cue0.id = CUES_INFO[0].id;
+ let cue1 = new VTTCue(CUES_INFO[1].startTime, CUES_INFO[1].endTime,
+ CUES_INFO[1].text);
+ cue1.id = CUES_INFO[1].id;
+ track.addCue(cue0);
+ track.addCue(cue1);
+ // Convert them to chrome objects in order to use chrome privilege APIs.
+ cue0 = SpecialPowers.wrap(cue0);
+ cue1 = SpecialPowers.wrap(cue1);
+ return [cue0, cue1];
+}
+
+async function startVideo(video) {
+ info(`start play video`);
+ const played = video && await video.play().then(() => true, () => false);
+ ok(played, "video has started playing");
+}
+
+async function waitUntilCueIsShowing(cue) {
+ info(`wait until cue ${cue.id} shows`);
+ // cue has not been showing yet.
+ if (!cue.getActive) {
+ await once(cue, "enter");
+ }
+ info(`cue ${cue.id} is showing`);
+}
+
+async function seekVideo(video, time) {
+ ok(isInRange(time, CUES_INFO[0].startTime, CUES_INFO[0].endTime) ||
+ isInRange(time, CUES_INFO[1].startTime, CUES_INFO[1].endTime),
+ `seek target time ${time} is within the correct range`)
+ info(`seek video to ${time}`);
+ video.currentTime = time;
+ await once(video, "seeked");
+ info(`seek succeeded, current time=${video.currentTime}`);
+}
+
+function isInRange(value, lowerBound, higherBound) {
+ return lowerBound <= value && value <= higherBound;
+}
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/test_webvtt_update_display_after_adding_or_removing_cue.html b/dom/media/webvtt/test/mochitest/test_webvtt_update_display_after_adding_or_removing_cue.html
new file mode 100644
index 0000000000..7fb8e6761b
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/test_webvtt_update_display_after_adding_or_removing_cue.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>WebVTT : cue display should be updated immediately after adding or removing cue</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="manifest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script class="testbody" type="text/javascript">
+/**
+ * This test is used to ensure that we will update cue display immediately after
+ * adding or removing cue after video starts, because `show-poster` flag would be
+ * reset after video starts, which allows us to process cues instead of showing
+ * a poster. In this test, we start with adding a cue [0:5] to video, which
+ * should be showed in the beginning, and then remove the cue later. The cue
+ * should be removed immediately, not show
+ */
+async function startTest() {
+ const video = await createVideo();
+ await startVideo(video);
+
+ info(`cue should be showed immediately after it was added.`);
+ const cue = createCueAndAddCueToVideo(video);
+ await waitUntilCueShows(cue);
+
+ info(`cue should be hid immediately after it was removed.`);
+ removeCueFromVideo(cue, video);
+ checkIfCueHides(cue, video);
+
+ endTestAndClearVideo(video);
+}
+
+SimpleTest.waitForExplicitFinish();
+onload = startTest;
+
+/**
+ * The following are test helper functions.
+ */
+async function createVideo() {
+ let video = document.createElement("video");
+ video.src = "gizmo.mp4";
+ video.controls = true;
+ document.body.appendChild(video);
+ // wait until media has loaded any data, because we won't update cue if it has
+ // not got any data.
+ await once(video, "loadedmetadata");
+ return video;
+}
+
+async function startVideo(video) {
+ info(`start play video`);
+ const played = video && await video.play().then(() => true, () => false);
+ ok(played, "video has started playing");
+}
+
+function createCueAndAddCueToVideo(video) {
+ let track = video.addTextTrack("subtitles");
+ track.mode = "showing";
+ let cue = new VTTCue(0, 5, "Test");
+ track.addCue(cue);
+ return cue;
+}
+
+function removeCueFromVideo(cue, video) {
+ let track = video.textTracks[0];
+ track.removeCue(cue);
+}
+
+async function waitUntilCueShows(cue) {
+ info(`wait until cue shows`);
+ // cue has not been showed yet.
+ cue = SpecialPowers.wrap(cue);
+ if (!cue.getActive) {
+ await once(cue, "enter");
+ }
+ ok(cue.getActive, `cue has been showed,`);
+}
+
+function checkIfCueHides(cue, video) {
+ ok(!SpecialPowers.wrap(cue).getActive, `cue has been hidden.`);
+ ok(video.currentTime < cue.endTime,
+ `cue is removed at ${video.currentTime}s before reaching its endtime.`);
+}
+
+function endTestAndClearVideo(video) {
+ removeNodeAndSource(video);
+ SimpleTest.finish();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/mochitest/vttPositionAlign.vtt b/dom/media/webvtt/test/mochitest/vttPositionAlign.vtt
new file mode 100644
index 0000000000..7613f4e7c5
--- /dev/null
+++ b/dom/media/webvtt/test/mochitest/vttPositionAlign.vtt
@@ -0,0 +1,86 @@
+WEBVTT
+
+00:00.000 --> 00:00.500
+Cue 0 : PositionAlign should be "auto".
+
+00:00.700 --> 00:00.800 position:50%,line-left
+Cue 1 : PositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 position:50%,center
+Cue 2 : PositionAlign should be "center".
+
+00:00.700 --> 00:00.800 position:50%,line-right
+Cue 3 : PositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 position:50%,auto
+Cue 4 : PositionAlign should be "auto"
+
+00:00.700 --> 00:00.800 position:50%,auto align:left
+Cue 5 : PositionAlign should be "auto", but computedPositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 position:50%,auto align:right
+Cue 6 : PositionAlign should be "auto", but computedPositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 position:50%,auto align:middle
+Cue 7 : PositionAlign should be "auto", but computedPositionAlign should be "center".
+
+NOTE ### These following cues are set with `align:start` ###
+
+00:00.700 --> 00:00.800 align:start
+LTR character in the beginning and align is "start", so computedPositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 align:start
+שלום RTL character in the beginning and align is "start", so computedPositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 align:start
+@ neutral charater in the beginning, but the first strong charater is LTR in "align:start". So computedPositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 align:start
+@ש neutral charater in the beginning, but the first strong charater is RTL in "align:start". So computedPositionAlign should be "line-right".
+
+NOTE
+This line contains only neutral charater, we would treat its base direction as
+LTR. However, if there are other following lines contains non-neutral
+charaters, we would detemine the base direction by the following line.
+
+00:00.700 --> 00:00.800 align:start
+@
+
+00:00.700 --> 00:00.800 align:start
+@
+The second line starts with LTR charater, computedPositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 align:start
+@
+שThe second line starts with RTL charater, computedPositionAlign should be "line-right".
+
+NOTE ### These following cues are set with `align:end` ###
+
+00:00.700 --> 00:00.800 align:end
+LTR character in the beginning and align is "end", so computedPositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 align:end
+ש RTL character in the beginning and align is "end", so computedPositionAlign should be "line-left".
+
+00:00.700 --> 00:00.800 align:end
+@ neutral charater in the beginning, but the first strong charater is LTR in "align:end". So computedPositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 align:end
+@ש neutral charater in the beginning, but the first strong charater is RTL in "align:end". So computedPositionAlign should be "line-left".
+
+NOTE
+This line contains only neutral charater, we would treat its base direction as
+LTR. However, if there are other following lines contains non-neutral
+charaters, we would detemine the base direction by the following line.
+
+00:00.700 --> 00:00.800 align:end
+@
+
+00:00.700 --> 00:00.800 align:end
+@
+The second line starts with LTR charater, computedPositionAlign should be "line-right".
+
+00:00.700 --> 00:00.800 align:end
+@
+שThe second line starts with RTL charater, computedPositionAlign should be "line-left".
+
diff --git a/dom/media/webvtt/test/reftest/black.mp4 b/dom/media/webvtt/test/reftest/black.mp4
new file mode 100644
index 0000000000..24eb3be139
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/black.mp4
Binary files differ
diff --git a/dom/media/webvtt/test/reftest/cues_time_overlapping.webvtt b/dom/media/webvtt/test/reftest/cues_time_overlapping.webvtt
new file mode 100644
index 0000000000..8ed899a9d8
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/cues_time_overlapping.webvtt
@@ -0,0 +1,7 @@
+WEBVTT FILE
+
+00:00:00.000 --> 00:00:01.000
+First cue
+
+00:00:00.000 --> 00:00:04.000
+Second cue
diff --git a/dom/media/webvtt/test/reftest/reftest.list b/dom/media/webvtt/test/reftest/reftest.list
new file mode 100644
index 0000000000..8311bac10f
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/reftest.list
@@ -0,0 +1,3 @@
+skip-if(Android) fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)&&/^aarch64-msvc/.test(xulRuntime.XPCOMABI),0-136,0-427680) == vtt_update_display_after_removed_cue.html vtt_update_display_after_removed_cue_ref.html
+skip-if(Android) fuzzy-if(winWidget,0-170,0-170) == vtt_overlapping_time.html vtt_overlapping_time-ref.html
+skip-if(Android) != vtt_reflow_display.html vtt_reflow_display-ref.html
diff --git a/dom/media/webvtt/test/reftest/vtt_overlapping_time-ref.html b/dom/media/webvtt/test/reftest/vtt_overlapping_time-ref.html
new file mode 100644
index 0000000000..a44e24678b
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_overlapping_time-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+<video id="v1" src="black.mp4" width="320" height="180">
+ <track label="English" src="cues_time_overlapping.webvtt" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is to ensure that when cues with overlapping times, the one with
+ * earlier end timestamp should disappear when the media time reaches its
+ * end time. This vtt file contains two cues, the first cue is [0,1], the second
+ * cue is [0,4], so if we seek video to 2s, only cue2 should be displayed.
+ */
+async function testTimeOverlappingCues() {
+ const video = document.getElementById("v1");
+ video.currentTime = 2;
+ video.onseeked = () => {
+ video.onseeked = null;
+ document.documentElement.removeAttribute('class');
+ }
+};
+
+window.addEventListener("MozReftestInvalidate",
+ testTimeOverlappingCues);
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/vtt_overlapping_time.html b/dom/media/webvtt/test/reftest/vtt_overlapping_time.html
new file mode 100644
index 0000000000..f973b398d5
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_overlapping_time.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+<video id="v1" src="black.mp4" autoplay width="320" height="180">
+ <track label="English" src="cues_time_overlapping.webvtt" default>
+</video>
+<script type="text/javascript">
+/**
+ * This test is to ensure that when cues with overlapping times, the one with
+ * earlier end timestamp should disappear when the media time reaches its
+ * end time. This vtt file contains two cues, the first cue is [0,1], the second
+ * cue is [0,4], so after video is playing over 1s, only cue2 should be displayed.
+ */
+async function testTimeOverlappingCues() {
+ const video = document.getElementById("v1");
+ video.ontimeupdate = () => {
+ if (video.currentTime > 1.0) {
+ document.documentElement.removeAttribute('class');
+ video.ontimeupdate = null;
+ }
+ }
+};
+
+window.addEventListener("MozReftestInvalidate",
+ testTimeOverlappingCues);
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/vtt_reflow_display-ref.html b/dom/media/webvtt/test/reftest/vtt_reflow_display-ref.html
new file mode 100644
index 0000000000..19f3208e6b
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_reflow_display-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<link rel="stylesheet" href="vtt_reflow_display.css">
+<body>
+<div class="video-player">
+ <div class="video-layer">
+ <video id="v1" autoplay controls></video>
+ </div>
+</div>
+<script>
+/**
+ * Simply play and pause a video without any cues.
+ */
+async function testDisplayCueDuringFrequentReflowRef() {
+ const video = document.getElementById("v1");
+ video.src = "white.webm";
+ video.onplay = _ => {
+ video.onplay = null;
+ video.pause();
+ document.documentElement.removeAttribute('class');
+ }
+};
+
+window.addEventListener("MozReftestInvalidate",
+ testDisplayCueDuringFrequentReflowRef);
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/vtt_reflow_display.css b/dom/media/webvtt/test/reftest/vtt_reflow_display.css
new file mode 100644
index 0000000000..4b66a07bd4
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_reflow_display.css
@@ -0,0 +1,33 @@
+body {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ max-height: 100%;
+ width: 100vw;
+ height: 100vh;
+}
+.video-player {
+ display: flex;
+ max-height: calc(100% - 400px);
+ flex: 1 1 0;
+ flex-direction: column;
+ position: relative;
+ max-width: 100%;
+ height: 0;
+}
+.video-layer {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ height: 100%;
+ flex: 1 1 0;
+}
+video {
+ object-fit: contain;
+ display: flex;
+ flex: auto;
+ max-width: 100%;
+ min-height: 0;
+ min-width: 0;
+}
diff --git a/dom/media/webvtt/test/reftest/vtt_reflow_display.html b/dom/media/webvtt/test/reftest/vtt_reflow_display.html
new file mode 100644
index 0000000000..e7ec496bc1
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_reflow_display.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+</head>
+<link rel="stylesheet" href="vtt_reflow_display.css">
+<body>
+<div class="video-player">
+ <div class="video-layer">
+ <video id="v1" autoplay controls></video>
+ </div>
+</div>
+<script>
+/**
+ * In bug 1733232, setting some CSS properties (from bug 1733232 comment17)
+ * would cause video frame's reflow called very frequently, which crashed the
+ * video control and caused no cue showing. We compare this test with another
+ * white video without any cues, and they should NOT be equal.
+ */
+function testDisplayCueDuringFrequentReflow() {
+ let video = document.getElementById("v1");
+ video.src = "white.webm";
+ let cue = new VTTCue(0, 4, "hello testing");
+ cue.onenter = _ => {
+ cue.onenter = null;
+ video.pause();
+ document.documentElement.removeAttribute('class');
+ }
+ let track = video.addTextTrack("captions");
+ track.mode = "showing";
+ track.addCue(cue);
+};
+
+window.addEventListener("MozReftestInvalidate",
+ testDisplayCueDuringFrequentReflow);
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue.html b/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue.html
new file mode 100644
index 0000000000..4cd5d5bbd2
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+<video id="v1" autoplay></video>
+<script type="text/javascript">
+
+/**
+ * This test is used to ensure we would update the cue display after removing
+ * cue from the text track, the removed cue should not display on the video's
+ * rendering area.
+ */
+function testUpdateDisplayAfterRemovedCue() {
+ let video = document.getElementById("v1");
+ video.src = "black.mp4";
+ let cue = new VTTCue(0, 4, "hello testing");
+ let track = video.addTextTrack("captions");
+ track.mode = "showing";
+ track.addCue(cue);
+ cue.onenter = () => {
+ cue.onenter = null;
+ track.removeCue(cue);
+ video.pause();
+ video.onpause = () => {
+ video.onpause = null;
+ document.documentElement.removeAttribute('class');
+ }
+ }
+};
+
+window.addEventListener("MozReftestInvalidate",
+ testUpdateDisplayAfterRemovedCue);
+</script>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue_ref.html b/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue_ref.html
new file mode 100644
index 0000000000..0b1afdc568
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/vtt_update_display_after_removed_cue_ref.html
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<video id="v1" src="black.mp4"></video>
+</body>
+</html>
diff --git a/dom/media/webvtt/test/reftest/white.webm b/dom/media/webvtt/test/reftest/white.webm
new file mode 100644
index 0000000000..bbacad7ffd
--- /dev/null
+++ b/dom/media/webvtt/test/reftest/white.webm
Binary files differ
diff --git a/dom/media/webvtt/test/xpcshell/test_parser.js b/dom/media/webvtt/test/xpcshell/test_parser.js
new file mode 100644
index 0000000000..5ae70f9762
--- /dev/null
+++ b/dom/media/webvtt/test/xpcshell/test_parser.js
@@ -0,0 +1,158 @@
+"use strict";
+
+const { WebVTT } = ChromeUtils.importESModule(
+ "resource://gre/modules/vtt.sys.mjs"
+);
+
+let fakeWindow = {
+ /* eslint-disable object-shorthand */
+ VTTCue: function () {},
+ VTTRegion: function () {},
+ /* eslint-enable object-shorthand */
+};
+
+// We have a better parser check in WPT. Here I want to check that incomplete
+// lines are correctly parsable.
+let tests = [
+ // Signature
+ { input: ["WEBVTT"], cue: 0, region: 0 },
+ { input: ["", "WE", "BVT", "T"], cue: 0, region: 0 },
+ { input: ["WEBVTT - This file has no cues."], cue: 0, region: 0 },
+ { input: ["WEBVTT", " - ", "This file has no cues."], cue: 0, region: 0 },
+
+ // Body with IDs
+ {
+ input: [
+ "WEB",
+ "VTT - This file has cues.\n",
+ "\n",
+ "14\n",
+ "00:01:14",
+ ".815 --> 00:0",
+ "1:18.114\n",
+ "- What?\n",
+ "- Where are we now?\n",
+ "\n",
+ "15\n",
+ "00:01:18.171 --> 00:01:20.991\n",
+ "- T",
+ "his is big bat country.\n",
+ "\n",
+ "16\n",
+ "00:01:21.058 --> 00:01:23.868\n",
+ "- [ Bat",
+ "s Screeching ]\n",
+ "- They won't get in your hair. They're after the bug",
+ "s.\n",
+ ],
+ cue: 3,
+ region: 0,
+ },
+
+ // Body without IDs
+ {
+ input: [
+ "WEBVTT - This file has c",
+ "ues.\n",
+ "\n",
+ "00:01:14.815 --> 00:01:18.114\n",
+ "- What?\n",
+ "- Where are we now?\n",
+ "\n",
+ "00:01:18.171 --> 00:01:2",
+ "0.991\n",
+ "- ",
+ "This is big bat country.\n",
+ "\n",
+ "00:01:21.058 --> 00:01:23.868\n",
+ "- [ Bats S",
+ "creeching ]\n",
+ "- They won't get in your hair. They're after the bugs.\n",
+ ],
+ cue: 3,
+ region: 0,
+ },
+
+ // Note
+ {
+ input: ["WEBVTT - This file has no cues.\n", "\n", "NOTE what"],
+ cue: 0,
+ region: 0,
+ },
+
+ // Regions - This vtt is taken from a WPT
+ {
+ input: [
+ "WE",
+ "BVTT\n",
+ "\n",
+ "REGION\n",
+ "id:0\n",
+ "\n",
+ "REGION\n",
+ "id:1\n",
+ "region",
+ "an",
+ "chor:0%,0%\n",
+ "\n",
+ "R",
+ "EGION\n",
+ "id:2\n",
+ "regionanchor:18446744073709552000%,18446744",
+ "073709552000%\n",
+ "\n",
+ "REGION\n",
+ "id:3\n",
+ "regionanchor: 100%,100%\n",
+ "regio",
+ "nanchor :100%,100%\n",
+ "regionanchor:100% ,100%\n",
+ "regionanchor:100%, 100%\n",
+ "regionanchor:100 %,100%\n",
+ "regionanchor:10",
+ "0%,100 %\n",
+ "\n",
+ "00:00:00.000 --> 00:00:01.000",
+ " region:0\n",
+ "text\n",
+ "\n",
+ "00:00:00.000 --> 00:00:01.000 region:1\n",
+ "text\n",
+ "\n",
+ "00:00:00.000 --> 00:00:01.000 region:3\n",
+ "text\n",
+ ],
+ cue: 3,
+ region: 4,
+ },
+];
+
+function run_test() {
+ tests.forEach(test => {
+ let parser = new WebVTT.Parser(fakeWindow, null);
+ ok(!!parser, "Ok... this is a good starting point");
+
+ let cue = 0;
+ parser.oncue = () => {
+ ++cue;
+ };
+
+ let region = 0;
+ parser.onregion = () => {
+ ++region;
+ };
+
+ parser.onparsingerror = () => {
+ ok(false, "No error accepted");
+ };
+
+ test.input.forEach(input => {
+ parser.parse(new TextEncoder().encode(input));
+ });
+
+ parser.flush();
+
+ equal(cue, test.cue, "Cue value matches");
+ equal(region, test.region, "Region value matches");
+ });
+}
diff --git a/dom/media/webvtt/test/xpcshell/xpcshell.ini b/dom/media/webvtt/test/xpcshell/xpcshell.ini
new file mode 100644
index 0000000000..07aa5d80d8
--- /dev/null
+++ b/dom/media/webvtt/test/xpcshell/xpcshell.ini
@@ -0,0 +1,3 @@
+[DEFAULT]
+
+[test_parser.js]