summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/webvtt/parsing
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/webvtt/parsing
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/webvtt/parsing')
-rw-r--r--testing/web-platform/tests/webvtt/parsing/README.md9
-rw-r--r--testing/web-platform/tests/webvtt/parsing/categories.json8
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/buildtests.py71
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/common.js196
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/entities.dat150
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tags.dat214
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/text.dat29
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/timestamps.dat63
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tree-building.dat88
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/entities.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tags.html42
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/text.html19
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/timestamps.html24
-rw-r--r--testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tree-building.html23
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/README.md52
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/categories.json6
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/signature-invalid.html49
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/arrows.test38
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/comment-in-cue-text.test28
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/empty.vtt0
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-garbage.test15
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-space.test14
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-tab.test14
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-timings.test13
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/ids.test32
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/newlines.test36
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/nulls.test232
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-id.test52
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-lines.test129
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-old.test18
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-regionanchor.test182
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-scroll.test67
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-viewportanchor.test182
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-align.test64
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-line.test223
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-multiple.test34
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-position.test102
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-region.test71
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-size.test78
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-vertical.test47
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-bom.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-formfeed.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid-whitespace.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-lowercase.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing-whitespace.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing.vtt2
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-no-newline.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-null.vttbin0 -> 8 bytes
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-partial.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space-no-newline.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab-no-newline.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab.test7
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-timings.test8
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-two-boms.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-websrt.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/stylesheets.test36
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-60.test33
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-eof.test9
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-garbage.test197
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-negative.test33
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-omitted-hours.test22
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-long.test60
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-short.test111
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/support/whitespace-chars.test32
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/arrows.html44
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/categories.json9
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/comment-in-cue-text.html47
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-garbage.html43
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-regions.html50
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-space.html43
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-tab.html43
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-timings.html43
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/ids.html44
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/newlines.html51
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/nulls.html60
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html55
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-id.html51
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-lines.html64
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-old.html42
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-regionanchor.html66
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-scroll.html54
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-viewportanchor.html66
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-align.html57
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-line.html102
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-multiple.html58
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-position.html64
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-region.html64
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-size.html58
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-vertical.html55
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-bom.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-no-newline.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space-no-newline.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab-no-newline.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-timings.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/stylesheets.html40
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/arrows.vtt27
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/comment-in-cue-text.vtt14
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-garbage.vtt5
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-regions.vtt59
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-space.vtt4
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-tab.vtt4
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-timings.vtt3
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/ids.vtt21
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/newlines.vtt12
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/nulls.vttbin0 -> 2792 bytes
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt44
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-id.vtt34
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-lines.vtt98
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-old.vtt9
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-regionanchor.vtt149
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-scroll.vtt46
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-viewportanchor.vtt149
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-align.vtt40
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-line.vtt154
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-multiple.vtt9
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-position.vtt71
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-region.vtt40
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-size.vtt53
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-vertical.vtt25
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-bom.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-no-newline.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space-no-newline.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab-no-newline.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab.vtt1
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-timings.vtt2
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/stylesheets.vtt29
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-60.vtt19
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-eof.vtt3
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-garbage.vtt190
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-negative.vtt13
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-omitted-hours.vtt10
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-long.vtt46
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-short.vtt97
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/whitespace-chars.vtt17
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-60.html47
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-eof.html39
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-garbage.html40
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-negative.html53
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-omitted-hours.html45
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-long.html47
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-short.html47
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tests/whitespace-chars.html48
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tools/build.py120
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tools/parser.py710
-rw-r--r--testing/web-platform/tests/webvtt/parsing/file-parsing/tools/spec_report.py99
150 files changed, 7789 insertions, 0 deletions
diff --git a/testing/web-platform/tests/webvtt/parsing/README.md b/testing/web-platform/tests/webvtt/parsing/README.md
new file mode 100644
index 0000000000..e789c1657b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/README.md
@@ -0,0 +1,9 @@
+# Parsing Tests
+
+Tests the [parsing section of the WebVTT spec.](https://w3c.github.io/webvtt/#parsing)
+
+Tests for [file parsing](https://w3c.github.io/webvtt/#file-parsing) are located
+in `file-parsing/`.
+
+Tests for [cue text parsing](https://w3c.github.io/webvtt/#cue-text-parsing-rules)
+are located in `cue-text-parsing/`
diff --git a/testing/web-platform/tests/webvtt/parsing/categories.json b/testing/web-platform/tests/webvtt/parsing/categories.json
new file mode 100644
index 0000000000..1ae85203e4
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/categories.json
@@ -0,0 +1,8 @@
+{
+ ":categories": [
+ ["file-parsing", "cue-text-parsing"]
+ ],
+ ":subcategories": ["file-parsing/categories.json"],
+ "file-parsing/*": "file-parsing",
+ "cue-text-parsing/*": "cue-text-parsing"
+}
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/buildtests.py b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/buildtests.py
new file mode 100644
index 0000000000..2152055000
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/buildtests.py
@@ -0,0 +1,71 @@
+#!/usr/bin/python3
+
+import os
+import urllib.parse
+import hashlib
+
+doctmpl = """\
+<!doctype html>
+<title>WebVTT cue data parser test %s</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+%s
+]);
+</script>
+"""
+
+testobj = "{name:'%s', input:'%s', expected:'%s'}"
+
+def appendtest(tests, input, expected):
+ tests.append(testobj % (hashlib.sha1(input.encode('UTF-8')).hexdigest(), urllib.parse.quote(input[:-1]), urllib.parse.quote(expected[:-1])))
+
+files = os.listdir('dat/')
+for file in files:
+ if os.path.isdir('dat/'+file) or file[0] == ".":
+ continue
+
+ tests = []
+ input = ""
+ expected = ""
+ state = ""
+ with open('dat/'+file, "r") as f:
+ while True:
+ line = f.readline()
+ if not line:
+ if state != "":
+ appendtest(tests, input, expected)
+ input = ""
+ expected = ""
+ state = ""
+ break
+
+ if line[0] == "#":
+ state = line
+ if line == "#document-fragment\n":
+ expected += bytes(line, 'UTF-8').decode('unicode-escape')
+ elif state == "#data\n":
+ input += bytes(line, 'UTF-8').decode('unicode-escape')
+ elif state == "#errors\n":
+ pass
+ elif state == "#document-fragment\n":
+ if line == "\n":
+ appendtest(tests, input, expected)
+ input = ""
+ expected = ""
+ state = ""
+ else:
+ expected += bytes(line, 'UTF-8').decode('unicode-escape')
+ else:
+ raise Exception("failed to parse file %s:%s (state: %s)" % (file, line, state))
+
+ name = os.path.splitext(file)[0]
+ with open('tests/'+name+".html", "w") as out:
+ out.write(doctmpl % (name, ",\n".join(tests)))
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/common.js b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/common.js
new file mode 100644
index 0000000000..c72bdc06d9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/common.js
@@ -0,0 +1,196 @@
+var namespaces = {
+ "html":"http://www.w3.org/1999/xhtml",
+ "mathml":"http://www.w3.org/1998/Math/MathML",
+ "svg":"http://www.w3.org/2000/svg",
+ "xlink":"http://www.w3.org/1999/xlink",
+ "xml":"http://www.w3.org/XML/1998/namespace",
+ "xmlns":"http://www.w3.org/2000/xmlns/"
+};
+
+var prefixes = {};
+for (var prefix in namespaces) {
+ if (namespaces.hasOwnProperty(prefix)) {
+ prefixes[namespaces[prefix]] = prefix;
+ }
+}
+prefixes[namespaces["mathml"]] = "math";
+
+function format(format_string) {
+ var insertions = Array.prototype.slice.call(arguments, 1);
+ var regexp = /%s/g;
+ var match_count = 0;
+ var rv = format_string.replace(regexp, function(match) {
+ var rv = insertions[match_count];
+ match_count++;
+ return rv;
+ });
+ return rv;
+}
+
+function test_serializer(element) {
+ //element.normalize();
+ var lines = [];
+ function serialize_element(element, indent) {
+ var indent_spaces = (new Array(indent)).join(" ");
+ switch(element.nodeType) {
+ case Node.DOCUMENT_TYPE_NODE:
+ if (element.name) {
+ if (element.publicId || element.systemId) {
+ var publicId = element.publicId ? element.publicId : "";
+ var systemId = element.systemId ? element.systemId : "";
+ lines.push(format("|%s<!DOCTYPE %s \"%s\" \"%s\">", indent_spaces,
+ element.name, publicId, systemId));
+ } else {
+ lines.push(format("|%s<!DOCTYPE %s>", indent_spaces,
+ element.name));
+ }
+ } else {
+ lines.push(format("|%s<!DOCTYPE >", indent_spaces));
+ }
+ break;
+ case Node.DOCUMENT_NODE:
+ lines.push("#document");
+ break;
+ case Node.DOCUMENT_FRAGMENT_NODE:
+ lines.push("#document-fragment");
+ break;
+ case Node.PROCESSING_INSTRUCTION_NODE:
+ lines.push(format("|%s<?%s %s>", indent_spaces, element.target, element.data));
+ break;
+ case Node.COMMENT_NODE:
+ lines.push(format("|%s<!-- %s -->", indent_spaces, element.nodeValue));
+ break;
+ case Node.TEXT_NODE:
+ lines.push(format("|%s\"%s\"", indent_spaces, element.nodeValue));
+ break;
+ case Node.ELEMENT_NODE:
+ if (element.getAttribute("data-skip") !== null) {
+ return;
+ }
+ if (element.namespaceURI !== null && element.namespaceURI !== namespaces.html) {
+ var name = format("%s %s", prefixes[element.namespaceURI],
+ element.localName);
+ } else {
+ var name = element.localName;
+ }
+ lines.push(format("|%s<%s>", indent_spaces, name));
+
+ var attributes = Array.prototype.map.call(
+ element.attributes,
+ function(attr) {
+ var name = (attr.namespaceURI ? prefixes[attr.namespaceURI] + " " : "") +
+ attr.localName;
+ return [name, attr.value];
+ });
+ attributes.sort(function (a, b) {
+ var x = a[0];
+ var y = b[0];
+ if (x === y) {
+ return 0;
+ }
+ return x > y ? 1 : -1;
+ });
+
+ attributes.forEach(
+ function(attr) {
+ var indent_spaces = (new Array(indent + 2)).join(" ");
+ lines.push(format("|%s%s=\"%s\"", indent_spaces, attr[0], attr[1]));
+ }
+ );
+ break;
+ }
+ indent += 2;
+ Array.prototype.forEach.call(element.childNodes,
+ function(node) {
+ serialize_element(node, indent);
+ });
+ }
+ serialize_element(element, 0);
+ return lines.join("\n");
+}
+
+function print_diffs(test_id, uri_encoded_input, expected, actual, container) {
+ container = container ? container : null;
+ if (actual) {
+ var diffs = mark_diffs(expected, actual);
+ var expected_text = diffs[0];
+ var actual_text = diffs[1];
+ } else {
+ var expected_text = expected;
+ var actual_text = "";
+ }
+
+ var tmpl = ["div", {"id":"${test_id}"},
+ ["h2", {}, "${test_id}"],
+ function(vars) {
+ if (vars.container !== null) {
+ return ["div", {"class":"container"},
+ ["h3", {}, "innerHTML Container"],
+ ["pre", {}, vars.container]];
+ } else {
+ return null;
+ }
+ },
+ ["div", {"id":"input_${test_id}"}, ["h3", {}, "Input"], ["pre", {},
+ ["code", {}, decodeURIComponent(uri_encoded_input)]]],
+ ["div", {"id":"expected_${test_id}"}, ["h3", {}, "Expected"],
+ ["pre", {}, ["code", {}, expected_text]]],
+ ["div", {"id":"actual_${test_id}"}, ["h3", {}, "Actual"],
+ ["pre", {}, ["code", {}, actual_text]]]
+ ];
+
+ var diff_dom = template.render(tmpl, {test_id:test_id, container:container});
+ document.body.appendChild(diff_dom);
+}
+
+function runTests(tests) {
+ tests.forEach(function(test){
+ var expected = decodeURIComponent(test.expected);
+ var t = async_test(document.title + ' - ' + test.name);
+ t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track not supported');
+ t.test_id = test.name;
+ t.url_encoded_input = test.input;
+ t.expected = expected;
+ var track_blob = new Blob(['WEBVTT\n\n00:00.000 --> 00:01.000\n',
+ decodeURIComponent(test.input)],
+ { type: 'text/vtt' });
+ var track_url = URL.createObjectURL(track_blob);;
+ track.src = track_url;
+ t.add_cleanup(function() {
+ URL.revokeObjectURL(track_url);
+ });
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = t.step_func(trackLoaded);
+ track.onerror = t.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+ });
+ });
+}
+
+function trackLoaded(e) {
+ var track = e.target;
+ setTimeout(removeElm, 0, track.parentNode);
+ var cue = track.track.cues[0];
+ var frag = cue.getCueAsHTML();
+ var got = test_serializer(frag);
+ if (got !== this.expected) {
+ print_diffs(this.test_id, this.url_encoded_input, this.expected, got);
+ }
+ assert_equals(got, this.expected);
+ this.done();
+}
+
+function trackError(e) {
+ setTimeout(removeElm, 0, e.target.parentNode);
+ assert_unreached('got error event');
+ this.done();
+}
+
+function removeElm(elm) {
+ document.body.removeChild(elm);
+}
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/entities.dat b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/entities.dat
new file mode 100644
index 0000000000..6522e3f5b8
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/entities.dat
@@ -0,0 +1,150 @@
+#data
+&
+#errors
+#document-fragment
+| "&"
+
+#data
+&amp
+#errors
+#document-fragment
+| "&"
+
+#data
+&amp;
+#errors
+#document-fragment
+| "&"
+
+#data
+&AMP;
+#errors
+#document-fragment
+| "&"
+
+#data
+&lt;
+#errors
+#document-fragment
+| "<"
+
+#data
+&gt;
+#errors
+#document-fragment
+| ">"
+
+#data
+a&lrm;b
+#errors
+#document-fragment
+| "a\u200Eb"
+
+#data
+a&rlm;b
+#errors
+#document-fragment
+| "a\u200Fb"
+
+#data
+&quot;
+#errors
+#document-fragment
+| "\u0022"
+
+#data
+&nbsp;
+#errors
+#document-fragment
+| "\u00A0"
+
+#data
+&copy;
+#errors
+#document-fragment
+| "\u00A9"
+
+#data
+&&
+#errors
+#document-fragment
+| "&&"
+
+#data
+&1
+#errors
+#document-fragment
+| "&1"
+
+#data
+&1;
+#errors
+#document-fragment
+| "&1;"
+
+#data
+&<
+#errors
+#document-fragment
+| "&"
+
+#data
+&<c
+#errors
+#document-fragment
+| "&"
+| <span>
+
+#data
+&#32;
+#errors
+#document-fragment
+| " "
+
+#data
+&#x20;
+#errors
+#document-fragment
+| " "
+
+#data
+&;
+#errors
+#document-fragment
+| "&;"
+
+#data
+&ClockwiseContourIntegral;
+#errors
+#document-fragment
+| "\u2232"
+
+#data
+&nsubE;
+#errors
+#document-fragment
+| "\u2AC5\u0338"
+
+#data
+&notin;
+#errors
+#document-fragment
+| "\u2209"
+
+#data
+&not;
+#errors
+#document-fragment
+| "\u00AC"
+
+#data
+&not
+#errors
+#document-fragment
+| "\u00AC"
+
+#data
+&notit;
+#errors
+#document-fragment
+| "\u00ACit;"
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tags.dat b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tags.dat
new file mode 100644
index 0000000000..0ef77a09a1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tags.dat
@@ -0,0 +1,214 @@
+#data
+<
+#errors
+#document-fragment
+
+#data
+<<
+#errors
+#document-fragment
+
+#data
+<\t
+#errors
+#document-fragment
+
+#data
+<\n
+#errors
+#document-fragment
+
+#data
+<\x20
+#errors
+#document-fragment
+
+#data
+<.
+#errors
+#document-fragment
+
+#data
+<c.
+#errors
+#document-fragment
+| <span>
+
+#data
+</
+#errors
+#document-fragment
+
+#data
+<c></>x
+#errors
+#document-fragment
+| <span>
+| "x"
+
+#data
+<c></
+c>x
+#errors
+#document-fragment
+| <span>
+| "x"
+
+#data
+<c>test
+#errors
+#document-fragment
+| <span>
+| "test"
+
+#data
+a<c.d e>b</c>c
+#errors
+#document-fragment
+| "a"
+| <span>
+| class="d"
+| "b"
+| "c"
+
+#data
+<i>test
+#errors
+#document-fragment
+| <i>
+| "test"
+
+#data
+a<i.d e>b</i>c
+#errors
+#document-fragment
+| "a"
+| <i>
+| class="d"
+| "b"
+| "c"
+
+#data
+<b>test
+#errors
+#document-fragment
+| <b>
+| "test"
+
+#data
+a<b.d e>b</b>c
+#errors
+#document-fragment
+| "a"
+| <b>
+| class="d"
+| "b"
+| "c"
+
+#data
+<u>test
+#errors
+#document-fragment
+| <u>
+| "test"
+
+#data
+a<u.d e>b</u>c
+#errors
+#document-fragment
+| "a"
+| <u>
+| class="d"
+| "b"
+| "c"
+
+#data
+<ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+
+#data
+a<ruby.f g>b<rt.h j>c</rt>d</ruby>e
+#errors
+#document-fragment
+| "a"
+| <ruby>
+| class="f"
+| "b"
+| <rt>
+| class="h"
+| "c"
+| "d"
+| "e"
+
+#data
+<rt>test
+#errors
+#document-fragment
+| "test"
+
+#data
+<v>test
+#errors
+#document-fragment
+| <span>
+| title=""
+| "test"
+
+#data
+<v a>test
+#errors
+#document-fragment
+| <span>
+| title="a"
+| "test"
+
+#data
+<v a b>test
+#errors
+#document-fragment
+| <span>
+| title="a b"
+| "test"
+
+#data
+<v.a>test
+#errors
+#document-fragment
+| <span>
+| class="a"
+| title=""
+| "test"
+
+#data
+<v.a.b>test
+#errors
+#document-fragment
+| <span>
+| class="a b"
+| title=""
+| "test"
+
+#data
+a<v.d e>b</v>c
+#errors
+#document-fragment
+| "a"
+| <span>
+| class="d"
+| title="e"
+| "b"
+| "c"
+
+#data
+a<lang.d e>b</lang>c
+#errors
+#document-fragment
+| "a"
+| <span>
+| class="d"
+| lang="e"
+| "b"
+| "c"
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/text.dat b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/text.dat
new file mode 100644
index 0000000000..e4129a2ec9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/text.dat
@@ -0,0 +1,29 @@
+#data
+text
+#errors
+#document-fragment
+| "text"
+
+#data
+text1\ntext2
+#errors
+#document-fragment
+| "text1\ntext2"
+
+#data
+foo\x00bar
+#errors
+#document-fragment
+| "foo\uFFFDbar"
+
+#data
+\u2713
+#errors
+#document-fragment
+| "\u2713"
+
+#data
+text1\n\ntext2
+#errors
+#document-fragment
+| "text1"
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/timestamps.dat b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/timestamps.dat
new file mode 100644
index 0000000000..a3aea9af6c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/timestamps.dat
@@ -0,0 +1,63 @@
+#data
+<0
+#errors
+#document-fragment
+
+#data
+<0.500
+#errors
+#document-fragment
+
+#data
+<0:00.500
+#errors
+#document-fragment
+
+#data
+<00:\x0000:00.500>
+#errors
+#document-fragment
+
+#data
+<00:00.500
+#errors
+#document-fragment
+| <?timestamp 00:00:00.500>
+
+#data
+<00:00:00.500
+#errors
+#document-fragment
+| <?timestamp 00:00:00.500>
+
+#data
+test<00:00:00.500>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 00:00:00.500>
+| "test"
+
+#data
+test<01:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 01:00:00.000>
+| "test"
+
+#data
+test<10:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 10:00:00.000>
+| "test"
+
+#data
+test<100:00:00.000>test
+#errors
+#document-fragment
+| "test"
+| <?timestamp 100:00:00.000>
+| "test"
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tree-building.dat b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tree-building.dat
new file mode 100644
index 0000000000..48d7ab20bf
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/dat/tree-building.dat
@@ -0,0 +1,88 @@
+#data
+test
+#errors
+#document-fragment
+| "test"
+
+#data
+<ruby>test<rt>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+
+#data
+<ruby>test<rt>test</rt>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt>test</rt></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt>test</ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></ruby></b>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
+
+#data
+<ruby>test<rt><b>test</rt></b></ruby>test
+#errors
+#document-fragment
+| <ruby>
+| "test"
+| <rt>
+| <b>
+| "test"
+| "test"
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/entities.html b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/entities.html
new file mode 100644
index 0000000000..dbae784de1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/entities.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<title>WebVTT cue data parser test entities</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'3686fc0cdc60dc536e75df054b0bd372273db2cc', input:'%26', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'f1869f6e2853635eec81cc3afa3e2b8148ccbdc0', input:'%26amp', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'92d76530d723b6b4e4ef8280c01cf1c80f9bebdb', input:'%26amp%3B', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'261cd4e9df4a12535b66a0c39e9635aab2bb19aa', input:'%26AMP%3B', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'1a2269cdb73bf97ec6a99b0edabfe646c471b67e', input:'%26lt%3B', expected:'%23document-fragment%0A%7C%20%22%3C%22'},
+{name:'44ceb90884cceeeccb4f7024e3598f7dc5ceebfa', input:'%26gt%3B', expected:'%23document-fragment%0A%7C%20%22%3E%22'},
+{name:'05def72af03fc2b1617da950d871b9fd0ba20e5a', input:'a%26lrm%3Bb', expected:'%23document-fragment%0A%7C%20%22a%E2%80%8Eb%22'},
+{name:'da999a55445eca43aa41e039ec439c1a812db297', input:'a%26rlm%3Bb', expected:'%23document-fragment%0A%7C%20%22a%E2%80%8Fb%22'},
+{name:'0fd9e3823b62c028c1d50e35b1f3ee3df02a62eb', input:'%26quot%3B', expected:'%23document-fragment%0A%7C%20%22%22%22'},
+{name:'e7387003fbacb22b706796c98b781eb4ebf5ff85', input:'%26nbsp%3B', expected:'%23document-fragment%0A%7C%20%22%C2%A0%22'},
+{name:'216cd0e914b9f2ccd04eff6d02a0b1ce24441d95', input:'%26copy%3B', expected:'%23document-fragment%0A%7C%20%22%C2%A9%22'},
+{name:'2cdf20980d17a5d077299215e6a7e97f3c6b07e2', input:'%26%26', expected:'%23document-fragment%0A%7C%20%22%26%26%22'},
+{name:'83f4500c0bd8598480713997a041d8f70fd3f11e', input:'%261', expected:'%23document-fragment%0A%7C%20%22%261%22'},
+{name:'2c6b2ba38a08eca45370f28a5b7df2aa463fb3dc', input:'%261%3B', expected:'%23document-fragment%0A%7C%20%22%261%3B%22'},
+{name:'f4bb977c0a06851bdd19260c035a766c5c8ea093', input:'%26%3C', expected:'%23document-fragment%0A%7C%20%22%26%22'},
+{name:'b1fff1ac42688d16e00f6c758d84e5152e39702d', input:'%26%3Cc', expected:'%23document-fragment%0A%7C%20%22%26%22%0A%7C%20%3Cspan%3E'},
+{name:'bd68f6beda2c2264e61dff7359c1ad48bc0a9934', input:'%26%2332%3B', expected:'%23document-fragment%0A%7C%20%22%20%22'},
+{name:'5b77a0be23453dfe6eea59d43bb0708f89e1df82', input:'%26%23x20%3B', expected:'%23document-fragment%0A%7C%20%22%20%22'},
+{name:'87986551b0e6180cb279f2aa4cdddf77daa90c11', input:'%26%3B', expected:'%23document-fragment%0A%7C%20%22%26%3B%22'},
+{name:'e3ac2060b915f0f499b2863f999dcdb38a5db79b', input:'%26ClockwiseContourIntegral%3B', expected:'%23document-fragment%0A%7C%20%22%E2%88%B2%22'},
+{name:'31c8a5ecfa5c54d8c0ec5b4ee8f0bbea0d6d40af', input:'%26nsubE%3B', expected:'%23document-fragment%0A%7C%20%22%E2%AB%85%CC%B8%22'},
+{name:'9ed59950764468c4ef2948d71cf75c3f2b60c74d', input:'%26notin%3B', expected:'%23document-fragment%0A%7C%20%22%E2%88%89%22'},
+{name:'71a6efcfab81264fb95bb3234c59687c11c72baf', input:'%26not%3B', expected:'%23document-fragment%0A%7C%20%22%C2%AC%22'},
+{name:'86d7c20ca3c060f9e699c7da43927c4a07a5d569', input:'%26not', expected:'%23document-fragment%0A%7C%20%22%C2%AC%22'},
+{name:'314cd94292df37044e90ce27b5606bf8ec636b94', input:'%26notit%3B', expected:'%23document-fragment%0A%7C%20%22%C2%ACit%3B%22'}
+]);
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tags.html b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tags.html
new file mode 100644
index 0000000000..c624320f2b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tags.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<title>WebVTT cue data parser test tags</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'d49e42f7582c6f00b2569f2d14629611c0c6b0e6', input:'%3C', expected:'%23document-fragment'},
+{name:'9dd187edd10c907e6b92148fd82940e401dbe79f', input:'%3C%3C', expected:'%23document-fragment'},
+{name:'2d2c4333983e23a4962083e8120e5d42c839f77b', input:'%3C%09', expected:'%23document-fragment'},
+{name:'94f898df44b470e2d05d74c6816fd908e55c9fdf', input:'%3C%0A', expected:'%23document-fragment'},
+{name:'2fdc1b84ba41ec98833851e80781df1fbe72182f', input:'%3C%20', expected:'%23document-fragment'},
+{name:'487690a6f5da4666f9caaf3a3ecc10992aca1414', input:'%3C.', expected:'%23document-fragment'},
+{name:'0d7df935b172f2a1b357b94596d68f2443f30f8b', input:'%3Cc.', expected:'%23document-fragment%0A%7C%20%3Cspan%3E'},
+{name:'cd1d6dd274e03ae8fc56bc4ef163998d9ff24496', input:'%3C/', expected:'%23document-fragment'},
+{name:'fca1a11d42b735453117f42456360e88082a3fd7', input:'%3Cc%3E%3C/%3Ex', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22x%22'},
+{name:'fe3b6277edf5c2f84e7a6779eddd0cac30552bca', input:'%3Cc%3E%3C/%0Ac%3Ex', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22x%22'},
+{name:'6ceded63b53eeab3681a0fc540e959ca88f7dce9', input:'%3Cc%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20%22test%22'},
+{name:'cdcdb0d5d6a975c5612eabcbea5d732ff3bc9f56', input:'a%3Cc.d%20e%3Eb%3C/c%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'},
+{name:'71de37451e7d5524eacc8a190d21cd64c4304e14', input:'%3Ci%3Etest', expected:'%23document-fragment%0A%7C%20%3Ci%3E%0A%7C%20%20%20%22test%22'},
+{name:'70f72cc4d2139d9e8c33189a1a9b89ecd6014a15', input:'a%3Ci.d%20e%3Eb%3C/i%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Ci%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'},
+{name:'985284b688a09f1f55e3c9aab49d7e4ca11f870a', input:'%3Cb%3Etest', expected:'%23document-fragment%0A%7C%20%3Cb%3E%0A%7C%20%20%20%22test%22'},
+{name:'39c36af6d6850bc474f1d9962c1133933fd50dd0', input:'a%3Cb.d%20e%3Eb%3C/b%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cb%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'},
+{name:'fa6993eaa94404648d8b52e2830e53369404fdcb', input:'%3Cu%3Etest', expected:'%23document-fragment%0A%7C%20%3Cu%3E%0A%7C%20%20%20%22test%22'},
+{name:'45221829445210412642152bfb22fa2ed222d46e', input:'a%3Cu.d%20e%3Eb%3C/u%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cu%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'},
+{name:'e4d351e1a6b40a7dace801b722efaa200c4895f2', input:'%3Cruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22'},
+{name:'a8481eabd1dcac1d02e57e74d499e2395ac171cd', input:'a%3Cruby.f%20g%3Eb%3Crt.h%20j%3Ec%3C/rt%3Ed%3C/ruby%3Ee', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cruby%3E%0A%7C%20%20%20class%3D%22f%22%0A%7C%20%20%20%22b%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20class%3D%22h%22%0A%7C%20%20%20%20%20%22c%22%0A%7C%20%20%20%22d%22%0A%7C%20%22e%22'},
+{name:'68e1d0376f827ebe0c047751a2067594ff41b612', input:'%3Crt%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22'},
+{name:'ab2024b4e65ed64a751adbe8aae1e84ee61bf3e6', input:'%3Cv%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'},
+{name:'10f4823ffb17c71654c4602bc45c58300e3ecbcc', input:'%3Cv%20a%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22a%22%0A%7C%20%20%20%22test%22'},
+{name:'909924ef392fb20c9526acfa4f18f891eda61a0c', input:'%3Cv%20a%20b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20title%3D%22a%20b%22%0A%7C%20%20%20%22test%22'},
+{name:'e5ca35cc29404efc0ebd58aa5f6efefc86fc5287', input:'%3Cv.a%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22a%22%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'},
+{name:'e535c486dac7dc571463b150adc55fd841bc3008', input:'%3Cv.a.b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22a%20b%22%0A%7C%20%20%20title%3D%22%22%0A%7C%20%20%20%22test%22'},
+{name:'bb7abafab60a0ea63f57420759fac4093148ecc8', input:'a%3Cv.d%20e%3Eb%3C/v%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20title%3D%22e%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'},
+{name:'b53365151e0b2434837d6cce15c3d51e666a813e', input:'a%3Clang.d%20e%3Eb%3C/lang%3Ec', expected:'%23document-fragment%0A%7C%20%22a%22%0A%7C%20%3Cspan%3E%0A%7C%20%20%20class%3D%22d%22%0A%7C%20%20%20lang%3D%22e%22%0A%7C%20%20%20%22b%22%0A%7C%20%22c%22'}
+]);
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/text.html b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/text.html
new file mode 100644
index 0000000000..f7241a5c15
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/text.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>WebVTT cue data parser test text</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'aa785adca3fcdfe1884ae840e13c6d294a2414e8', input:'text', expected:'%23document-fragment%0A%7C%20%22text%22'},
+{name:'3979f3c0c7664ee8a9f78854626bc7bc39b86c96', input:'text1%0Atext2', expected:'%23document-fragment%0A%7C%20%22text1%0Atext2%22'},
+{name:'6805ac5ddce21cfceb4eccf04a6a9013760f5d5b', input:'foo%00bar', expected:'%23document-fragment%0A%7C%20%22foo%EF%BF%BDbar%22'},
+{name:'5cfbdbe32701516fc90c3786da1db4716ac09fb8', input:'%E2%9C%93', expected:'%23document-fragment%0A%7C%20%22%E2%9C%93%22'},
+{name:'a34d27ca7b23f07db6ec2e32226fca105e958db6', input:'text1%0A%0Atext2', expected:'%23document-fragment%0A%7C%20%22text1%22'}
+]);
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/timestamps.html b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/timestamps.html
new file mode 100644
index 0000000000..1739d96367
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/timestamps.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>WebVTT cue data parser test timestamps</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'54c245f3fbe7a3e25398b13971d44f2bb3a5f947', input:'%3C0', expected:'%23document-fragment'},
+{name:'5e190a1b4541fcb10e403af111c14ef152fecb0d', input:'%3C0.500', expected:'%23document-fragment'},
+{name:'92b97d3497836259e0b9305e27f2b91ea1dc9b31', input:'%3C0%3A00.500', expected:'%23document-fragment'},
+{name:'2f0e84518d356cb1e56a366296fa491c5bed1e3a', input:'%3C00%3A%0000%3A00.500%3E', expected:'%23document-fragment'},
+{name:'47fa4306a695161da88533d456ce94829e53b13d', input:'%3C00%3A00.500', expected:'%23document-fragment%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E'},
+{name:'c1036a4322c1852e02e5a1843a9a81dfca6d7af3', input:'%3C00%3A00%3A00.500', expected:'%23document-fragment%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E'},
+{name:'70ec34d828ca661a583c651207becb968bb41653', input:'test%3C00%3A00%3A00.500%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2000%3A00%3A00.500%3E%0A%7C%20%22test%22'},
+{name:'66ba641ff047a226fa60fe867fd2479d40f3ff0f', input:'test%3C01%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2001%3A00%3A00.000%3E%0A%7C%20%22test%22'},
+{name:'398e8da1aaaf392739ca72057fef58bd5333f74d', input:'test%3C10%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%2010%3A00%3A00.000%3E%0A%7C%20%22test%22'},
+{name:'391fce67644cf4dd9967e1436d1449ef5baf675f', input:'test%3C100%3A00%3A00.000%3Etest', expected:'%23document-fragment%0A%7C%20%22test%22%0A%7C%20%3C%3Ftimestamp%20100%3A00%3A00.000%3E%0A%7C%20%22test%22'}
+]);
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tree-building.html b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tree-building.html
new file mode 100644
index 0000000000..6cd617dece
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/cue-text-parsing/tests/tree-building.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>WebVTT cue data parser test tree-building</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-text-parsing-rules">
+<style>video { display:none }</style>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/html/syntax/parsing/template.js></script>
+<script src=/html/syntax/parsing/common.js></script>
+<script src=../common.js></script>
+<div id=log></div>
+<script>
+runTests([
+{name:'4e1243bd22c66e76c2ba9eddc1f91394e57f9f83', input:'test', expected:'%23document-fragment%0A%7C%20%22test%22'},
+{name:'2564487cfc7e317428fb437ef8de8de4f4963426', input:'%3Cruby%3Etest%3Crt%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22'},
+{name:'9b1902c975558eeaff4afbaf0a6dc100e1978769', input:'%3Cruby%3Etest%3Crt%3Etest%3C/rt%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%20%20%22test%22'},
+{name:'119c596ea09649d3bd03934485e3067e89377412', input:'%3Cruby%3Etest%3Crt%3Etest%3C/rt%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%22test%22'},
+{name:'c94512b045699cb72f730e46b2a0a3bed2c939f9', input:'%3Cruby%3Etest%3Crt%3Etest%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%22test%22%0A%7C%20%22test%22'},
+{name:'325c1e590e74f1ff33ca5b4838c04cf6b6dd71ba', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%20%20%22test%22'},
+{name:'92847ed2694c9639ba96f4cc61e2215362a74904', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%20%20%22test%22'},
+{name:'c0da62d1c8716ca544c96799f06ac7e4664500fb', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/ruby%3E%3C/b%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%20%20%20%20%22test%22'},
+{name:'b85bd616672eba0591718182ef32e3307d223bb0', input:'%3Cruby%3Etest%3Crt%3E%3Cb%3Etest%3C/rt%3E%3C/b%3E%3C/ruby%3Etest', expected:'%23document-fragment%0A%7C%20%3Cruby%3E%0A%7C%20%20%20%22test%22%0A%7C%20%20%20%3Crt%3E%0A%7C%20%20%20%20%20%3Cb%3E%0A%7C%20%20%20%20%20%20%20%22test%22%0A%7C%20%22test%22'}
+]);
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/README.md b/testing/web-platform/tests/webvtt/parsing/file-parsing/README.md
new file mode 100644
index 0000000000..4cff0af952
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/README.md
@@ -0,0 +1,52 @@
+# Tests for http://w3c.github.io/webvtt/#file-parsing
+
+Tests that expect an 'error' event (due to invalid signature) are:
+
+```bash
+./signature-invalid.html
+./support/*.vtt
+```
+
+Other tests are generated from source files with a custom format. The source files are:
+
+```bash
+./support/*.test
+```
+
+## .test Format
+
+* The first line is the title of the test.
+* Subsequent lines until a blank line contain HTML metadata.
+* Subsequent lines until a `===` line contains JS assertions.
+* Finally the WebVTT file. Special characters can be escaped using python3 escape sequences: `\x00`, `\r`.
+
+## Building Tests
+
+Requirements: Python 3.2 or newer
+
+```bash
+$ python3 tools/build.py
+```
+
+## Spec Coverage Report
+
+There is also a python implementation of the WebVTT file parser algorithm and a
+script to create a test coverage report of this implementation, under `tools/`.
+
+Requirements:
+* Python 3.2 or newer
+* [Coverage.py](https://pypi.python.org/pypi/coverage)
+
+Installing Coverage.py using [pip](https://pypi.python.org/pypi/pip).
+
+```bash
+$ pip3 install coverage
+```
+
+Generating the report:
+
+```bash
+$ python3 spec_report.py
+```
+
+Will output `report.html`.
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/categories.json b/testing/web-platform/tests/webvtt/parsing/file-parsing/categories.json
new file mode 100644
index 0000000000..e78106cee1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/categories.json
@@ -0,0 +1,6 @@
+{
+ ":categories": [
+ ["file-parsing", "cue-text-parsing"]
+ ],
+ ":subcategories": ["tests/categories.json"]
+}
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/signature-invalid.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/signature-invalid.html
new file mode 100644
index 0000000000..62ee90828f
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/signature-invalid.html
@@ -0,0 +1,49 @@
+<!doctype html>
+<title>WebVTT parser test: invalid signatures</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+[
+ // Alphabetical order, by file
+ ['empty', 'empty.vtt'],
+ ['formfeed', 'signature-formfeed.vtt'],
+ ['invalid whitespace', 'signature-invalid-whitespace.vtt'],
+ ['invalid', 'signature-invalid.vtt'],
+ ['lowercase', 'signature-lowercase.vtt'],
+ ['missing whitespace', 'signature-missing-whitespace.vtt'],
+ ['missing', 'signature-missing.vtt'],
+ ['null', 'signature-null.vtt'],
+ ['partial', 'signature-partial.vtt'],
+ ['two boms', 'signature-two-boms.vtt'],
+ ['websrt', 'signature-websrt.vtt'],
+].forEach(function(test_data) {
+ var test_name = 'signature, ' + test_data[0];
+ var test_file = 'support/' + test_data[1];
+
+ var test = async_test(test_name);
+ test.step(function() {
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = test_file;
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+ });
+
+ function trackLoaded(event) {
+ assert_unreached('track should fail to load');
+ this.done();
+ }
+
+ function trackError(e) {
+ this.done();
+ }
+});
+done();
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/arrows.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/arrows.test
new file mode 100644
index 0000000000..72207a2417
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/arrows.test
@@ -0,0 +1,38 @@
+arrows
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-timings-and-settings-parsing">
+
+assert_equals(cues.length, 6);
+
+for (var i = 0; i < cues.length; i++) {
+ assert_equals(cues[i].id, '', 'Failed with cue ' + i);
+ assert_equals(cues[i].text, 'text' + i, 'Failed with cue ' + i);
+}
+
+===
+WEBVTT
+
+-->
+00:00:00.000 --> 00:00:01.000
+text0
+foo-->
+00:00:00.000 --> 00:00:01.000
+text1
+-->foo
+00:00:00.000 --> 00:00:01.000
+text2
+--->
+00:00:00.000 --> 00:00:01.000
+text3
+-->-->
+00:00:00.000 --> 00:00:01.000
+text4
+00:00:00.000 --> 00:00:01.000
+text5
+
+00:00:00.000 -a -->
+
+00:00:00.000 --a -->
+
+00:00:00.000 - -->
+
+00:00:00.000 -- -->
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/comment-in-cue-text.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/comment-in-cue-text.test
new file mode 100644
index 0000000000..38e4b9f16e
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/comment-in-cue-text.test
@@ -0,0 +1,28 @@
+comment-in-cue-text
+<link rel="help" href="https://www.w3.org/TR/webvtt1/#introduction-comments">
+
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'NOTE text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'NOTE text\nNOTE text2');
+assert_equals(cues[1].startTime, 1);
+assert_equals(cues[1].endTime, 2);
+
+===
+WEBVTT
+
+NOTE this is real comment that should be ignored
+
+00:00:00.000 --> 00:00:01.000
+NOTE text
+
+NOTE
+this is also a real comment that should be ignored
+this is also a real comment that should be ignored
+
+00:00:01.000 --> 00:00:02.000
+NOTE text
+NOTE text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/empty.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/empty.vtt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/empty.vtt
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-garbage.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-garbage.test
new file mode 100644
index 0000000000..a8714aae91
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-garbage.test
@@ -0,0 +1,15 @@
+header, garbage
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+===
+WEBVTT
+foobar
+
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-space.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-space.test
new file mode 100644
index 0000000000..3b2fa7dc90
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-space.test
@@ -0,0 +1,14 @@
+header, space
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+===
+WEBVTT
+\x20
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-tab.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-tab.test
new file mode 100644
index 0000000000..91892d614a
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-tab.test
@@ -0,0 +1,14 @@
+header, tab
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+===
+WEBVTT
+\t
+00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-timings.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-timings.test
new file mode 100644
index 0000000000..c3348e43f8
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/header-timings.test
@@ -0,0 +1,13 @@
+header, timings
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+===
+WEBVTT
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/ids.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/ids.test
new file mode 100644
index 0000000000..135f1c6abc
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/ids.test
@@ -0,0 +1,32 @@
+ids
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 5);
+assert_equals(cues[0].id, " leading space");
+assert_equals(cues[1].id, "trailing space ");
+assert_equals(cues[2].id, "-- >");
+assert_equals(cues[3].id, "->");
+assert_equals(cues[4].id, " ");
+
+===
+WEBVTT
+
+\x20leading space
+00:00:00.000 --> 00:00:01.000
+text0
+
+trailing space\x20
+00:00:00.000 --> 00:00:01.000
+text1
+
+-- >
+00:00:00.000 --> 00:00:01.000
+text2
+
+->
+00:00:00.000 --> 00:00:01.000
+text3
+
+\x20
+00:00:00.000 --> 00:00:01.000
+text4
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/newlines.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/newlines.test
new file mode 100644
index 0000000000..2d10536b68
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/newlines.test
@@ -0,0 +1,36 @@
+newlines
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 4);
+
+assert_equals(cues[0].id, "cr");
+assert_equals(cues[0].text, "text0");
+
+assert_equals(cues[1].id, "lf");
+assert_equals(cues[1].text, "text1");
+
+assert_equals(cues[2].id, "crlf");
+assert_equals(cues[2].text, "text2");
+
+assert_equals(cues[3].id, "lfcr");
+assert_equals(cues[3].text, "text3");
+
+===
+WEBVTT\r\
+\r\
+cr\r\
+00:00:00.000 --> 00:00:01.000\r\
+text0\n\
+\n\
+lf\n\
+00:00:00.000 --> 00:00:01.000\n\
+text1\r\n\
+\r\n\
+crlf\r\n\
+00:00:00.000 --> 00:00:01.000\r\n\
+text2\n\
+\r\
+lfcr\r\
+00:00:00.000 --> 00:00:01.000\n\
+text3\n\
+\r
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/nulls.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/nulls.test
new file mode 100644
index 0000000000..02450ce5c4
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/nulls.test
@@ -0,0 +1,232 @@
+nulls
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 7, cues);
+
+assert_equals(cues[0].id, "");
+assert_equals(cues[0].text, "text0");
+
+assert_equals(cues[1].id, "\uFFFD (null in id)");
+assert_equals(cues[1].text, "text1");
+
+assert_equals(cues[2].id, "\uFFFD (null in cue data)");
+assert_equals(cues[2].text, "\uFFFDtext\uFFFD2");
+
+assert_equals(cues[3].align, "center");
+assert_equals(cues[3].text, "text3");
+
+assert_equals(cues[4].align, "center");
+assert_equals(cues[4].text, "text4");
+
+assert_equals(cues[5].align, "center");
+assert_equals(cues[5].text, "text5");
+
+assert_equals(cues[6].align, "end");
+assert_equals(cues[6].text, "text6");
+
+===
+WEBVTT
+\x00
+(null in previous line should make this line also part of the header)
+00:00:00.000 --> 00:00:01.000
+text0
+
+\x00 (null in id)
+00:00:00.000 --> 00:00:01.000
+text1
+
+\uFFFD (null in cue data)
+00:00:00.000 --> 00:00:01.000
+\uFFFDtext\x002
+
+00:00:00.000 --> 00:00:01.000 align\x00:end
+text3
+
+00:00:00.000 --> 00:00:01.000 align:end\x00
+text4
+
+00:00:00.000 --> 00:00:01.000\x00align:end
+text5
+
+00:00:00.000 --> 00:00:01.000\x00 align:end
+text6
+
+00:00:00.000\x00 --> 00:00:01.000
+invalid
+
+00:00:00.000 -->\x0000:00:01.000
+invalid
+
+\x0000:00:00.000 --> 00:00:01.000
+invalid
+
+0\x000:00:00.000 --> 00:00:01.000
+invalid
+
+00\x00:00:00.000 --> 00:00:01.000
+invalid
+
+00:\x0000:00.000 --> 00:00:01.000
+invalid
+
+00:0\x000:00.000 --> 00:00:01.000
+invalid
+
+00:00\x00:00.000 --> 00:00:01.000
+invalid
+
+00:00:\x0000.000 --> 00:00:01.000
+invalid
+
+00:00:0\x000.000 --> 00:00:01.000
+invalid
+
+00:00:00\x00.000 --> 00:00:01.000
+invalid
+
+00:00:00.\x00000 --> 00:00:01.000
+invalid
+
+00:00:00.0\x0000 --> 00:00:01.000
+invalid
+
+00:00:00.00\x000 --> 00:00:01.000
+invalid
+
+00:00:00.000\x00 --> 00:00:01.000
+invalid
+
+00:00:00.000 \x00--> 00:00:01.000
+invalid
+
+00:00:00.000 -\x00-> 00:00:01.000
+invalid
+
+00:00:00.000 --\x00> 00:00:01.000
+invalid
+
+00:00:00.000 -->\x00 00:00:01.000
+invalid
+
+00:00:00.000 --> \x0000:00:01.000
+invalid
+
+00:00:00.000 --> 0\x000:00:01.000
+invalid
+
+00:00:00.000 --> 00\x00:00:01.000
+invalid
+
+00:00:00.000 --> 00:\x0000:01.000
+invalid
+
+00:00:00.000 --> 00:0\x000:01.000
+invalid
+
+00:00:00.000 --> 00:00\x00:01.000
+invalid
+
+00:00:00.000 --> 00:00:\x0001.000
+invalid
+
+00:00:00.000 --> 00:00:0\x001.000
+invalid
+
+00:00:00.000 --> 00:00:01\x00.000
+invalid
+
+00:00:00.000 --> 00:00:01.\x00000
+invalid
+
+00:00:00.000 --> 00:00:01.0\x0000
+invalid
+
+00:00:00.000 --> 00:00:01.00\x000
+invalid
+
+\x000:00:00.000 --> 00:00:01.000
+invalid
+
+0\x00:00:00.000 --> 00:00:01.000
+invalid
+
+00\x0000:00.000 --> 00:00:01.000
+invalid
+
+00:\x000:00.000 --> 00:00:01.000
+invalid
+
+00:0\x00:00.000 --> 00:00:01.000
+invalid
+
+00:00\x0000.000 --> 00:00:01.000
+invalid
+
+00:00:\x000.000 --> 00:00:01.000
+invalid
+
+00:00:0\x00.000 --> 00:00:01.000
+invalid
+
+00:00:00\x00000 --> 00:00:01.000
+invalid
+
+00:00:00.\x0000 --> 00:00:01.000
+invalid
+
+00:00:00.0\x000 --> 00:00:01.000
+invalid
+
+00:00:00.00\x00 --> 00:00:01.000
+invalid
+
+00:00:00.000\x00--> 00:00:01.000
+invalid
+
+00:00:00.000 \x00-> 00:00:01.000
+invalid
+
+00:00:00.000 -\x00> 00:00:01.000
+invalid
+
+00:00:00.000 --\x00 00:00:01.000
+invalid
+
+00:00:00.000 -->\x0000:00:01.000
+invalid
+
+00:00:00.000 --> \x000:00:01.000
+invalid
+
+00:00:00.000 --> 0\x00:00:01.000
+invalid
+
+00:00:00.000 --> 00\x0000:01.000
+invalid
+
+00:00:00.000 --> 00:\x000:01.000
+invalid
+
+00:00:00.000 --> 00:0\x00:01.000
+invalid
+
+00:00:00.000 --> 00:00\x0001.000
+invalid
+
+00:00:00.000 --> 00:00:\x001.000
+invalid
+
+00:00:00.000 --> 00:00:0\x00.000
+invalid
+
+00:00:00.000 --> 00:00:01\x00000
+invalid
+
+00:00:00.000 --> 00:00:01.\x0000
+invalid
+
+00:00:00.000 --> 00:00:01.0\x000
+invalid
+
+00:00:00.000 --> 00:00:01.00\x00
+invalid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-id.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-id.test
new file mode 100644
index 0000000000..b611f84371
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-id.test
@@ -0,0 +1,52 @@
+regions, id
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 4);
+
+var region1 = cues[0].region;
+assert_equals(region1.lines, 2);
+
+var region2 = cues[1].region;
+assert_equals(region2.lines, 1);
+
+var region3 = cues[2].region;
+assert_equals(region3.lines, 3);
+
+var region4 = cues[3].region;
+assert_equals(region4.lines, 4);
+
+===
+WEBVTT
+
+NOTE No API for accessing region ids, so using lines to uniquely identify regions
+
+REGION
+id:foo
+id:bar
+lines:1
+
+REGION
+id:bar id:foo
+lines:2
+
+REGION
+id:id
+id: foo
+id :bar
+lines:3
+
+REGION
+id:\v
+lines:4
+
+00:00:00.000 --> 00:00:01.000 region:foo
+valid
+
+00:00:00.000 --> 00:00:01.000 region:bar
+valid
+
+00:00:00.000 --> 00:00:01.000 region:id
+valid
+
+00:00:00.000 --> 00:00:01.000 region:\v
+valid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-lines.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-lines.test
new file mode 100644
index 0000000000..a492a5448c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-lines.test
@@ -0,0 +1,129 @@
+regions, lines
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 13);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_lines = [
+ 0,
+ 1,
+ 100,
+ 101,
+ 65536,
+ 4294967296,
+ 18446744073709552000,
+ 10000000000000000000000000000000000,
+ 2,
+];
+valid_lines.forEach(function(valid, index) {
+ assert_equals(regions[index].lines, valid, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_lines.length + i;
+
+ assert_equals(regions[index].lines, 3, 'Failed with region ' + index);
+}
+
+===
+WEBVTT
+
+NOTE valid
+
+REGION
+id:1
+lines:0
+
+REGION
+id:2
+lines:1
+
+REGION
+id:3
+lines:100
+
+REGION
+id:4
+lines:101
+
+REGION
+id:5
+lines:65536
+
+REGION
+id:6
+lines:4294967296
+
+REGION
+id:7
+lines:18446744073709552000
+
+REGION
+id:8
+lines:10000000000000000000000000000000000
+
+REGION
+id:9
+lines:1 lines:3
+lines:2
+
+NOTE invalid
+
+REGION
+id:10
+lines:-0
+
+REGION
+id:11
+lines:1.5
+
+REGION
+id:12
+lines:-1
+
+REGION
+id:13
+lines: 1
+lines :1
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-old.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-old.test
new file mode 100644
index 0000000000..4acb54b262
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-old.test
@@ -0,0 +1,18 @@
+regions, old
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].region, null);
+assert_equals(cues[1].region, null);
+
+===
+WEBVTT
+Region: id=foo width=40% lines=3 regionanchor=0%,100% viewportanchor=10%,90% scroll=up
+Region: id=bar width=40% lines=3 regionanchor=100%,100% viewportanchor=90%,90% scroll=up
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text0
+
+00:00:00.000 --> 00:00:01.000 region:bar
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-regionanchor.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-regionanchor.test
new file mode 100644
index 0000000000..0b0a896e20
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-regionanchor.test
@@ -0,0 +1,182 @@
+regions, regionanchor
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 20);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_anchors = [
+ [0, 100],
+ [0, 0],
+ [1, 1],
+ [100, 0],
+ [0, 100],
+ [100, 100],
+];
+valid_anchors.forEach(function(pair, index) {
+ var anchorX = pair[0];
+ var anchorY = pair[1];
+
+ assert_equals(regions[index].regionAnchorX, anchorX, 'Failed with region ' + index);
+ assert_equals(regions[index].regionAnchorY, anchorY, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_anchors.length + i;
+
+ assert_equals(regions[index].regionAnchorX, 0, 'Failed with region ' + index);
+ assert_equals(regions[index].regionAnchorY, 100, 'Failed with region ' + index);
+}
+
+===
+WEBVTT
+
+NOTE valid
+
+REGION
+id:0
+
+REGION
+id:1
+regionanchor:0%,0%
+
+REGION
+id:2
+regionanchor:1%,1%
+
+REGION
+id:3
+regionanchor:100%,0%
+
+REGION
+id:4
+regionanchor:0%,100%
+
+REGION
+id:5
+regionanchor:100%,100%
+
+NOTE invalid
+
+REGION
+id:6
+regionanchor:0,0
+
+REGION
+id:7
+regionanchor:0%,0
+
+REGION
+id:8
+regionanchor:0,0%
+
+REGION
+id:9
+regionanchor:1%
+
+REGION
+id:10
+regionanchor:,1%
+
+REGION
+id:11
+regionanchor:101%,1%
+
+REGION
+id:12
+regionanchor:1%,101%
+
+REGION
+id:13
+regionanchor:-0%,0%
+
+REGION
+id:14
+regionanchor:0%,-0%
+
+REGION
+id:15
+regionanchor:65536%,65536%
+
+REGION
+id:16
+regionanchor:4294967296%,4294967296%
+
+REGION
+id:17
+regionanchor:18446744073709552000%,18446744073709552000%
+
+REGION
+id:18
+regionanchor:10000000000000000000000000000000000%,10000000000000000000000000000000000%
+
+REGION
+id:19
+regionanchor: 100%,100%
+regionanchor :100%,100%
+regionanchor:100% ,100%
+regionanchor:100%, 100%
+regionanchor:100 %,100%
+regionanchor:100%,100 %
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
+
+00:00:00.000 --> 00:00:01.000 region:14
+text
+
+00:00:00.000 --> 00:00:01.000 region:15
+text
+
+00:00:00.000 --> 00:00:01.000 region:16
+text
+
+00:00:00.000 --> 00:00:01.000 region:17
+text
+
+00:00:00.000 --> 00:00:01.000 region:18
+text
+
+00:00:00.000 --> 00:00:01.000 region:19
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-scroll.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-scroll.test
new file mode 100644
index 0000000000..f4b27800dd
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-scroll.test
@@ -0,0 +1,67 @@
+regions, scroll
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 6);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_lines = [
+ '',
+ 'up',
+ 'up',
+ '',
+ '',
+ 'up',
+].forEach(function(valid, index) {
+ assert_equals(regions[index].scroll, valid, 'Failed with region ' + index);
+});
+
+===
+WEBVTT
+
+REGION
+id:0
+
+REGION
+id:1
+scroll:up
+
+REGION
+id:2
+scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up
+scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up
+
+REGION
+id:3
+scroll:down
+scroll:left
+scroll:right
+
+REGION
+id:4
+scroll: up
+scroll :up
+
+REGION
+id:5
+scroll:up scroll:
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-viewportanchor.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-viewportanchor.test
new file mode 100644
index 0000000000..c63816d0c4
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/regions-viewportanchor.test
@@ -0,0 +1,182 @@
+regions, viewportanchor
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+
+assert_equals(cues.length, 20);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_anchors = [
+ [0, 100],
+ [0, 0],
+ [1, 1],
+ [100, 0],
+ [0, 100],
+ [100, 100],
+];
+valid_anchors.forEach(function(pair, index) {
+ var anchorX = pair[0];
+ var anchorY = pair[1];
+
+ assert_equals(regions[index].viewportAnchorX, anchorX, 'Failed with region ' + index);
+ assert_equals(regions[index].viewportAnchorY, anchorY, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_anchors.length + i;
+
+ assert_equals(regions[index].viewportAnchorX, 0, 'Failed with region ' + index);
+ assert_equals(regions[index].viewportAnchorY, 100, 'Failed with region ' + index);
+}
+
+===
+WEBVTT
+
+NOTE valid
+
+REGION
+id:0
+
+REGION
+id:1
+viewportanchor:0%,0%
+
+REGION
+id:2
+viewportanchor:1%,1%
+
+REGION
+id:3
+viewportanchor:100%,0%
+
+REGION
+id:4
+viewportanchor:0%,100%
+
+REGION
+id:5
+viewportanchor:100%,100%
+
+NOTE invalid
+
+REGION
+id:6
+viewportanchor:0,0
+
+REGION
+id:7
+viewportanchor:0%,0
+
+REGION
+id:8
+viewportanchor:0,0%
+
+REGION
+id:9
+viewportanchor:1%
+
+REGION
+id:10
+viewportanchor:,1%
+
+REGION
+id:11
+viewportanchor:101%,1%
+
+REGION
+id:12
+viewportanchor:1%,101%
+
+REGION
+id:13
+viewportanchor:-0%,0%
+
+REGION
+id:14
+viewportanchor:0%,-0%
+
+REGION
+id:15
+viewportanchor:65536%,65536%
+
+REGION
+id:16
+viewportanchor:4294967296%,4294967296%
+
+REGION
+id:17
+viewportanchor:18446744073709552000%,18446744073709552000%
+
+REGION
+id:18
+viewportanchor:10000000000000000000000000000000000%,10000000000000000000000000000000000%
+
+REGION
+id:19
+viewportanchor: 100%,100%
+viewportanchor :100%,100%
+viewportanchor:100% ,100%
+viewportanchor:100%, 100%
+viewportanchor:100 %,100%
+viewportanchor:100%,100 %
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
+
+00:00:00.000 --> 00:00:01.000 region:14
+text
+
+00:00:00.000 --> 00:00:01.000 region:15
+text
+
+00:00:00.000 --> 00:00:01.000 region:16
+text
+
+00:00:00.000 --> 00:00:01.000 region:17
+text
+
+00:00:00.000 --> 00:00:01.000 region:18
+text
+
+00:00:00.000 --> 00:00:01.000 region:19
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-align.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-align.test
new file mode 100644
index 0000000000..ec5618a64b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-align.test
@@ -0,0 +1,64 @@
+settings, align
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 13);
+
+[
+ 'center',
+ 'start',
+ 'center',
+ 'end',
+ 'left',
+ 'right',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'center',
+].forEach(function(valid, index) {
+ assert_equals(cues[index].align, valid, 'Failed with cue ' + index);
+});
+
+===
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 align:start
+text1
+
+00:00:00.000 --> 00:00:01.000 align:center
+text2
+
+00:00:00.000 --> 00:00:01.000 align:end
+text3
+
+00:00:00.000 --> 00:00:01.000 align:left
+text4
+
+00:00:00.000 --> 00:00:01.000 align:right
+text5
+
+00:00:00.000 --> 00:00:01.000 align:start align:end
+text6
+
+00:00:00.000 --> 00:00:01.000 align:end align:CENTER
+text7
+
+00:00:00.000 --> 00:00:01.000 align:end align: center
+text8
+
+00:00:00.000 --> 00:00:01.000 align:end align:
+text9
+
+00:00:00.000 --> 00:00:01.000 align:end align:middle
+text10
+
+00:00:00.000 --> 00:00:01.000 align:end align
+text11
+
+00:00:00.000 --> 00:00:01.000 align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:center
+text12
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-line.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-line.test
new file mode 100644
index 0000000000..5b68d9c8ab
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-line.test
@@ -0,0 +1,223 @@
+settings, line
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 46);
+
+// Test starts with simple valid values
+var valid_values = [
+ -1,
+ 0,
+ 0,
+ 1,
+ 100,
+ 101,
+ 65536,
+ 4294967296,
+ 18446744073709552000,
+ 10000000000000000000000000000000000,
+ 1.5,
+ Number.MAX_VALUE,
+ -1 * Number.MAX_VALUE,
+ Number.MIN_VALUE,
+ 0, // Less than Number.MIN_VALUE
+];
+valid_values.forEach(function(valid, index) {
+ assert_equals(cues[index].line, valid, 'Failed with cue ' + index);
+ assert_true(cues[index].snapToLines, 'Failed with cue ' + index);
+});
+
+// Then a set of invalid ones
+var invalid_length = 23;
+for (var i = 0; i < invalid_length; i++) {
+ var index = valid_values.length + i;
+
+ assert_equals(cues[index].line, 'auto', 'Failed with cue ' + index);
+ assert_true(cues[index].snapToLines, 'Failed with cue ' + index);
+}
+
+// Then more specific tests
+var index = valid_values.length + invalid_length;
+
+assert_equals(cues[index].line, 0);
+assert_false(cues[index].snapToLines);
+
+assert_equals(cues[index + 1].line, 0);
+assert_false(cues[index + 1].snapToLines);
+
+assert_equals(cues[index + 2].line, 100);
+assert_false(cues[index + 2].snapToLines);
+assert_equals(cues[index + 2].lineAlign, 'start');
+
+assert_equals(cues[index + 3].line, 100);
+assert_false(cues[index + 3].snapToLines);
+assert_equals(cues[index + 3].lineAlign, 'start');
+
+assert_equals(cues[index + 4].line, 100);
+assert_false(cues[index + 4].snapToLines);
+assert_equals(cues[index + 4].lineAlign, 'center');
+
+assert_equals(cues[index + 5].line, 100);
+assert_false(cues[index + 5].snapToLines);
+assert_equals(cues[index + 5].lineAlign, 'end');
+
+assert_equals(cues[index + 6].line, Number.MIN_VALUE);
+assert_false(cues[index + 6].snapToLines);
+
+assert_equals(cues[index + 7].line, 0);
+assert_false(cues[index + 7].snapToLines);
+
+===
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000 line:-1
+valid0
+
+00:00:00.000 --> 00:00:01.000 line:0
+valid1
+
+00:00:00.000 --> 00:00:01.000 line:-0
+valid2
+
+00:00:00.000 --> 00:00:01.000 line:1
+valid3
+
+00:00:00.000 --> 00:00:01.000 line:100
+valid4
+
+00:00:00.000 --> 00:00:01.000 line:101
+valid5
+
+00:00:00.000 --> 00:00:01.000 line:65536
+valid6
+
+00:00:00.000 --> 00:00:01.000 line:4294967296
+valid7
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000
+valid8
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000
+valid9
+
+00:00:00.000 --> 00:00:01.000 line:1.5
+valid10
+
+Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+valid11
+
+-1 * Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:-179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+valid12
+
+Number.MIN_VALUE
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
+valid13
+
+Less than Number.MIN_VALUE
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
+valid14
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 line:65536%
+invalid15
+
+00:00:00.000 --> 00:00:01.000 line:4294967296%
+invalid16
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000%
+invalid17
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000%
+invalid18
+
+00:00:00.000 --> 00:00:01.000 line:-0%
+invalid19
+
+00:00:00.000 --> 00:00:01.000 line:101%
+invalid20
+
+00:00:00.000 --> 00:00:01.000 line:1%-
+invalid21
+
+00:00:00.000 --> 00:00:01.000 line:1-
+invalid22
+
+00:00:00.000 --> 00:00:01.000 line:%1
+invalid23
+
+00:00:00.000 --> 00:00:01.000 line:1%%
+invalid24
+
+00:00:00.000 --> 00:00:01.000 line:0%0
+invalid25
+
+00:00:00.000 --> 00:00:01.000 line: 0%
+invalid26
+
+00:00:00.000 --> 00:00:01.000 line:0%x
+invalid27
+
+00:00:00.000 --> 00:00:01.000 line:-
+invalid28
+
+00:00:00.000 --> 00:00:01.000 line:%
+invalid29
+
+00:00:00.000 --> 00:00:01.000 line:1..5
+invalid30
+
+00:00:00.000 --> 00:00:01.000 line:.5
+invalid31
+
+00:00:00.000 --> 00:00:01.000 line:5.
+invalid32
+
+Greater than Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:179769313486231590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+invalid33
+
+Less than -1 * Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:-179769313486231590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+invalid34
+
+exponential notation
+00:00:00.000 --> 00:00:01.000 line:1e2
+invalid35
+
+00:00:00.000 --> 00:00:01.000 line:100%,middle
+invalid36
+
+00:00:00.000 --> 00:00:01.000 line:100%,
+invalid37
+
+NOTE extra
+
+00:00:00.000 --> 00:00:01.000 line:0%
+text38
+
+00:00:00.000 --> 00:00:01.000 line:00%
+text39
+
+00:00:00.000 --> 00:00:01.000 line:100%
+text40
+
+00:00:00.000 --> 00:00:01.000 line:100%,start
+text41
+
+00:00:00.000 --> 00:00:01.000 line:100%,center
+text42
+
+00:00:00.000 --> 00:00:01.000 line:100%,end
+text43
+
+Number.MIN_VALUE %
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005%
+text44
+
+Less than Number.MIN_VALUE %
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002%
+text45
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-multiple.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-multiple.test
new file mode 100644
index 0000000000..2aa7dc1624
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-multiple.test
@@ -0,0 +1,34 @@
+settings, multiple
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 2);
+
+var cue = cues[0];
+assert_equals(cue.id, 'id0');
+assert_equals(cue.text, 'text0');
+assert_equals(cue.align, 'start');
+assert_equals(cue.line, 1);
+assert_equals(cue.snapToLines, false);
+assert_equals(cue.vertical, 'lr');
+assert_equals(cue.size, 50);
+assert_equals(cue.position, 25);
+
+var cue = cues[1];
+assert_equals(cue.id, 'id1');
+assert_equals(cue.text, 'text1');
+assert_equals(cue.align, 'center');
+assert_equals(cue.line, 1);
+assert_equals(cue.vertical, 'rl');
+assert_equals(cue.size, 0);
+assert_equals(cue.position, 100);
+
+===
+WEBVTT
+
+id0
+00:00:00.000 --> 00:00:01.000 align:start line:1% vertical:lr size:50% position:25%
+text0
+
+id1
+00:00:00.000 --> 00:00:01.000 align:center line:1 vertical:rl size:0% position:100%
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-position.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-position.test
new file mode 100644
index 0000000000..efed18caea
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-position.test
@@ -0,0 +1,102 @@
+settings, position
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 22);
+
+var valid_positions = [
+ [1, 'auto'],
+ [100, 'auto'],
+ [1, 'auto'],
+ [1.5, 'auto'],
+ [1, 'line-left'],
+ [1, 'center'],
+ [1, 'line-right'],
+ [1, 'auto'],
+];
+valid_positions.forEach(function(pair, index) {
+ var position = pair[0];
+ var positionAlign = pair[1];
+
+ assert_equals(cues[index].position, position, 'Failed with cue ' + index);
+ assert_equals(cues[index].positionAlign, positionAlign, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_positions.length + i;
+
+ assert_equals(cues[index].position, 'auto', 'Failed with cue ' + index);
+ assert_equals(cues[index].positionAlign, 'auto', 'Failed with cue ' + index);
+}
+
+===
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000 position:1%
+text0
+
+00:00:00.000 --> 00:00:01.000 position:100%
+text1
+
+00:00:00.000 --> 00:00:01.000 position:1% position:x
+text2
+
+00:00:00.000 --> 00:00:01.000 position:1.5%
+text3
+
+00:00:00.000 --> 00:00:01.000 position:1%,line-left
+text4
+
+00:00:00.000 --> 00:00:01.000 position:1%,center
+text5
+
+00:00:00.000 --> 00:00:01.000 position:1%,line-right
+text6
+
+00:00:00.000 --> 00:00:01.000 position:1% ,center
+text7
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 position:1%,middle
+invalid8
+
+00:00:00.000 --> 00:00:01.000 position:1%, center
+invalid9
+
+00:00:00.000 --> 00:00:01.000 position:-1%
+invalid10
+
+00:00:00.000 --> 00:00:01.000 position:1
+invalid11
+
+00:00:00.000 --> 00:00:01.000 position:1x
+invalid12
+
+00:00:00.000 --> 00:00:01.000 position:1%x
+invalid13
+
+00:00:00.000 --> 00:00:01.000 position:
+invalid14
+
+00:00:00.000 --> 00:00:01.000 position: 1%
+invalid15
+
+00:00:00.000 --> 00:00:01.000 position:101%
+invalid16
+
+00:00:00.000 --> 00:00:01.000 position:65536%
+invalid17
+
+00:00:00.000 --> 00:00:01.000 position:4294967296%
+invalid18
+
+00:00:00.000 --> 00:00:01.000 position:101%,line-left
+invalid19
+
+00:00:00.000 --> 00:00:01.000 position:101%,center
+invalid20
+
+00:00:00.000 --> 00:00:01.000 position:101%,line-right
+invalid21
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-region.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-region.test
new file mode 100644
index 0000000000..bfd0434e76
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-region.test
@@ -0,0 +1,71 @@
+settings, region
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 9);
+
+var fooRegion = cues[0].region;
+assert_true(!!fooRegion, 'Cue 0 has invalid region');
+
+var barRegion = cues[1].region;
+assert_true(!!barRegion, 'Cue 1 has invalid region');
+
+assert_not_equals(fooRegion, barRegion);
+
+var valid_regions = [
+ fooRegion,
+ barRegion,
+ barRegion,
+ null,
+ fooRegion
+];
+valid_regions.forEach(function(valid, index) {
+ assert_equals(cues[index].region, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_regions.length + i;
+
+ assert_equals(cues[index].region, null);
+}
+
+===
+WEBVTT
+
+REGION
+id:foo
+
+REGION
+id:bar
+
+REGION
+id:foo
+
+REGION
+width:10%
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text0
+
+00:00:00.000 --> 00:00:01.000 region:bar
+text1
+
+00:00:00.000 --> 00:00:01.000 region:foo region:bar
+text2
+
+00:00:00.000 --> 00:00:01.000 region:invalid
+text3
+
+00:00:00.000 --> 00:00:01.000 region:invalid region:foo
+text4
+
+00:00:00.000 --> 00:00:01.000 region:
+invalid5
+
+00:00:00.000 --> 00:00:01.000 region:\x20
+invalid6
+
+00:00:00.000 --> 00:00:01.000 region: foo
+invalid7
+
+00:00:00.000 --> 00:00:01.000 region :foo
+invalid8
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-size.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-size.test
new file mode 100644
index 0000000000..4c2de1d5f2
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-size.test
@@ -0,0 +1,78 @@
+settings, size
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 16);
+
+var valid_sizes = [
+ 100,
+ 2,
+ 0,
+ 0,
+ 100,
+ 50,
+ 1.5,
+];
+valid_sizes.forEach(function(valid, index) {
+ assert_equals(cues[index].size, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 9; i++) {
+ var index = valid_sizes.length + i;
+
+ assert_equals(cues[index].size, 100, 'Failed with cue ' + index);
+}
+
+===
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 size:1xx size:2%
+text1
+
+00:00:00.000 --> 00:00:01.000 size:0%
+text2
+
+00:00:00.000 --> 00:00:01.000 size:00%
+text3
+
+00:00:00.000 --> 00:00:01.000 size:50% size:100%
+text4
+
+00:00:00.000 --> 00:00:01.000 size:50% size:101%
+text5
+
+00:00:00.000 --> 00:00:01.000 size:1.5%
+text6
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 size:
+invalid7
+
+00:00:00.000 --> 00:00:01.000 size:x
+invalid8
+
+00:00:00.000 --> 00:00:01.000 size:%
+invalid9
+
+00:00:00.000 --> 00:00:01.000 size:%%
+invalid10
+
+00:00:00.000 --> 00:00:01.000 size:1%%
+invalid11
+
+00:00:00.000 --> 00:00:01.000 size:1%x
+invalid12
+
+00:00:00.000 --> 00:00:01.000 size:101%
+invalid13
+
+00:00:00.000 --> 00:00:01.000 size:-3%
+invalid14
+
+00:00:00.000 --> 00:00:01.000 size:200%
+invalid15
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-vertical.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-vertical.test
new file mode 100644
index 0000000000..33d23b2c46
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/settings-vertical.test
@@ -0,0 +1,47 @@
+settings, size
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 8);
+
+var valid_vertical = [
+ '',
+ 'lr',
+ 'rl',
+ 'lr',
+];
+valid_vertical.forEach(function(valid, index) {
+ assert_equals(cues[index].vertical, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_vertical.length + i;
+
+ assert_equals(cues[index].vertical, '', 'Failed with cue ' + index);
+}
+
+===
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 vertical:lr
+text1
+
+00:00:00.000 --> 00:00:01.000 vertical:rl
+text2
+
+00:00:00.000 --> 00:00:01.000 vertical:rl vertical:lr
+text3
+
+00:00:00.000 --> 00:00:01.000 vertical:
+invalid4
+
+00:00:00.000 --> 00:00:01.000 vertical:RL
+invalid5
+
+00:00:00.000 --> 00:00:01.000 vertical: rl
+invalid6
+
+00:00:00.000 --> 00:00:01.000 vertical:vertical-rl
+invalid7
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-bom.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-bom.test
new file mode 100644
index 0000000000..245385f572
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-bom.test
@@ -0,0 +1,7 @@
+signature, bom
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+\ufeffWEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-formfeed.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-formfeed.vtt
new file mode 100644
index 0000000000..0ba5286373
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-formfeed.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid-whitespace.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid-whitespace.vtt
new file mode 100644
index 0000000000..1f67eaee97
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid-whitespace.vtt
@@ -0,0 +1 @@
+WEBVTT foo
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid.vtt
new file mode 100644
index 0000000000..5407fcb350
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-invalid.vtt
@@ -0,0 +1 @@
+VTTWEB
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-lowercase.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-lowercase.vtt
new file mode 100644
index 0000000000..994d1694fd
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-lowercase.vtt
@@ -0,0 +1 @@
+webvtt
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing-whitespace.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing-whitespace.vtt
new file mode 100644
index 0000000000..7ed44af02c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing-whitespace.vtt
@@ -0,0 +1 @@
+WEBVTTfoo
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing.vtt
new file mode 100644
index 0000000000..bd90460a23
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-missing.vtt
@@ -0,0 +1,2 @@
+00:00:00.000 --> 00:00:01.000
+invalid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-no-newline.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-no-newline.test
new file mode 100644
index 0000000000..13cf042c17
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-no-newline.test
@@ -0,0 +1,7 @@
+signature, no newline
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-null.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-null.vtt
new file mode 100644
index 0000000000..ead93cc166
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-null.vtt
Binary files differ
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-partial.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-partial.vtt
new file mode 100644
index 0000000000..3e5de2b6c9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-partial.vtt
@@ -0,0 +1 @@
+WEBVT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space-no-newline.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space-no-newline.test
new file mode 100644
index 0000000000..021107316f
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space-no-newline.test
@@ -0,0 +1,7 @@
+signature, space, no newline
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT\x20 \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space.test
new file mode 100644
index 0000000000..349562eb9e
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-space.test
@@ -0,0 +1,7 @@
+signature, space
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT\x20
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab-no-newline.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab-no-newline.test
new file mode 100644
index 0000000000..fbca4bed60
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab-no-newline.test
@@ -0,0 +1,7 @@
+signature, tab, no newline
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT\t \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab.test
new file mode 100644
index 0000000000..3b500d0463
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-tab.test
@@ -0,0 +1,7 @@
+signature, tab
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT\t
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-timings.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-timings.test
new file mode 100644
index 0000000000..0197e8ac42
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-timings.test
@@ -0,0 +1,8 @@
+signature, timings
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT 00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-two-boms.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-two-boms.vtt
new file mode 100644
index 0000000000..05c973be18
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-two-boms.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-websrt.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-websrt.vtt
new file mode 100644
index 0000000000..4a02525e38
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/signature-websrt.vtt
@@ -0,0 +1 @@
+WEBSRT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/stylesheets.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/stylesheets.test
new file mode 100644
index 0000000000..f4fbf424fc
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/stylesheets.test
@@ -0,0 +1,36 @@
+stylesheets, rules
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+// There's no way to test the actual style from js
+assert_equals(document.styleSheets.length, 0);
+
+===
+WEBVTT
+
+STYLE
+::cue(#foo) {
+ width: 20px;
+} /*
+NOTE hello
+00:00:00.000 -- > 00:00:01.000
+*/
+.foo {
+ width: 19px;
+}
+
+.bar {
+ width: 18px;
+}
+
+foo
+00:00:00.000 --> 00:00:01.000
+text
+
+STYLE
+::cue(::bar) {
+ width: 18px;
+}
+
+bar
+00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-60.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-60.test
new file mode 100644
index 0000000000..7cfe482392
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-60.test
@@ -0,0 +1,33 @@
+timings, 60
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text1');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 216001);
+
+assert_equals(cues[1].text, 'text2');
+assert_equals(cues[1].startTime, 216000);
+assert_equals(cues[1].endTime, 216001);
+
+===
+WEBVTT
+
+00:00:60.000 --> 00:00:01.000
+invalid
+
+00:60:00.000 --> 00:00:01.000
+invalid
+
+00:00:00.000 --> 00:00:60.000
+invalid
+
+00:00:00.000 --> 00:60:00.000
+invalid
+
+00:00:00.000 --> 60:00:01.000
+text1
+
+60:00:00.000 --> 60:00:01.000
+text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-eof.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-eof.test
new file mode 100644
index 0000000000..7b871164e9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-eof.test
@@ -0,0 +1,9 @@
+timings, eof
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT
+
+00:00:00.000 --> \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-garbage.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-garbage.test
new file mode 100644
index 0000000000..99f7c28b42
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-garbage.test
@@ -0,0 +1,197 @@
+timings, garbage
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+
+assert_equals(cues.length, 0);
+
+===
+WEBVTT
+
+x00:00:00.000 --> 00:00:01.000
+invalid
+
+0x0:00:00.000 --> 00:00:01.000
+invalid
+
+00x:00:00.000 --> 00:00:01.000
+invalid
+
+00:x00:00.000 --> 00:00:01.000
+invalid
+
+00:0x0:00.000 --> 00:00:01.000
+invalid
+
+00:00x:00.000 --> 00:00:01.000
+invalid
+
+00:00:x00.000 --> 00:00:01.000
+invalid
+
+00:00:0x0.000 --> 00:00:01.000
+invalid
+
+00:00:00x.000 --> 00:00:01.000
+invalid
+
+00:00:00.x000 --> 00:00:01.000
+invalid
+
+00:00:00.0x00 --> 00:00:01.000
+invalid
+
+00:00:00.00x0 --> 00:00:01.000
+invalid
+
+00:00:00.000x --> 00:00:01.000
+invalid
+
+00:00:00.000 x--> 00:00:01.000
+invalid
+
+00:00:00.000 -x-> 00:00:01.000
+invalid
+
+00:00:00.000 --x> 00:00:01.000
+invalid
+
+00:00:00.000 -->x 00:00:01.000
+invalid
+
+00:00:00.000 --> x00:00:01.000
+invalid
+
+00:00:00.000 --> 0x0:00:01.000
+invalid
+
+00:00:00.000 --> 00x:00:01.000
+invalid
+
+00:00:00.000 --> 00:x00:01.000
+invalid
+
+00:00:00.000 --> 00:0x0:01.000
+invalid
+
+00:00:00.000 --> 00:00x:01.000
+invalid
+
+00:00:00.000 --> 00:00:x01.000
+invalid
+
+00:00:00.000 --> 00:00:0x1.000
+invalid
+
+00:00:00.000 --> 00:00:01x.000
+invalid
+
+00:00:00.000 --> 00:00:01.x000
+invalid
+
+00:00:00.000 --> 00:00:01.0x00
+invalid
+
+00:00:00.000 --> 00:00:01.00x0
+invalid
+
+x0:00:00.000 --> 00:00:01.000
+invalid
+
+0x:00:00.000 --> 00:00:01.000
+invalid
+
+00x00:00.000 --> 00:00:01.000
+invalid
+
+00:x0:00.000 --> 00:00:01.000
+invalid
+
+00:0x:00.000 --> 00:00:01.000
+invalid
+
+00:00x00.000 --> 00:00:01.000
+invalid
+
+00:00:x0.000 --> 00:00:01.000
+invalid
+
+00:00:0x.000 --> 00:00:01.000
+invalid
+
+00:00:00x000 --> 00:00:01.000
+invalid
+
+00:00:00.x00 --> 00:00:01.000
+invalid
+
+00:00:00.0x0 --> 00:00:01.000
+invalid
+
+00:00:00.00x --> 00:00:01.000
+invalid
+
+00:00:00.000x--> 00:00:01.000
+invalid
+
+00:00:00.000 x-> 00:00:01.000
+invalid
+
+00:00:00.000 -x> 00:00:01.000
+invalid
+
+00:00:00.000 --x 00:00:01.000
+invalid
+
+00:00:00.000 -->x00:00:01.000
+invalid
+
+00:00:00.000 --> x0:00:01.000
+invalid
+
+00:00:00.000 --> 0x:00:01.000
+invalid
+
+00:00:00.000 --> 00x00:01.000
+invalid
+
+00:00:00.000 --> 00:x0:01.000
+invalid
+
+00:00:00.000 --> 00:0x:01.000
+invalid
+
+00:00:00.000 --> 00:00x01.000
+invalid
+
+00:00:00.000 --> 00:00:x1.000
+invalid
+
+00:00:00.000 --> 00:00:0x.000
+invalid
+
+00:00:00.000 --> 00:00:01x000
+invalid
+
+00:00:00.000 --> 00:00:01.x00
+invalid
+
+00:00:00.000 --> 00:00:01.0x0
+invalid
+
+00:00:00.000 --> 00:00:01.00x
+invalid
+
+00.00:00.000 --> 00:00:01.000
+invalid
+
+00:00.00.000 --> 00:00:01.000
+invalid
+
+00:00:00:000 --> 00:00:01.000
+invalid
+
+00:00.00:000 --> 00:00:01.000
+invalid
+
+00:00:00,000 --> 00:00:01,000
+invalid \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-negative.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-negative.test
new file mode 100644
index 0000000000..2cded00929
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-negative.test
@@ -0,0 +1,33 @@
+timings, negative
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 4);
+
+[
+ [0, 0],
+ [1, 0.999],
+ [60, 59.999],
+ [3600, 3599.999],
+].forEach(function(pair, index) {
+ var startTime = pair[0];
+ var endTime = pair[1];
+
+ assert_equals(cues[index].text, 'text' + index, 'Failed with cue ' + index);
+ assert_equals(cues[index].startTime, startTime, 'Failed with cue ' + index);
+ assert_equals(cues[index].endTime, endTime, 'Failed with cue ' + index);
+});
+
+===
+WEBVTT
+
+00:00:00.000 --> 00:00:00.000
+text0
+
+00:00:01.000 --> 00:00:00.999
+text1
+
+00:01:00.000 --> 00:00:59.999
+text2
+
+01:00:00.000 --> 00:59:59.999
+text3
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-omitted-hours.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-omitted-hours.test
new file mode 100644
index 0000000000..8fb5858571
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-omitted-hours.test
@@ -0,0 +1,22 @@
+timings, omitted hours
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 3);
+
+Array.from(cues).forEach(function(cue, index) {
+ assert_equals(cue.text, 'text' + index, 'Failed with cue ' + index);
+ assert_equals(cue.startTime, 0, 'Failed with cue ' + index);
+ assert_equals(cue.endTime, 1, 'Failed with cue ' + index);
+});
+
+===
+WEBVTT
+
+00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:01.000
+text1
+
+00:00.000 --> 00:01.000
+text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-long.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-long.test
new file mode 100644
index 0000000000..5f2cc889a6
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-long.test
@@ -0,0 +1,60 @@
+timings, too long
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text0');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'text1');
+assert_equals(cues[1].startTime, 0);
+assert_equals(cues[1].endTime, 1);
+
+===
+WEBVTT
+
+000:00:00.000 --> 00:00:01.000
+text0
+
+00::00:00.000 --> 00:00:01.000
+invalid
+
+00:000:00.000 --> 00:00:01.000
+invalid
+
+00:00::00.000 --> 00:00:01.000
+invalid
+
+00:00:000.000 --> 00:00:01.000
+invalid
+
+00:00:00..000 --> 00:00:01.000
+invalid
+
+00:00:00.0000 --> 00:00:01.000
+invalid
+
+00:00.0000 --> 00:00:01.000
+invalid
+
+000:00.000 --> 00:01.000
+invalid
+
+00::00.000 --> 00:01.000
+invalid
+
+00:000.000 --> 00:01.000
+invalid
+
+00:00..000 --> 00:01.000
+invalid
+
+00:00.0000 --> 00:01.000
+invalid
+
+00:00.000 --> 000:01.000
+invalid
+
+00:00:00.000 --> 000:00:01.000
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-short.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-short.test
new file mode 100644
index 0000000000..d078eacf7c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/timings-too-short.test
@@ -0,0 +1,111 @@
+timings, too short
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text0');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'text1');
+assert_equals(cues[1].startTime, 0);
+assert_equals(cues[1].endTime, 1);
+
+===
+WEBVTT
+
+0:00:00.000 --> 00:00:01.000
+text0
+
+0000:00.000 --> 00:00:01.000
+invalid
+
+00:0:00.000 --> 00:00:01.000
+invalid
+
+00:0000.000 --> 00:00:01.000
+invalid
+
+00:00:0.000 --> 00:00:01.000
+invalid
+
+00:00:00000 --> 00:00:01.000
+invalid
+
+00:00:00.00 --> 00:00:01.000
+invalid
+
+00:00:00.0 --> 00:00:01.000
+invalid
+
+00:00:00. --> 00:00:01.000
+invalid
+
+00:00:00 --> 00:00:01.000
+invalid
+
+00:00:0 --> 00:00:01.000
+invalid
+
+00:00: --> 00:00:01.000
+invalid
+
+00:00 --> 00:00:01.000
+invalid
+
+00:0 --> 00:00:01.000
+invalid
+
+00: --> 00:00:01.000
+invalid
+
+00 --> 00:00:01.000
+invalid
+
+0 --> 00:00:01.000
+invalid
+
+ --> 00:00:01.000
+invalid
+
+0:00.000 --> 00:01.000
+invalid
+
+0000.000 --> 00:01.000
+invalid
+
+00:0.000 --> 00:01.000
+invalid
+
+00:00000 --> 00:01.000
+invalid
+
+00:00.00 --> 00:01.000
+invalid
+
+00:00.0 --> 00:01.000
+invalid
+
+00:00. --> 00:01.000
+invalid
+
+0:00. --> 00:01.000
+invalid
+
+:00. --> 00:01.000
+invalid
+
+00. --> 00:01.000
+invalid
+
+0. --> 00:01.000
+invalid
+
+. --> 00:01.000
+invalid
+
+00:00.000 --> 0:01.000
+invalid
+
+00:00:00.000 --> 0:00:01.000
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/support/whitespace-chars.test b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/whitespace-chars.test
new file mode 100644
index 0000000000..7ee43facaa
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/support/whitespace-chars.test
@@ -0,0 +1,32 @@
+whitespace chars
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+
+assert_equals(cues.length, 3);
+
+assert_equals(cues[0].id, 'spaces');
+assert_equals(cues[0].text, ' text0');
+
+assert_equals(cues[1].id, 'tabs');
+assert_equals(cues[1].text, 'text1');
+
+assert_equals(cues[2].id, 'form feed');
+assert_equals(cues[2].text, 'text2');
+
+===
+WEBVTT
+
+spaces
+ 00:00:00.000 --> 00:00:01.000\x20
+ text0
+
+tabs
+\t\t\t00:00:00.000\t\t\t\t-->\t\t00:00:01.000\t
+text1
+
+form feed
+\f\f\f00:00:00.000\f\f\f\f-->\f\f00:00:01.000\f
+text2
+
+vertical tab
+\v\v\v00:00:00.000\v\v\v\v-->\v\v00:00:01.000\v
+invalid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/arrows.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/arrows.html
new file mode 100644
index 0000000000..7eefc797c7
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/arrows.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/arrows.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: arrows</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#cue-timings-and-settings-parsing">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('arrows');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/arrows.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 6);
+
+for (var i = 0; i < cues.length; i++) {
+ assert_equals(cues[i].id, '', 'Failed with cue ' + i);
+ assert_equals(cues[i].text, 'text' + i, 'Failed with cue ' + i);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/categories.json b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/categories.json
new file mode 100644
index 0000000000..eac23f67dd
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/categories.json
@@ -0,0 +1,9 @@
+{
+ "arrows.html": "cues",
+ "ids.html": "cues",
+ "settings-*.html": "cues",
+ "signature-timings.html": "cues",
+ "timings-*.html": "cues",
+ "regions-*.html": "regions",
+ "stylesheets-*.html": "stylesheets"
+}
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/comment-in-cue-text.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/comment-in-cue-text.html
new file mode 100644
index 0000000000..d3cd12549b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/comment-in-cue-text.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/comment-in-cue-text.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: comment-in-cue-text</title>
+<link rel="help" href="https://www.w3.org/TR/webvtt1/#webvtt-comment-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('comment-in-cue-text');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/comment-in-cue-text.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'NOTE text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'NOTE text\nNOTE text2');
+assert_equals(cues[1].startTime, 1);
+assert_equals(cues[1].endTime, 2);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-garbage.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-garbage.html
new file mode 100644
index 0000000000..4ebace2409
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-garbage.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/header-garbage.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: header, garbage</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('header, garbage');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/header-garbage.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-regions.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-regions.html
new file mode 100644
index 0000000000..f935cb6a2a
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-regions.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<title>Tests proper parsing of various regions present in WebVTT header area.</title>
+<script src="/common/media.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+const regionDefaults = {
+ width: 100,
+ lines: 3,
+ regionAnchorX: 0,
+ regionAnchorY: 100,
+ viewportAnchorX: 0,
+ viewportAnchorY: 100,
+ scroll: ''
+};
+
+function checkProperties(region, expected, i) {
+ for (var prop in regionDefaults) {
+ if (!(prop in expected))
+ expected[prop] = regionDefaults[prop];
+ assert_equals(region[prop], expected[prop], prop + ' (cue ' + ( i + 1 ) + ')');
+ }
+}
+
+function checkCueRegions(cues) {
+ for (let i = 0; i < cues.length; ++i) {
+ let cue = cues[i];
+ let expected = JSON.parse(cue.text);
+ if (cue.region)
+ checkProperties(cue.region, expected, i);
+ else
+ assert_equals(expected, 'no region');
+ }
+}
+
+async_test(function(t) {
+ var video = document.createElement('video');
+ video.src = getVideoURI('/media/test');
+ var testTrack = document.createElement('track');
+ testTrack.onload = t.step_func_done(function() {
+ var track = testTrack.track;
+ assert_equals(track.cues.length, 10);
+ checkCueRegions(track.cues);
+ });
+ testTrack.src = 'support/header-regions.vtt';
+ testTrack.kind = 'captions';
+ testTrack.default = true;
+ video.appendChild(testTrack);
+});
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-space.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-space.html
new file mode 100644
index 0000000000..c679d69f51
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-space.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/header-space.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: header, space</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('header, space');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/header-space.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-tab.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-tab.html
new file mode 100644
index 0000000000..540bad54b6
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-tab.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/header-tab.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: header, tab</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('header, tab');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/header-tab.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-timings.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-timings.html
new file mode 100644
index 0000000000..adff8579a7
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/header-timings.html
@@ -0,0 +1,43 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/header-timings.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: header, timings</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('header, timings');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/header-timings.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 1);
+
+assert_equals(cues[0].text, 'text');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/ids.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/ids.html
new file mode 100644
index 0000000000..73763836bc
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/ids.html
@@ -0,0 +1,44 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/ids.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: ids</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('ids');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/ids.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 5);
+assert_equals(cues[0].id, " leading space");
+assert_equals(cues[1].id, "trailing space ");
+assert_equals(cues[2].id, "-- >");
+assert_equals(cues[3].id, "->");
+assert_equals(cues[4].id, " ");
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/newlines.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/newlines.html
new file mode 100644
index 0000000000..6afab36067
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/newlines.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/newlines.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: newlines</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('newlines');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/newlines.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 4);
+
+assert_equals(cues[0].id, "cr");
+assert_equals(cues[0].text, "text0");
+
+assert_equals(cues[1].id, "lf");
+assert_equals(cues[1].text, "text1");
+
+assert_equals(cues[2].id, "crlf");
+assert_equals(cues[2].text, "text2");
+
+assert_equals(cues[3].id, "lfcr");
+assert_equals(cues[3].text, "text3");
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/nulls.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/nulls.html
new file mode 100644
index 0000000000..d3a97eae8d
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/nulls.html
@@ -0,0 +1,60 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/nulls.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: nulls</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('nulls');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/nulls.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 7, cues);
+
+assert_equals(cues[0].id, "");
+assert_equals(cues[0].text, "text0");
+
+assert_equals(cues[1].id, "\uFFFD (null in id)");
+assert_equals(cues[1].text, "text1");
+
+assert_equals(cues[2].id, "\uFFFD (null in cue data)");
+assert_equals(cues[2].text, "\uFFFDtext\uFFFD2");
+
+assert_equals(cues[3].align, "center");
+assert_equals(cues[3].text, "text3");
+
+assert_equals(cues[4].align, "center");
+assert_equals(cues[4].text, "text4");
+
+assert_equals(cues[5].align, "center");
+assert_equals(cues[5].text, "text5");
+
+assert_equals(cues[6].align, "end");
+assert_equals(cues[6].text, "text6");
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html
new file mode 100644
index 0000000000..db1f27f67f
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-edge-case.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-edge-case.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: multiple regions edge cases</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, lines');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-edge-case.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 4);
+
+var region1 = cues[0].region;
+assert_equals(region1.lines, 1);
+assert_equals(region1.id, "foo");
+
+var region2 = cues[1].region;
+assert_equals(region2.lines, 2);
+assert_equals(region2.id, "bill");
+
+var region3 = cues[2].region;
+assert_equals(region3.lines, 3);
+assert_equals(region3.id, "jill");
+
+var region4 = cues[3].region;
+assert_equals(region4.lines, 4);
+assert_equals(region4.id, "jack");
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-id.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-id.html
new file mode 100644
index 0000000000..3a6e3feafa
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-id.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-id.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, id</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, id');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-id.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 4);
+
+var region1 = cues[0].region;
+assert_equals(region1.lines, 2);
+
+var region2 = cues[1].region;
+assert_equals(region2.lines, 1);
+
+var region3 = cues[2].region;
+assert_equals(region3.lines, 3);
+
+var region4 = cues[3].region;
+assert_equals(region4.lines, 4);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-lines.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-lines.html
new file mode 100644
index 0000000000..8e9b979291
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-lines.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-lines.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, lines</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, lines');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-lines.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 13);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_lines = [
+ 0,
+ 1,
+ 100,
+ 101,
+ 65536,
+ 4294967296,
+ 18446744073709552000,
+ 10000000000000000000000000000000000,
+ 2,
+];
+valid_lines.forEach(function(valid, index) {
+ assert_equals(regions[index].lines, valid, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_lines.length + i;
+
+ assert_equals(regions[index].lines, 3, 'Failed with region ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-old.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-old.html
new file mode 100644
index 0000000000..ea6875756e
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-old.html
@@ -0,0 +1,42 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-old.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, old</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, old');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-old.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].region, null);
+assert_equals(cues[1].region, null);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-regionanchor.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-regionanchor.html
new file mode 100644
index 0000000000..1cccfe9a04
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-regionanchor.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-regionanchor.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, regionanchor</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, regionanchor');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-regionanchor.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 20);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_anchors = [
+ [0, 100],
+ [0, 0],
+ [1, 1],
+ [100, 0],
+ [0, 100],
+ [100, 100],
+];
+valid_anchors.forEach(function(pair, index) {
+ var anchorX = pair[0];
+ var anchorY = pair[1];
+
+ assert_equals(regions[index].regionAnchorX, anchorX, 'Failed with region ' + index);
+ assert_equals(regions[index].regionAnchorY, anchorY, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_anchors.length + i;
+
+ assert_equals(regions[index].regionAnchorX, 0, 'Failed with region ' + index);
+ assert_equals(regions[index].regionAnchorY, 100, 'Failed with region ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-scroll.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-scroll.html
new file mode 100644
index 0000000000..698af98f7a
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-scroll.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-scroll.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, scroll</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, scroll');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-scroll.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 6);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_lines = [
+ '',
+ 'up',
+ 'up',
+ '',
+ '',
+ 'up',
+].forEach(function(valid, index) {
+ assert_equals(regions[index].scroll, valid, 'Failed with region ' + index);
+});
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-viewportanchor.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-viewportanchor.html
new file mode 100644
index 0000000000..b4c905fa4e
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/regions-viewportanchor.html
@@ -0,0 +1,66 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/regions-viewportanchor.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: regions, viewportanchor</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-region-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('regions, viewportanchor');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/regions-viewportanchor.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 20);
+
+var regions = Array.from(cues).map(function(cue) {
+ return cue.region;
+});
+
+var valid_anchors = [
+ [0, 100],
+ [0, 0],
+ [1, 1],
+ [100, 0],
+ [0, 100],
+ [100, 100],
+];
+valid_anchors.forEach(function(pair, index) {
+ var anchorX = pair[0];
+ var anchorY = pair[1];
+
+ assert_equals(regions[index].viewportAnchorX, anchorX, 'Failed with region ' + index);
+ assert_equals(regions[index].viewportAnchorY, anchorY, 'Failed with region ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_anchors.length + i;
+
+ assert_equals(regions[index].viewportAnchorX, 0, 'Failed with region ' + index);
+ assert_equals(regions[index].viewportAnchorY, 100, 'Failed with region ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-align.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-align.html
new file mode 100644
index 0000000000..06ea26fa78
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-align.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-align.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, align</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, align');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-align.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 13);
+
+[
+ 'center',
+ 'start',
+ 'center',
+ 'end',
+ 'left',
+ 'right',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'end',
+ 'center',
+].forEach(function(valid, index) {
+ assert_equals(cues[index].align, valid, 'Failed with cue ' + index);
+});
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-line.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-line.html
new file mode 100644
index 0000000000..a38e56eb0b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-line.html
@@ -0,0 +1,102 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-line.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, line</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, line');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-line.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 46);
+
+// Test starts with simple valid values
+var valid_values = [
+ -1,
+ 0,
+ 0,
+ 1,
+ 100,
+ 101,
+ 65536,
+ 4294967296,
+ 18446744073709552000,
+ 10000000000000000000000000000000000,
+ 1.5,
+ Number.MAX_VALUE,
+ -1 * Number.MAX_VALUE,
+ Number.MIN_VALUE,
+ 0, // Less than Number.MIN_VALUE
+];
+valid_values.forEach(function(valid, index) {
+ assert_equals(cues[index].line, valid, 'Failed with cue ' + index);
+ assert_true(cues[index].snapToLines, 'Failed with cue ' + index);
+});
+
+// Then a set of invalid ones
+var invalid_length = 23;
+for (var i = 0; i < invalid_length; i++) {
+ var index = valid_values.length + i;
+
+ assert_equals(cues[index].line, 'auto', 'Failed with cue ' + index);
+ assert_true(cues[index].snapToLines, 'Failed with cue ' + index);
+}
+
+// Then more specific tests
+var index = valid_values.length + invalid_length;
+
+assert_equals(cues[index].line, 0);
+assert_false(cues[index].snapToLines);
+
+assert_equals(cues[index + 1].line, 0);
+assert_false(cues[index + 1].snapToLines);
+
+assert_equals(cues[index + 2].line, 100);
+assert_false(cues[index + 2].snapToLines);
+assert_equals(cues[index + 2].lineAlign, 'start');
+
+assert_equals(cues[index + 3].line, 100);
+assert_false(cues[index + 3].snapToLines);
+assert_equals(cues[index + 3].lineAlign, 'start');
+
+assert_equals(cues[index + 4].line, 100);
+assert_false(cues[index + 4].snapToLines);
+assert_equals(cues[index + 4].lineAlign, 'center');
+
+assert_equals(cues[index + 5].line, 100);
+assert_false(cues[index + 5].snapToLines);
+assert_equals(cues[index + 5].lineAlign, 'end');
+
+assert_equals(cues[index + 6].line, Number.MIN_VALUE);
+assert_false(cues[index + 6].snapToLines);
+
+assert_equals(cues[index + 7].line, 0);
+assert_false(cues[index + 7].snapToLines);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-multiple.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-multiple.html
new file mode 100644
index 0000000000..982a36a125
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-multiple.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-multiple.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, multiple</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, multiple');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-multiple.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+var cue = cues[0];
+assert_equals(cue.id, 'id0');
+assert_equals(cue.text, 'text0');
+assert_equals(cue.align, 'start');
+assert_equals(cue.line, 1);
+assert_equals(cue.snapToLines, false);
+assert_equals(cue.vertical, 'lr');
+assert_equals(cue.size, 50);
+assert_equals(cue.position, 25);
+
+var cue = cues[1];
+assert_equals(cue.id, 'id1');
+assert_equals(cue.text, 'text1');
+assert_equals(cue.align, 'center');
+assert_equals(cue.line, 1);
+assert_equals(cue.vertical, 'rl');
+assert_equals(cue.size, 0);
+assert_equals(cue.position, 100);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-position.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-position.html
new file mode 100644
index 0000000000..e4ddcf8dbe
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-position.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-position.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, position</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, position');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-position.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 22);
+
+var valid_positions = [
+ [1, 'auto'],
+ [100, 'auto'],
+ [1, 'auto'],
+ [1.5, 'auto'],
+ [1, 'line-left'],
+ [1, 'center'],
+ [1, 'line-right'],
+ [1, 'auto'],
+];
+valid_positions.forEach(function(pair, index) {
+ var position = pair[0];
+ var positionAlign = pair[1];
+
+ assert_equals(cues[index].position, position, 'Failed with cue ' + index);
+ assert_equals(cues[index].positionAlign, positionAlign, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 14; i++) {
+ var index = valid_positions.length + i;
+
+ assert_equals(cues[index].position, 'auto', 'Failed with cue ' + index);
+ assert_equals(cues[index].positionAlign, 'auto', 'Failed with cue ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-region.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-region.html
new file mode 100644
index 0000000000..150f2feec4
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-region.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-region.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, region</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, region');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-region.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 9);
+
+var fooRegion = cues[0].region;
+assert_true(!!fooRegion, 'Cue 0 has invalid region');
+
+var barRegion = cues[1].region;
+assert_true(!!barRegion, 'Cue 1 has invalid region');
+
+assert_not_equals(fooRegion, barRegion);
+
+var valid_regions = [
+ fooRegion,
+ barRegion,
+ barRegion,
+ null,
+ fooRegion
+];
+valid_regions.forEach(function(valid, index) {
+ assert_equals(cues[index].region, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_regions.length + i;
+
+ assert_equals(cues[index].region, null);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-size.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-size.html
new file mode 100644
index 0000000000..be0ee561cb
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-size.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-size.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, size</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, size');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-size.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 16);
+
+var valid_sizes = [
+ 100,
+ 2,
+ 0,
+ 0,
+ 100,
+ 50,
+ 1.5,
+];
+valid_sizes.forEach(function(valid, index) {
+ assert_equals(cues[index].size, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 9; i++) {
+ var index = valid_sizes.length + i;
+
+ assert_equals(cues[index].size, 100, 'Failed with cue ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-vertical.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-vertical.html
new file mode 100644
index 0000000000..70af76588f
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/settings-vertical.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/settings-vertical.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: settings, size</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('settings, size');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/settings-vertical.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 8);
+
+var valid_vertical = [
+ '',
+ 'lr',
+ 'rl',
+ 'lr',
+];
+valid_vertical.forEach(function(valid, index) {
+ assert_equals(cues[index].vertical, valid, 'Failed with cue ' + index);
+});
+
+for (var i = 0; i < 4; i++) {
+ var index = valid_vertical.length + i;
+
+ assert_equals(cues[index].vertical, '', 'Failed with cue ' + index);
+}
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-bom.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-bom.html
new file mode 100644
index 0000000000..6addc7bb69
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-bom.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-bom.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, bom</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, bom');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-bom.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-no-newline.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-no-newline.html
new file mode 100644
index 0000000000..e96915d3a3
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-no-newline.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-no-newline.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, no newline</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, no newline');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-no-newline.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space-no-newline.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space-no-newline.html
new file mode 100644
index 0000000000..28a55f8f15
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space-no-newline.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-space-no-newline.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, space, no newline</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, space, no newline');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-space-no-newline.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space.html
new file mode 100644
index 0000000000..cfc1540947
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-space.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-space.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, space</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, space');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-space.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab-no-newline.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab-no-newline.html
new file mode 100644
index 0000000000..f4fd270df6
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab-no-newline.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-tab-no-newline.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, tab, no newline</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, tab, no newline');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-tab-no-newline.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab.html
new file mode 100644
index 0000000000..cd5df4c319
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-tab.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-tab.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, tab</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, tab');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-tab.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-timings.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-timings.html
new file mode 100644
index 0000000000..6394c89888
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/signature-timings.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/signature-timings.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: signature, timings</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#webvtt-parser-algorithm">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('signature, timings');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/signature-timings.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/stylesheets.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/stylesheets.html
new file mode 100644
index 0000000000..48cd920c79
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/stylesheets.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/stylesheets.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: stylesheets, rules</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('stylesheets, rules');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/stylesheets.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+// There's no way to test the actual style from js
+assert_equals(document.styleSheets.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/arrows.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/arrows.vtt
new file mode 100644
index 0000000000..30d17b9de1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/arrows.vtt
@@ -0,0 +1,27 @@
+WEBVTT
+
+-->
+00:00:00.000 --> 00:00:01.000
+text0
+foo-->
+00:00:00.000 --> 00:00:01.000
+text1
+-->foo
+00:00:00.000 --> 00:00:01.000
+text2
+--->
+00:00:00.000 --> 00:00:01.000
+text3
+-->-->
+00:00:00.000 --> 00:00:01.000
+text4
+00:00:00.000 --> 00:00:01.000
+text5
+
+00:00:00.000 -a -->
+
+00:00:00.000 --a -->
+
+00:00:00.000 - -->
+
+00:00:00.000 -- -->
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/comment-in-cue-text.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/comment-in-cue-text.vtt
new file mode 100644
index 0000000000..47081905a7
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/comment-in-cue-text.vtt
@@ -0,0 +1,14 @@
+WEBVTT
+
+NOTE this is real comment that should be ignored
+
+00:00:00.000 --> 00:00:01.000
+NOTE text
+
+NOTE
+this is also a real comment that should be ignored
+this is also a real comment that should be ignored
+
+00:00:01.000 --> 00:00:02.000
+NOTE text
+NOTE text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-garbage.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-garbage.vtt
new file mode 100644
index 0000000000..0504e796be
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-garbage.vtt
@@ -0,0 +1,5 @@
+WEBVTT
+foobar
+
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-regions.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-regions.vtt
new file mode 100644
index 0000000000..67308835b6
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-regions.vtt
@@ -0,0 +1,59 @@
+WEBVTT FILE
+
+REGION
+id:region_without_settings
+
+REGION
+id:region_with_all_settings width:32%
+lines:5
+regionanchor:41%,20% viewportanchor:31%,84%
+scroll:up
+
+REGION
+id:region_floating_point_anchor
+regionanchor:41.125%,20.25% viewportanchor:32.75%,32.5%
+
+REGION
+id:not_unique_id width:42%
+
+REGION
+id:not_unique_id
+width:67%
+
+REGION
+invalid_settings values but region still created
+: Invalid Header
+
+REGION
+id:region_split_by_ascii_whitespace width:10%
+lines:5 regionanchor:40%,20% viewportanchor:30%,80% scroll:up
+
+00:00:00.000 --> 00:00:02.500 region:someregionattributeid
+"no region"
+
+00:00:00.000 --> 00:00:02.500 line:5 region:ignored_attribute_value
+"no region"
+
+00:00:00.000 --> 00:00:02.500 size:10% region:ignored_attribute_value
+"no region"
+
+00:00:00.000 --> 00:00:02.500 vertical:lr region:ignored_attribute_value
+"no region"
+
+00:00:03.000 --> 00:00:04.000 region:region_without_settings
+{}
+
+00:00:04.000 --> 00:00:05.000 region:region_with_all_settings
+{"width":32,"lines":5,"regionAnchorX":41,"regionAnchorY":20,"viewportAnchorX":31,"viewportAnchorY":84,"scroll":"up"}
+
+00:00:05.000 --> 00:00:06.000 region:region_floating_point_anchor
+{"regionAnchorX":41.125,"regionAnchorY":20.25,"viewportAnchorX":32.75,"viewportAnchorY":32.5}
+
+00:00:06.000 --> 00:00:07.000 region:not_unique_id
+{"width":67}
+
+00:00:07.000 --> 00:00:08.000 region:
+"no region"
+
+00:00:08.000 --> 00:00:09.000 region:region_split_by_ascii_whitespace
+{"width":10,"lines":5,"regionAnchorX":40,"regionAnchorY":20,"viewportAnchorX":30,"viewportAnchorY":80,"scroll":"up"}
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-space.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-space.vtt
new file mode 100644
index 0000000000..9462a1e7c1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-space.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-tab.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-tab.vtt
new file mode 100644
index 0000000000..76564a6e1a
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-tab.vtt
@@ -0,0 +1,4 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-timings.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-timings.vtt
new file mode 100644
index 0000000000..5442228eec
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/header-timings.vtt
@@ -0,0 +1,3 @@
+WEBVTT
+00:00:00.000 --> 00:00:01.000
+text \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/ids.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/ids.vtt
new file mode 100644
index 0000000000..5f3e91f8a4
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/ids.vtt
@@ -0,0 +1,21 @@
+WEBVTT
+
+ leading space
+00:00:00.000 --> 00:00:01.000
+text0
+
+trailing space
+00:00:00.000 --> 00:00:01.000
+text1
+
+-- >
+00:00:00.000 --> 00:00:01.000
+text2
+
+->
+00:00:00.000 --> 00:00:01.000
+text3
+
+
+00:00:00.000 --> 00:00:01.000
+text4
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/newlines.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/newlines.vtt
new file mode 100644
index 0000000000..bde1c30e2c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/newlines.vtt
@@ -0,0 +1,12 @@
+WEBVTT cr 00:00:00.000 --> 00:00:01.000 text0
+
+lf
+00:00:00.000 --> 00:00:01.000
+text1
+
+crlf
+00:00:00.000 --> 00:00:01.000
+text2
+ lfcr 00:00:00.000 --> 00:00:01.000
+text3
+
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/nulls.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/nulls.vtt
new file mode 100644
index 0000000000..fe6d193d63
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/nulls.vtt
Binary files differ
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt
new file mode 100644
index 0000000000..29debd5bd8
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-edge-case.vtt
@@ -0,0 +1,44 @@
+WEBVTT
+
+NOTE valid
+
+REGION
+id:foo lines:1
+
+-->
+REGION
+id:foo
+lines:2
+-->
+
+REGION
+id:bill
+lines:2
+
+REGION
+REGION
+id:jill
+lines:3
+
+REGION
+--->
+id:jill lines:4
+
+REGION
+id:jack--> lines:5
+
+REGION
+id:jack lines:4
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text
+
+00:00:00.000 --> 00:00:01.000 region:bill
+text
+
+00:00:00.000 --> 00:00:01.000 region:jill
+text
+
+00:00:00.000 --> 00:00:01.000 region:jack
+text
+
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-id.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-id.vtt
new file mode 100644
index 0000000000..bbcc14d2cd
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-id.vtt
@@ -0,0 +1,34 @@
+WEBVTT
+
+NOTE No API for accessing region ids, so using lines to uniquely identify regions
+
+REGION
+id:foo
+id:bar
+lines:1
+
+REGION
+id:bar id:foo
+lines:2
+
+REGION
+id:id
+id: foo
+id :bar
+lines:3
+
+REGION
+id:
+lines:4
+
+00:00:00.000 --> 00:00:01.000 region:foo
+valid
+
+00:00:00.000 --> 00:00:01.000 region:bar
+valid
+
+00:00:00.000 --> 00:00:01.000 region:id
+valid
+
+00:00:00.000 --> 00:00:01.000 region:
+valid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-lines.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-lines.vtt
new file mode 100644
index 0000000000..d6397045aa
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-lines.vtt
@@ -0,0 +1,98 @@
+WEBVTT
+
+NOTE valid
+
+REGION
+id:1
+lines:0
+
+REGION
+id:2
+lines:1
+
+REGION
+id:3
+lines:100
+
+REGION
+id:4
+lines:101
+
+REGION
+id:5
+lines:65536
+
+REGION
+id:6
+lines:4294967296
+
+REGION
+id:7
+lines:18446744073709552000
+
+REGION
+id:8
+lines:10000000000000000000000000000000000
+
+REGION
+id:9
+lines:1 lines:3
+lines:2
+
+NOTE invalid
+
+REGION
+id:10
+lines:-0
+
+REGION
+id:11
+lines:1.5
+
+REGION
+id:12
+lines:-1
+
+REGION
+id:13
+lines: 1
+lines :1
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-old.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-old.vtt
new file mode 100644
index 0000000000..f9b26659a8
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-old.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+Region: id=foo width=40% lines=3 regionanchor=0%,100% viewportanchor=10%,90% scroll=up
+Region: id=bar width=40% lines=3 regionanchor=100%,100% viewportanchor=90%,90% scroll=up
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text0
+
+00:00:00.000 --> 00:00:01.000 region:bar
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-regionanchor.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-regionanchor.vtt
new file mode 100644
index 0000000000..e6aa770c37
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-regionanchor.vtt
@@ -0,0 +1,149 @@
+WEBVTT
+
+NOTE valid
+
+REGION
+id:0
+
+REGION
+id:1
+regionanchor:0%,0%
+
+REGION
+id:2
+regionanchor:1%,1%
+
+REGION
+id:3
+regionanchor:100%,0%
+
+REGION
+id:4
+regionanchor:0%,100%
+
+REGION
+id:5
+regionanchor:100%,100%
+
+NOTE invalid
+
+REGION
+id:6
+regionanchor:0,0
+
+REGION
+id:7
+regionanchor:0%,0
+
+REGION
+id:8
+regionanchor:0,0%
+
+REGION
+id:9
+regionanchor:1%
+
+REGION
+id:10
+regionanchor:,1%
+
+REGION
+id:11
+regionanchor:101%,1%
+
+REGION
+id:12
+regionanchor:1%,101%
+
+REGION
+id:13
+regionanchor:-0%,0%
+
+REGION
+id:14
+regionanchor:0%,-0%
+
+REGION
+id:15
+regionanchor:65536%,65536%
+
+REGION
+id:16
+regionanchor:4294967296%,4294967296%
+
+REGION
+id:17
+regionanchor:18446744073709552000%,18446744073709552000%
+
+REGION
+id:18
+regionanchor:10000000000000000000000000000000000%,10000000000000000000000000000000000%
+
+REGION
+id:19
+regionanchor: 100%,100%
+regionanchor :100%,100%
+regionanchor:100% ,100%
+regionanchor:100%, 100%
+regionanchor:100 %,100%
+regionanchor:100%,100 %
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
+
+00:00:00.000 --> 00:00:01.000 region:14
+text
+
+00:00:00.000 --> 00:00:01.000 region:15
+text
+
+00:00:00.000 --> 00:00:01.000 region:16
+text
+
+00:00:00.000 --> 00:00:01.000 region:17
+text
+
+00:00:00.000 --> 00:00:01.000 region:18
+text
+
+00:00:00.000 --> 00:00:01.000 region:19
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-scroll.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-scroll.vtt
new file mode 100644
index 0000000000..4c7f21d935
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-scroll.vtt
@@ -0,0 +1,46 @@
+WEBVTT
+
+REGION
+id:0
+
+REGION
+id:1
+scroll:up
+
+REGION
+id:2
+scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up
+scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up scroll:up
+
+REGION
+id:3
+scroll:down
+scroll:left
+scroll:right
+
+REGION
+id:4
+scroll: up
+scroll :up
+
+REGION
+id:5
+scroll:up scroll:
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-viewportanchor.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-viewportanchor.vtt
new file mode 100644
index 0000000000..7470be647c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/regions-viewportanchor.vtt
@@ -0,0 +1,149 @@
+WEBVTT
+
+NOTE valid
+
+REGION
+id:0
+
+REGION
+id:1
+viewportanchor:0%,0%
+
+REGION
+id:2
+viewportanchor:1%,1%
+
+REGION
+id:3
+viewportanchor:100%,0%
+
+REGION
+id:4
+viewportanchor:0%,100%
+
+REGION
+id:5
+viewportanchor:100%,100%
+
+NOTE invalid
+
+REGION
+id:6
+viewportanchor:0,0
+
+REGION
+id:7
+viewportanchor:0%,0
+
+REGION
+id:8
+viewportanchor:0,0%
+
+REGION
+id:9
+viewportanchor:1%
+
+REGION
+id:10
+viewportanchor:,1%
+
+REGION
+id:11
+viewportanchor:101%,1%
+
+REGION
+id:12
+viewportanchor:1%,101%
+
+REGION
+id:13
+viewportanchor:-0%,0%
+
+REGION
+id:14
+viewportanchor:0%,-0%
+
+REGION
+id:15
+viewportanchor:65536%,65536%
+
+REGION
+id:16
+viewportanchor:4294967296%,4294967296%
+
+REGION
+id:17
+viewportanchor:18446744073709552000%,18446744073709552000%
+
+REGION
+id:18
+viewportanchor:10000000000000000000000000000000000%,10000000000000000000000000000000000%
+
+REGION
+id:19
+viewportanchor: 100%,100%
+viewportanchor :100%,100%
+viewportanchor:100% ,100%
+viewportanchor:100%, 100%
+viewportanchor:100 %,100%
+viewportanchor:100%,100 %
+
+00:00:00.000 --> 00:00:01.000 region:0
+text
+
+00:00:00.000 --> 00:00:01.000 region:1
+text
+
+00:00:00.000 --> 00:00:01.000 region:2
+text
+
+00:00:00.000 --> 00:00:01.000 region:3
+text
+
+00:00:00.000 --> 00:00:01.000 region:4
+text
+
+00:00:00.000 --> 00:00:01.000 region:5
+text
+
+00:00:00.000 --> 00:00:01.000 region:6
+text
+
+00:00:00.000 --> 00:00:01.000 region:7
+text
+
+00:00:00.000 --> 00:00:01.000 region:8
+text
+
+00:00:00.000 --> 00:00:01.000 region:9
+text
+
+00:00:00.000 --> 00:00:01.000 region:10
+text
+
+00:00:00.000 --> 00:00:01.000 region:11
+text
+
+00:00:00.000 --> 00:00:01.000 region:12
+text
+
+00:00:00.000 --> 00:00:01.000 region:13
+text
+
+00:00:00.000 --> 00:00:01.000 region:14
+text
+
+00:00:00.000 --> 00:00:01.000 region:15
+text
+
+00:00:00.000 --> 00:00:01.000 region:16
+text
+
+00:00:00.000 --> 00:00:01.000 region:17
+text
+
+00:00:00.000 --> 00:00:01.000 region:18
+text
+
+00:00:00.000 --> 00:00:01.000 region:19
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-align.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-align.vtt
new file mode 100644
index 0000000000..3bcfe5ac4c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-align.vtt
@@ -0,0 +1,40 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 align:start
+text1
+
+00:00:00.000 --> 00:00:01.000 align:center
+text2
+
+00:00:00.000 --> 00:00:01.000 align:end
+text3
+
+00:00:00.000 --> 00:00:01.000 align:left
+text4
+
+00:00:00.000 --> 00:00:01.000 align:right
+text5
+
+00:00:00.000 --> 00:00:01.000 align:start align:end
+text6
+
+00:00:00.000 --> 00:00:01.000 align:end align:CENTER
+text7
+
+00:00:00.000 --> 00:00:01.000 align:end align: center
+text8
+
+00:00:00.000 --> 00:00:01.000 align:end align:
+text9
+
+00:00:00.000 --> 00:00:01.000 align:end align:middle
+text10
+
+00:00:00.000 --> 00:00:01.000 align:end align
+text11
+
+00:00:00.000 --> 00:00:01.000 align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:end align:center
+text12
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-line.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-line.vtt
new file mode 100644
index 0000000000..03ce64a1cf
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-line.vtt
@@ -0,0 +1,154 @@
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000 line:-1
+valid0
+
+00:00:00.000 --> 00:00:01.000 line:0
+valid1
+
+00:00:00.000 --> 00:00:01.000 line:-0
+valid2
+
+00:00:00.000 --> 00:00:01.000 line:1
+valid3
+
+00:00:00.000 --> 00:00:01.000 line:100
+valid4
+
+00:00:00.000 --> 00:00:01.000 line:101
+valid5
+
+00:00:00.000 --> 00:00:01.000 line:65536
+valid6
+
+00:00:00.000 --> 00:00:01.000 line:4294967296
+valid7
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000
+valid8
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000
+valid9
+
+00:00:00.000 --> 00:00:01.000 line:1.5
+valid10
+
+Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+valid11
+
+-1 * Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:-179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+valid12
+
+Number.MIN_VALUE
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005
+valid13
+
+Less than Number.MIN_VALUE
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
+valid14
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 line:65536%
+invalid15
+
+00:00:00.000 --> 00:00:01.000 line:4294967296%
+invalid16
+
+00:00:00.000 --> 00:00:01.000 line:18446744073709552000%
+invalid17
+
+00:00:00.000 --> 00:00:01.000 line:10000000000000000000000000000000000%
+invalid18
+
+00:00:00.000 --> 00:00:01.000 line:-0%
+invalid19
+
+00:00:00.000 --> 00:00:01.000 line:101%
+invalid20
+
+00:00:00.000 --> 00:00:01.000 line:1%-
+invalid21
+
+00:00:00.000 --> 00:00:01.000 line:1-
+invalid22
+
+00:00:00.000 --> 00:00:01.000 line:%1
+invalid23
+
+00:00:00.000 --> 00:00:01.000 line:1%%
+invalid24
+
+00:00:00.000 --> 00:00:01.000 line:0%0
+invalid25
+
+00:00:00.000 --> 00:00:01.000 line: 0%
+invalid26
+
+00:00:00.000 --> 00:00:01.000 line:0%x
+invalid27
+
+00:00:00.000 --> 00:00:01.000 line:-
+invalid28
+
+00:00:00.000 --> 00:00:01.000 line:%
+invalid29
+
+00:00:00.000 --> 00:00:01.000 line:1..5
+invalid30
+
+00:00:00.000 --> 00:00:01.000 line:.5
+invalid31
+
+00:00:00.000 --> 00:00:01.000 line:5.
+invalid32
+
+Greater than Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:179769313486231590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+invalid33
+
+Less than -1 * Number.MAX_VALUE
+00:00:00.000 --> 00:00:01.000 line:-179769313486231590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+invalid34
+
+exponential notation
+00:00:00.000 --> 00:00:01.000 line:1e2
+invalid35
+
+00:00:00.000 --> 00:00:01.000 line:100%,middle
+invalid36
+
+00:00:00.000 --> 00:00:01.000 line:100%,
+invalid37
+
+NOTE extra
+
+00:00:00.000 --> 00:00:01.000 line:0%
+text38
+
+00:00:00.000 --> 00:00:01.000 line:00%
+text39
+
+00:00:00.000 --> 00:00:01.000 line:100%
+text40
+
+00:00:00.000 --> 00:00:01.000 line:100%,start
+text41
+
+00:00:00.000 --> 00:00:01.000 line:100%,center
+text42
+
+00:00:00.000 --> 00:00:01.000 line:100%,end
+text43
+
+Number.MIN_VALUE %
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005%
+text44
+
+Less than Number.MIN_VALUE %
+00:00:00.000 --> 00:00:01.000 line:0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002%
+text45
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-multiple.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-multiple.vtt
new file mode 100644
index 0000000000..17035a2a42
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-multiple.vtt
@@ -0,0 +1,9 @@
+WEBVTT
+
+id0
+00:00:00.000 --> 00:00:01.000 align:start line:1% vertical:lr size:50% position:25%
+text0
+
+id1
+00:00:00.000 --> 00:00:01.000 align:center line:1 vertical:rl size:0% position:100%
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-position.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-position.vtt
new file mode 100644
index 0000000000..9ded1a67a3
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-position.vtt
@@ -0,0 +1,71 @@
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000 position:1%
+text0
+
+00:00:00.000 --> 00:00:01.000 position:100%
+text1
+
+00:00:00.000 --> 00:00:01.000 position:1% position:x
+text2
+
+00:00:00.000 --> 00:00:01.000 position:1.5%
+text3
+
+00:00:00.000 --> 00:00:01.000 position:1%,line-left
+text4
+
+00:00:00.000 --> 00:00:01.000 position:1%,center
+text5
+
+00:00:00.000 --> 00:00:01.000 position:1%,line-right
+text6
+
+00:00:00.000 --> 00:00:01.000 position:1% ,center
+text7
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 position:1%,middle
+invalid8
+
+00:00:00.000 --> 00:00:01.000 position:1%, center
+invalid9
+
+00:00:00.000 --> 00:00:01.000 position:-1%
+invalid10
+
+00:00:00.000 --> 00:00:01.000 position:1
+invalid11
+
+00:00:00.000 --> 00:00:01.000 position:1x
+invalid12
+
+00:00:00.000 --> 00:00:01.000 position:1%x
+invalid13
+
+00:00:00.000 --> 00:00:01.000 position:
+invalid14
+
+00:00:00.000 --> 00:00:01.000 position: 1%
+invalid15
+
+00:00:00.000 --> 00:00:01.000 position:101%
+invalid16
+
+00:00:00.000 --> 00:00:01.000 position:65536%
+invalid17
+
+00:00:00.000 --> 00:00:01.000 position:4294967296%
+invalid18
+
+00:00:00.000 --> 00:00:01.000 position:101%,line-left
+invalid19
+
+00:00:00.000 --> 00:00:01.000 position:101%,center
+invalid20
+
+00:00:00.000 --> 00:00:01.000 position:101%,line-right
+invalid21
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-region.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-region.vtt
new file mode 100644
index 0000000000..9116d37367
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-region.vtt
@@ -0,0 +1,40 @@
+WEBVTT
+
+REGION
+id:foo
+
+REGION
+id:bar
+
+REGION
+id:foo
+
+REGION
+width:10%
+
+00:00:00.000 --> 00:00:01.000 region:foo
+text0
+
+00:00:00.000 --> 00:00:01.000 region:bar
+text1
+
+00:00:00.000 --> 00:00:01.000 region:foo region:bar
+text2
+
+00:00:00.000 --> 00:00:01.000 region:invalid
+text3
+
+00:00:00.000 --> 00:00:01.000 region:invalid region:foo
+text4
+
+00:00:00.000 --> 00:00:01.000 region:
+invalid5
+
+00:00:00.000 --> 00:00:01.000 region:
+invalid6
+
+00:00:00.000 --> 00:00:01.000 region: foo
+invalid7
+
+00:00:00.000 --> 00:00:01.000 region :foo
+invalid8
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-size.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-size.vtt
new file mode 100644
index 0000000000..9c2cb8a78c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-size.vtt
@@ -0,0 +1,53 @@
+WEBVTT
+
+NOTE valid
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 size:1xx size:2%
+text1
+
+00:00:00.000 --> 00:00:01.000 size:0%
+text2
+
+00:00:00.000 --> 00:00:01.000 size:00%
+text3
+
+00:00:00.000 --> 00:00:01.000 size:50% size:100%
+text4
+
+00:00:00.000 --> 00:00:01.000 size:50% size:101%
+text5
+
+00:00:00.000 --> 00:00:01.000 size:1.5%
+text6
+
+NOTE invalid
+
+00:00:00.000 --> 00:00:01.000 size:
+invalid7
+
+00:00:00.000 --> 00:00:01.000 size:x
+invalid8
+
+00:00:00.000 --> 00:00:01.000 size:%
+invalid9
+
+00:00:00.000 --> 00:00:01.000 size:%%
+invalid10
+
+00:00:00.000 --> 00:00:01.000 size:1%%
+invalid11
+
+00:00:00.000 --> 00:00:01.000 size:1%x
+invalid12
+
+00:00:00.000 --> 00:00:01.000 size:101%
+invalid13
+
+00:00:00.000 --> 00:00:01.000 size:-3%
+invalid14
+
+00:00:00.000 --> 00:00:01.000 size:200%
+invalid15
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-vertical.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-vertical.vtt
new file mode 100644
index 0000000000..f24c86eaa9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/settings-vertical.vtt
@@ -0,0 +1,25 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:00:01.000 vertical:lr
+text1
+
+00:00:00.000 --> 00:00:01.000 vertical:rl
+text2
+
+00:00:00.000 --> 00:00:01.000 vertical:rl vertical:lr
+text3
+
+00:00:00.000 --> 00:00:01.000 vertical:
+invalid4
+
+00:00:00.000 --> 00:00:01.000 vertical:RL
+invalid5
+
+00:00:00.000 --> 00:00:01.000 vertical: rl
+invalid6
+
+00:00:00.000 --> 00:00:01.000 vertical:vertical-rl
+invalid7
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-bom.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-bom.vtt
new file mode 100644
index 0000000000..c0a1057770
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-bom.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-no-newline.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-no-newline.vtt
new file mode 100644
index 0000000000..af1827ddf9
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space-no-newline.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space-no-newline.vtt
new file mode 100644
index 0000000000..6abbf425ae
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space.vtt
new file mode 100644
index 0000000000..1352a20931
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-space.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab-no-newline.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab-no-newline.vtt
new file mode 100644
index 0000000000..e28ec9b83b
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab-no-newline.vtt
@@ -0,0 +1 @@
+WEBVTT \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab.vtt
new file mode 100644
index 0000000000..ab4bb0ea6f
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-tab.vtt
@@ -0,0 +1 @@
+WEBVTT
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-timings.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-timings.vtt
new file mode 100644
index 0000000000..067c284f93
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/signature-timings.vtt
@@ -0,0 +1,2 @@
+WEBVTT 00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/stylesheets.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/stylesheets.vtt
new file mode 100644
index 0000000000..409718af07
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/stylesheets.vtt
@@ -0,0 +1,29 @@
+WEBVTT
+
+STYLE
+::cue(#foo) {
+ width: 20px;
+} /*
+NOTE hello
+00:00:00.000 -- > 00:00:01.000
+*/
+.foo {
+ width: 19px;
+}
+
+.bar {
+ width: 18px;
+}
+
+foo
+00:00:00.000 --> 00:00:01.000
+text
+
+STYLE
+::cue(::bar) {
+ width: 18px;
+}
+
+bar
+00:00:00.000 --> 00:00:01.000
+text
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-60.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-60.vtt
new file mode 100644
index 0000000000..68475fbbaa
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-60.vtt
@@ -0,0 +1,19 @@
+WEBVTT
+
+00:00:60.000 --> 00:00:01.000
+invalid
+
+00:60:00.000 --> 00:00:01.000
+invalid
+
+00:00:00.000 --> 00:00:60.000
+invalid
+
+00:00:00.000 --> 00:60:00.000
+invalid
+
+00:00:00.000 --> 60:00:01.000
+text1
+
+60:00:00.000 --> 60:00:01.000
+text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-eof.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-eof.vtt
new file mode 100644
index 0000000000..470221d29c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-eof.vtt
@@ -0,0 +1,3 @@
+WEBVTT
+
+00:00:00.000 --> \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-garbage.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-garbage.vtt
new file mode 100644
index 0000000000..16291237a2
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-garbage.vtt
@@ -0,0 +1,190 @@
+WEBVTT
+
+x00:00:00.000 --> 00:00:01.000
+invalid
+
+0x0:00:00.000 --> 00:00:01.000
+invalid
+
+00x:00:00.000 --> 00:00:01.000
+invalid
+
+00:x00:00.000 --> 00:00:01.000
+invalid
+
+00:0x0:00.000 --> 00:00:01.000
+invalid
+
+00:00x:00.000 --> 00:00:01.000
+invalid
+
+00:00:x00.000 --> 00:00:01.000
+invalid
+
+00:00:0x0.000 --> 00:00:01.000
+invalid
+
+00:00:00x.000 --> 00:00:01.000
+invalid
+
+00:00:00.x000 --> 00:00:01.000
+invalid
+
+00:00:00.0x00 --> 00:00:01.000
+invalid
+
+00:00:00.00x0 --> 00:00:01.000
+invalid
+
+00:00:00.000x --> 00:00:01.000
+invalid
+
+00:00:00.000 x--> 00:00:01.000
+invalid
+
+00:00:00.000 -x-> 00:00:01.000
+invalid
+
+00:00:00.000 --x> 00:00:01.000
+invalid
+
+00:00:00.000 -->x 00:00:01.000
+invalid
+
+00:00:00.000 --> x00:00:01.000
+invalid
+
+00:00:00.000 --> 0x0:00:01.000
+invalid
+
+00:00:00.000 --> 00x:00:01.000
+invalid
+
+00:00:00.000 --> 00:x00:01.000
+invalid
+
+00:00:00.000 --> 00:0x0:01.000
+invalid
+
+00:00:00.000 --> 00:00x:01.000
+invalid
+
+00:00:00.000 --> 00:00:x01.000
+invalid
+
+00:00:00.000 --> 00:00:0x1.000
+invalid
+
+00:00:00.000 --> 00:00:01x.000
+invalid
+
+00:00:00.000 --> 00:00:01.x000
+invalid
+
+00:00:00.000 --> 00:00:01.0x00
+invalid
+
+00:00:00.000 --> 00:00:01.00x0
+invalid
+
+x0:00:00.000 --> 00:00:01.000
+invalid
+
+0x:00:00.000 --> 00:00:01.000
+invalid
+
+00x00:00.000 --> 00:00:01.000
+invalid
+
+00:x0:00.000 --> 00:00:01.000
+invalid
+
+00:0x:00.000 --> 00:00:01.000
+invalid
+
+00:00x00.000 --> 00:00:01.000
+invalid
+
+00:00:x0.000 --> 00:00:01.000
+invalid
+
+00:00:0x.000 --> 00:00:01.000
+invalid
+
+00:00:00x000 --> 00:00:01.000
+invalid
+
+00:00:00.x00 --> 00:00:01.000
+invalid
+
+00:00:00.0x0 --> 00:00:01.000
+invalid
+
+00:00:00.00x --> 00:00:01.000
+invalid
+
+00:00:00.000x--> 00:00:01.000
+invalid
+
+00:00:00.000 x-> 00:00:01.000
+invalid
+
+00:00:00.000 -x> 00:00:01.000
+invalid
+
+00:00:00.000 --x 00:00:01.000
+invalid
+
+00:00:00.000 -->x00:00:01.000
+invalid
+
+00:00:00.000 --> x0:00:01.000
+invalid
+
+00:00:00.000 --> 0x:00:01.000
+invalid
+
+00:00:00.000 --> 00x00:01.000
+invalid
+
+00:00:00.000 --> 00:x0:01.000
+invalid
+
+00:00:00.000 --> 00:0x:01.000
+invalid
+
+00:00:00.000 --> 00:00x01.000
+invalid
+
+00:00:00.000 --> 00:00:x1.000
+invalid
+
+00:00:00.000 --> 00:00:0x.000
+invalid
+
+00:00:00.000 --> 00:00:01x000
+invalid
+
+00:00:00.000 --> 00:00:01.x00
+invalid
+
+00:00:00.000 --> 00:00:01.0x0
+invalid
+
+00:00:00.000 --> 00:00:01.00x
+invalid
+
+00.00:00.000 --> 00:00:01.000
+invalid
+
+00:00.00.000 --> 00:00:01.000
+invalid
+
+00:00:00:000 --> 00:00:01.000
+invalid
+
+00:00.00:000 --> 00:00:01.000
+invalid
+
+00:00:00,000 --> 00:00:01,000
+invalid \ No newline at end of file
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-negative.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-negative.vtt
new file mode 100644
index 0000000000..fb3589d8a1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-negative.vtt
@@ -0,0 +1,13 @@
+WEBVTT
+
+00:00:00.000 --> 00:00:00.000
+text0
+
+00:00:01.000 --> 00:00:00.999
+text1
+
+00:01:00.000 --> 00:00:59.999
+text2
+
+01:00:00.000 --> 00:59:59.999
+text3
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-omitted-hours.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-omitted-hours.vtt
new file mode 100644
index 0000000000..f581ae3025
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-omitted-hours.vtt
@@ -0,0 +1,10 @@
+WEBVTT
+
+00:00.000 --> 00:00:01.000
+text0
+
+00:00:00.000 --> 00:01.000
+text1
+
+00:00.000 --> 00:01.000
+text2
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-long.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-long.vtt
new file mode 100644
index 0000000000..6357f8dccc
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-long.vtt
@@ -0,0 +1,46 @@
+WEBVTT
+
+000:00:00.000 --> 00:00:01.000
+text0
+
+00::00:00.000 --> 00:00:01.000
+invalid
+
+00:000:00.000 --> 00:00:01.000
+invalid
+
+00:00::00.000 --> 00:00:01.000
+invalid
+
+00:00:000.000 --> 00:00:01.000
+invalid
+
+00:00:00..000 --> 00:00:01.000
+invalid
+
+00:00:00.0000 --> 00:00:01.000
+invalid
+
+00:00.0000 --> 00:00:01.000
+invalid
+
+000:00.000 --> 00:01.000
+invalid
+
+00::00.000 --> 00:01.000
+invalid
+
+00:000.000 --> 00:01.000
+invalid
+
+00:00..000 --> 00:01.000
+invalid
+
+00:00.0000 --> 00:01.000
+invalid
+
+00:00.000 --> 000:01.000
+invalid
+
+00:00:00.000 --> 000:00:01.000
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-short.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-short.vtt
new file mode 100644
index 0000000000..78d190a7bc
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/timings-too-short.vtt
@@ -0,0 +1,97 @@
+WEBVTT
+
+0:00:00.000 --> 00:00:01.000
+text0
+
+0000:00.000 --> 00:00:01.000
+invalid
+
+00:0:00.000 --> 00:00:01.000
+invalid
+
+00:0000.000 --> 00:00:01.000
+invalid
+
+00:00:0.000 --> 00:00:01.000
+invalid
+
+00:00:00000 --> 00:00:01.000
+invalid
+
+00:00:00.00 --> 00:00:01.000
+invalid
+
+00:00:00.0 --> 00:00:01.000
+invalid
+
+00:00:00. --> 00:00:01.000
+invalid
+
+00:00:00 --> 00:00:01.000
+invalid
+
+00:00:0 --> 00:00:01.000
+invalid
+
+00:00: --> 00:00:01.000
+invalid
+
+00:00 --> 00:00:01.000
+invalid
+
+00:0 --> 00:00:01.000
+invalid
+
+00: --> 00:00:01.000
+invalid
+
+00 --> 00:00:01.000
+invalid
+
+0 --> 00:00:01.000
+invalid
+
+ --> 00:00:01.000
+invalid
+
+0:00.000 --> 00:01.000
+invalid
+
+0000.000 --> 00:01.000
+invalid
+
+00:0.000 --> 00:01.000
+invalid
+
+00:00000 --> 00:01.000
+invalid
+
+00:00.00 --> 00:01.000
+invalid
+
+00:00.0 --> 00:01.000
+invalid
+
+00:00. --> 00:01.000
+invalid
+
+0:00. --> 00:01.000
+invalid
+
+:00. --> 00:01.000
+invalid
+
+00. --> 00:01.000
+invalid
+
+0. --> 00:01.000
+invalid
+
+. --> 00:01.000
+invalid
+
+00:00.000 --> 0:01.000
+invalid
+
+00:00:00.000 --> 0:00:01.000
+text1
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/whitespace-chars.vtt b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/whitespace-chars.vtt
new file mode 100644
index 0000000000..b26c93cd19
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/support/whitespace-chars.vtt
@@ -0,0 +1,17 @@
+WEBVTT
+
+spaces
+ 00:00:00.000 --> 00:00:01.000
+ text0
+
+tabs
+ 00:00:00.000 --> 00:00:01.000
+text1
+
+form feed
+ 00:00:00.000 --> 00:00:01.000
+text2
+
+vertical tab
+ 00:00:00.000 --> 00:00:01.000
+invalid
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-60.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-60.html
new file mode 100644
index 0000000000..ddc21a0915
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-60.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-60.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, 60</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, 60');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-60.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text1');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 216001);
+
+assert_equals(cues[1].text, 'text2');
+assert_equals(cues[1].startTime, 216000);
+assert_equals(cues[1].endTime, 216001);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-eof.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-eof.html
new file mode 100644
index 0000000000..3750cfb703
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-eof.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-eof.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, eof</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, eof');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-eof.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-garbage.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-garbage.html
new file mode 100644
index 0000000000..4af3ca47f1
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-garbage.html
@@ -0,0 +1,40 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-garbage.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, garbage</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-webvtt-cue-timings-and-settings">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, garbage');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-garbage.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 0);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-negative.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-negative.html
new file mode 100644
index 0000000000..5645de6e27
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-negative.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-negative.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, negative</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, negative');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-negative.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 4);
+
+[
+ [0, 0],
+ [1, 0.999],
+ [60, 59.999],
+ [3600, 3599.999],
+].forEach(function(pair, index) {
+ var startTime = pair[0];
+ var endTime = pair[1];
+
+ assert_equals(cues[index].text, 'text' + index, 'Failed with cue ' + index);
+ assert_equals(cues[index].startTime, startTime, 'Failed with cue ' + index);
+ assert_equals(cues[index].endTime, endTime, 'Failed with cue ' + index);
+});
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-omitted-hours.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-omitted-hours.html
new file mode 100644
index 0000000000..89c6f67896
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-omitted-hours.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-omitted-hours.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, omitted hours</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, omitted hours');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-omitted-hours.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 3);
+
+Array.from(cues).forEach(function(cue, index) {
+ assert_equals(cue.text, 'text' + index, 'Failed with cue ' + index);
+ assert_equals(cue.startTime, 0, 'Failed with cue ' + index);
+ assert_equals(cue.endTime, 1, 'Failed with cue ' + index);
+});
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-long.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-long.html
new file mode 100644
index 0000000000..5270c62173
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-long.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-too-long.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, too long</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, too long');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-too-long.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text0');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'text1');
+assert_equals(cues[1].startTime, 0);
+assert_equals(cues[1].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-short.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-short.html
new file mode 100644
index 0000000000..3295260d44
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/timings-too-short.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/timings-too-short.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: timings, too short</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-timestamp">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('timings, too short');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/timings-too-short.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 2);
+
+assert_equals(cues[0].text, 'text0');
+assert_equals(cues[0].startTime, 0);
+assert_equals(cues[0].endTime, 1);
+
+assert_equals(cues[1].text, 'text1');
+assert_equals(cues[1].startTime, 0);
+assert_equals(cues[1].endTime, 1);
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/whitespace-chars.html b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/whitespace-chars.html
new file mode 100644
index 0000000000..92ecf7e0c2
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tests/whitespace-chars.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<!-- DO NOT EDIT! This file and support/whitespace-chars.vtt are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: whitespace chars</title>
+<link rel="help" href="https://w3c.github.io/webvtt/#collect-a-webvtt-block">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('whitespace chars');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = 'support/whitespace-chars.vtt';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+assert_equals(cues.length, 3);
+
+assert_equals(cues[0].id, 'spaces');
+assert_equals(cues[0].text, ' text0');
+
+assert_equals(cues[1].id, 'tabs');
+assert_equals(cues[1].text, 'text1');
+
+assert_equals(cues[2].id, 'form feed');
+assert_equals(cues[2].text, 'text2');
+
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/build.py b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/build.py
new file mode 100644
index 0000000000..d4c0fdf78d
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/build.py
@@ -0,0 +1,120 @@
+import os
+import glob
+import shutil
+from os import path
+
+
+TEST_FILE_PATTERN = "support/**.test"
+TEST_OUTPUT_PATH = "tests"
+
+TEMPLATE = """\
+<!doctype html>
+<!-- DO NOT EDIT! This file and %vtt_file_rel_path are generated. -->
+<!-- See /webvtt/parsing/file-parsing/README.md -->
+<meta charset=utf-8>
+<title>WebVTT parser test: %test_name</title>
+%test_headers
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var t = async_test('%test_name');
+t.step(function(){
+ var video = document.createElement('video');
+ var track = document.createElement('track');
+ assert_true('src' in track, 'track element not supported');
+ track.src = '%vtt_file_rel_path';
+ track['default'] = true;
+ track.kind = 'subtitles';
+ track.onload = this.step_func(trackLoaded);
+ track.onerror = this.step_func(trackError);
+ video.appendChild(track);
+ document.body.appendChild(video);
+});
+
+function trackLoaded(event) {
+ var track = event.target;
+ var video = track.parentNode;
+ var cues = video.textTracks[0].cues;
+ {
+%test_js
+ }
+ this.done();
+}
+
+function trackError(e) {
+ assert_unreached('got unexpected error event');
+}
+</script>
+"""
+
+def generate_test(test_path, output_dir):
+ # Read test file
+ test_filename = path.basename(test_path)
+ test_basefilename = path.splitext(test_filename)[0]
+
+ with open(test_path, 'r') as test:
+ test_source = test.read()
+
+ # Split test header
+ splits = test_source.split('\n\n', 1)
+ if len(splits) != 2:
+ raise ValueError("Leave an empty line between the test header and body")
+
+ test_header, test_body = splits
+
+ # Split header into name + html headers
+ splits = test_header.split('\n', 1)
+
+ test_name = splits[0]
+ if len(splits) == 2:
+ test_headers = splits[1]
+
+ # Split body into js + vtt
+ splits = test_body.split('\n===\n', 1)
+ if len(splits) != 2:
+ raise ValueError("Use === to separate the js and vtt parts")
+
+ test_js, test_vtt = splits
+
+ # Get output paths
+ os.makedirs(output_dir, exist_ok=True)
+ html_file_path = path.join(output_dir, test_basefilename + '.html')
+
+ vtt_file_dir = path.join(output_dir, 'support')
+ os.makedirs(vtt_file_dir, exist_ok=True)
+
+ vtt_file_name = test_basefilename + '.vtt'
+ vtt_file_path = path.join(vtt_file_dir, vtt_file_name)
+ vtt_file_rel_path = path.join('support', vtt_file_name)
+
+ # Write html file
+ with open(html_file_path, 'w') as output:
+ html = (TEMPLATE.replace('%test_name', test_name)
+ .replace('%test_headers', test_headers)
+ .replace('%test_js', test_js)
+ .replace('%vtt_file_rel_path', vtt_file_rel_path))
+ output.write(html)
+
+ # Write vtt file
+ with open(vtt_file_path, 'w') as output:
+ encoded = bytes(test_vtt, "utf-8").decode("unicode_escape")
+ output.write(encoded)
+
+def main():
+ file_parsing_path = path.normpath(path.join(path.dirname(__file__), ".."))
+
+ test_output_path = path.join(file_parsing_path, TEST_OUTPUT_PATH)
+
+ tests_pattern = path.join(file_parsing_path, TEST_FILE_PATTERN)
+
+ # Clean test directory
+ shutil.rmtree(test_output_path)
+
+ # Generate tests
+ for file in glob.glob(tests_pattern):
+ print('Building test files for: ' + file)
+ generate_test(file, test_output_path)
+
+if __name__ == '__main__':
+ main()
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/parser.py b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/parser.py
new file mode 100644
index 0000000000..b77e83de78
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/parser.py
@@ -0,0 +1,710 @@
+"""
+A direct translation of the webvtt file parsing algorithm.
+
+See https://w3c.github.io/webvtt/#file-parsing for documentation
+"""
+import re
+import string
+
+SPACE_CHARACTERS = [' ', '\t', '\n', '\f', '\r']
+SPACE_SPLIT_PATTERN = r"[{}]*".format(''.join(SPACE_CHARACTERS))
+DIGITS = string.digits
+
+class DictInit:
+ def __init__(self, **dict):
+ self.__dict__.update(dict)
+
+class VTTCue(DictInit): pass
+class VTTRegion(DictInit): pass
+class Stylesheet(DictInit): pass
+
+class W3CParser:
+ input = None
+ position = None
+
+ def collect_characters(self, condition):
+ result = ""
+ while self.position < len(self.input) and condition(self.input[self.position]):
+ result += self.input[self.position]
+ self.position += 1
+ return result
+
+ def skip_whitespace(self):
+ self.collect_characters(lambda c: c in SPACE_CHARACTERS)
+
+ def parse_percentage_string(self, input):
+ 'parse a percentage string'
+
+ # 1.
+ input = input
+
+ # 2.
+ if not re.match(r'^\d+(\.\d+)?%$', input):
+ return None
+
+ # 3.
+ percentage = float(input[:-1])
+
+ # 4.
+ if percentage < 0 or percentage > 100:
+ return None
+
+ # 5.
+ return percentage
+
+class VTTParser(W3CParser):
+ def __init__(self, input):
+ self.input = input
+ self.position = 0
+ self.seen_cue = False
+
+ self.text_tracks = []
+ self.stylesheets = []
+ self.regions = []
+ self.errors = []
+
+ def parse(self):
+ 'WebVTT parser algorithm'
+
+ # 1.
+ self.input = self.input.replace('\0', '\ufffd').replace('\r\n', '\n').replace('\r', '\n')
+
+ # 2.
+ self.position = 0
+
+ # 3.
+ self.seen_cue = False
+
+ # 4.
+ if len(self.input) < 6:
+ self.errors.append('input too small for webvtt')
+ return
+
+ # 5.
+ if len(self.input) == 6 and self.input != 'WEBVTT':
+ self.errors.append('invalid webvtt header')
+ return
+
+ # 6.
+ if len(self.input) > 6:
+ if not (self.input[0:6] == 'WEBVTT' and self.input[6] in ['\u0020', '\u0009', '\u000A']):
+ self.errors.append('invalid webvtt header')
+ return
+
+ # 7.
+ self.collect_characters(lambda c: c != '\n')
+
+ # 8.
+ if self.position >= len(self.input):
+ return
+
+ # 9.
+ if self.input[self.position] == '\n':
+ self.position += 1
+
+ # 10.
+ if self.position >= len(self.input):
+ return
+
+ # 11.
+ if self.input[self.position] != '\n':
+ self.collect_block(in_header = True)
+ else:
+ self.position += 1
+
+ # 12.
+ self.collect_characters(lambda c: c == '\n')
+
+ # 13.
+ self.regions = []
+
+ # 14.
+ while self.position < len(self.input):
+ # 1.
+ block = self.collect_block()
+
+ # 2.
+ if isinstance(block, VTTCue):
+ self.text_tracks.append(block)
+
+ # 3.
+ elif isinstance(block, Stylesheet):
+ self.stylesheets.append(block)
+
+ # 4.
+ elif isinstance(block, VTTRegion):
+ self.regions.append(block)
+
+ # 5.
+ self.collect_characters(lambda c: c == '\n')
+
+ # 15.
+ return
+
+ def collect_block(self, in_header = False):
+ 'collect a WebVTT block'
+
+ # 1. (done by class)
+
+ line_count = 0 # 2.
+ previous_position = self.position # 3.
+ line = "" # 4.
+ buffer = "" # 5.
+ seen_eof = False # 6.
+ seen_arrow = False # 7.
+ cue = None # 8.
+ stylesheet = None # 9.
+ region = None # 10.
+
+ # 11.
+ while True:
+ # 1.
+ line = self.collect_characters(lambda c: c != '\n')
+
+ # 2.
+ line_count += 1
+
+ # 3.
+ if self.position >= len(self.input):
+ seen_eof = True
+ else:
+ self.position += 1
+
+ # 4.
+ if '-->' in line:
+ # 1.
+ if not in_header and (line_count == 1 or line_count == 2 and not seen_arrow):
+ # 1.
+ seen_arrow = True
+
+ # 2.
+ previous_position = self.position
+
+ # 3.
+ cue = VTTCue(
+ id = buffer,
+ pause_on_exit = False,
+ region = None,
+ writing_direction = 'horizontal',
+ snap_to_lines = True,
+ line = 'auto',
+ line_alignment = 'start alignment',
+ position = 'auto',
+ position_alignment = 'auto',
+ cue_size = 100,
+ text_alignment = 'center',
+ text = '',
+ )
+
+ # 4.
+ if not VTTCueParser(self, line, cue).collect_cue_timings_and_settings():
+ cue = None
+ else:
+ buffer = ''
+ self.seen_cue = True # DIFFERENCE
+
+ else:
+ self.errors.append('invalid webvtt cue block')
+ self.position = previous_position
+ break
+
+ # 5.
+ elif line == '':
+ break
+
+ # 6.
+ else:
+ # 1.
+ if not in_header and line_count == 2:
+ # 1.
+ if not self.seen_cue and re.match(r'^STYLE\s*$', buffer):
+ stylesheet = Stylesheet(
+ location = None,
+ parent = None,
+ owner_node = None,
+ owner_rule = None,
+ media = None,
+ title = None,
+ alternate = False,
+ origin_clean = True,
+ source = None,
+ )
+ buffer = ''
+ # 2.
+ elif not self.seen_cue and re.match(r'^REGION\s*$', buffer):
+ region = VTTRegion(
+ id = '',
+ width = 100,
+ lines = 3,
+ anchor_point = (0, 100),
+ viewport_anchor_point = (0, 100),
+ scroll_value = None,
+ )
+ buffer = ''
+
+ # 2.
+ if buffer != '':
+ buffer += '\n'
+
+ # 3.
+ buffer += line
+
+ # 4.
+ previous_position = self.position
+
+ # 7.
+ if seen_eof:
+ break
+
+ # 12.
+ if cue is not None:
+ cue.text = buffer
+ return cue
+
+ # 13.
+ elif stylesheet is not None:
+ stylesheet.source = buffer
+ return stylesheet
+
+ # 14.
+ elif region is not None:
+ self.collect_region_settings(region, buffer)
+ return region
+
+ # 15.
+ return None
+
+ def collect_region_settings(self, region, input):
+ 'collect WebVTT region settings'
+
+ # 1.
+ settings = re.split(SPACE_SPLIT_PATTERN, input)
+
+ # 2.
+ for setting in settings:
+ # 1.
+ if ':' not in setting:
+ continue
+
+ index = setting.index(':')
+ if index in [0, len(setting) - 1]:
+ continue
+
+ # 2.
+ name = setting[:index]
+
+ # 3.
+ value = setting[index + 1:]
+
+ # 4.
+ if name == "id":
+ region.id = value
+
+ elif name == "width":
+ percentage = self.parse_percentage_string(value)
+ if percentage is not None:
+ region.width = percentage
+
+ elif name == "lines":
+ # 1.
+ if not re.match(r'^\d+$', value):
+ continue
+
+ # 2.
+ number = int(value)
+
+ # 3.
+ region.lines = number
+
+ elif name == "regionanchor":
+ # 1.
+ if ',' not in value:
+ continue
+
+ #. 2.
+ index = value.index(',')
+ anchorX = value[:index]
+
+ # 3.
+ anchorY = value[index + 1:]
+
+ # 4.
+ percentageX = self.parse_percentage_string(anchorX)
+ percentageY = self.parse_percentage_string(anchorY)
+ if None in [percentageX, percentageY]:
+ continue
+
+ # 5.
+ region.anchor_point = (percentageX, percentageY)
+
+ elif name == "viewportanchor":
+ # 1.
+ if ',' not in value:
+ continue
+
+ #. 2.
+ index = value.index(',')
+ viewportanchorX = value[:index]
+
+ # 3.
+ viewportanchorY = value[index + 1:]
+
+ # 4.
+ percentageX = self.parse_percentage_string(viewportanchorX)
+ percentageY = self.parse_percentage_string(viewportanchorY)
+ if None in [percentageX, percentageY]:
+ continue
+
+ # 5.
+ region.viewport_anchor_point = (percentageX, percentageY)
+
+ elif name == "scroll":
+ # 1.
+ if value == "up":
+ region.scroll_value = "up"
+
+ # 5.
+ continue
+
+
+class VTTCueParser(W3CParser):
+ def __init__(self, parent, input, cue):
+ self.parent = parent
+ self.errors = self.parent.errors
+ self.input = input
+ self.position = 0
+ self.cue = cue
+
+ def collect_cue_timings_and_settings(self):
+ 'collect WebVTT cue timings and settings'
+
+ # 1. (handled by class)
+
+ # 2.
+ self.position = 0
+
+ # 3.
+ self.skip_whitespace()
+
+ # 4.
+ timestamp = self.collect_timestamp()
+ if timestamp is None:
+ self.errors.append('invalid start time for VTTCue')
+ return False
+ self.cue.start_time = timestamp
+
+ # 5.
+ self.skip_whitespace()
+
+ # 6.
+ if self.input[self.position] != '-':
+ return False
+ self.position += 1
+
+ # 7.
+ if self.input[self.position] != '-':
+ return False
+ self.position += 1
+
+ # 8.
+ if self.input[self.position] != '>':
+ return False
+ self.position += 1
+
+ # 9.
+ self.skip_whitespace()
+
+ # 10.
+ timestamp = self.collect_timestamp()
+ if timestamp is None:
+ self.errors.append('invalid end time for VTTCue')
+ return False
+ self.cue.end_time = timestamp
+
+ # 11.
+ remainder = self.input[self.position:]
+
+ # 12.
+ self.parse_settings(remainder)
+
+ # Extra
+ return True
+
+ def parse_settings(self, input):
+ 'parse the WebVTT cue settings'
+
+ # 1.
+
+ settings = re.split(SPACE_SPLIT_PATTERN, input)
+
+ # 2.
+ for setting in settings:
+ # 1.
+ if ':' not in setting:
+ continue
+
+ index = setting.index(':')
+ if index in [0, len(setting) - 1]:
+ continue
+
+ # 2.
+ name = setting[:index]
+
+ # 3.
+ value = setting[index + 1:]
+
+ # 4.
+ if name == 'region':
+ # 1.
+ last_regions = (region for region in reversed(self.parent.regions) if region.id == value)
+ self.cue.region = next(last_regions, None)
+
+ elif name == 'vertical':
+ # 1. and 2.
+ if value in ['rl', 'lr']:
+ self.cue.writing_direction = value
+
+ elif name == 'line':
+ # 1.
+ if ',' in value:
+ index = value.index(',')
+ linepos = value[:index]
+ linealign = value[index + 1:]
+
+ # 2.
+ else:
+ linepos = value
+ linealign = None
+
+ # 3.
+ if not re.search(r'\d', linepos):
+ continue
+
+ # 4.
+ if linepos[-1] == '%':
+ number = self.parse_percentage_string(linepos)
+ if number is None:
+ continue
+ else:
+ # 1.
+ if not re.match(r'^[-\.\d]*$', linepos):
+ continue
+
+ # 2.
+ if '-' in linepos[1:]:
+ continue
+
+ # 3.
+ if linepos.count('.') > 1:
+ continue
+
+ # 4.
+ if '.' in linepos:
+ if not re.search(r'\d\.\d', linepos):
+ continue
+
+ # 5.
+ number = float(linepos)
+
+ # 5.
+ if linealign == "start":
+ self.cue.line_alignment = 'start'
+
+ # 6.
+ elif linealign == "center":
+ self.cue.line_alignment = 'center'
+
+ # 7.
+ elif linealign == "end":
+ self.cue.line_alignment = 'end'
+
+ # 8.
+ elif linealign != None:
+ continue
+
+ # 9.
+ self.cue.line = number
+
+ # 10.
+ if linepos[-1] == '%':
+ self.cue.snap_to_lines = False
+ else:
+ self.cue.snap_to_lines = True
+
+ elif name == 'position':
+ # 1.
+ if ',' in value:
+ index = value.index(',')
+ colpos = value[:index]
+ colalign = value[index + 1:]
+
+ # 2.
+ else:
+ colpos = value
+ colalign = None
+
+ # 3.
+ number = self.parse_percentage_string(colpos)
+ if number is None:
+ continue
+
+ # 4.
+ if colalign == "line-left":
+ self.cue.line_alignment = 'line-left'
+
+ # 5.
+ elif colalign == "center":
+ self.cue.line_alignment = 'center'
+
+ # 6.
+ elif colalign == "line-right":
+ self.cue.line_alignment = 'line-right'
+
+ # 7.
+ elif colalign != None:
+ continue
+
+ # 8.
+ self.cue.position = number
+
+ elif name == 'size':
+ # 1.
+ number = self.parse_percentage_string(value)
+ if number is None:
+ continue
+
+ # 2.
+ self.cue.cue_size = number
+
+ elif name == 'align':
+ # 1.
+ if value == 'start':
+ self.cue.text_alignment = 'start'
+
+ # 2.
+ if value == 'center':
+ self.cue.text_alignment = 'center'
+
+ # 3.
+ if value == 'end':
+ self.cue.text_alignment = 'end'
+
+ # 4.
+ if value == 'left':
+ self.cue.text_alignment = 'left'
+
+ # 5.
+ if value == 'right':
+ self.cue.text_alignment = 'right'
+
+ # 5.
+ continue
+
+ def collect_timestamp(self):
+ 'collect a WebVTT timestamp'
+
+ # 1. (handled by class)
+
+ # 2.
+ most_significant_units = 'minutes'
+
+ # 3.
+ if self.position >= len(self.input):
+ return None
+
+ # 4.
+ if self.input[self.position] not in DIGITS:
+ return None
+
+ # 5.
+ string = self.collect_characters(lambda c: c in DIGITS)
+
+ # 6.
+ value_1 = int(string)
+
+ # 7.
+ if len(string) != 2 or value_1 > 59:
+ most_significant_units = 'hours'
+
+ # 8.
+ if self.position >= len(self.input) or self.input[self.position] != ':':
+ return None
+ self.position += 1
+
+ # 9.
+ string = self.collect_characters(lambda c: c in DIGITS)
+
+ # 10.
+ if len(string) != 2:
+ return None
+
+ # 11.
+ value_2 = int(string)
+
+ # 12.
+ if most_significant_units == 'hours' or self.position < len(self.input) and self.input[self.position] == ':':
+ # 1.
+ if self.position >= len(self.input) or self.input[self.position] != ':':
+ return None
+ self.position += 1
+
+ # 2.
+ string = self.collect_characters(lambda c: c in DIGITS)
+
+ # 3.
+ if len(string) != 2:
+ return None
+
+ # 4.
+ value_3 = int(string)
+ else:
+ value_3 = value_2
+ value_2 = value_1
+ value_1 = 0
+
+ # 13.
+ if self.position >= len(self.input) or self.input[self.position] != '.':
+ return None
+ self.position += 1
+
+ # 14.
+ string = self.collect_characters(lambda c: c in DIGITS)
+
+ # 15.
+ if len(string) != 3:
+ return None
+
+ # 16.
+ value_4 = int(string)
+
+ # 17.
+ if value_2 >= 59 or value_3 >= 59:
+ return None
+
+ # 18.
+ result = value_1 * 60 * 60 + value_2 * 60 + value_3 + value_4 / 1000
+
+ # 19.
+ return result
+
+
+def main(argv):
+ files = [open(path, 'r') for path in argv[1:]]
+
+ try:
+ for file in files:
+ parser = VTTParser(file.read())
+ parser.parse()
+
+ print("Results: {}".format(file))
+ print(" Cues: {}".format(parser.text_tracks))
+ print(" StyleSheets: {}".format(parser.stylesheets))
+ print(" Regions: {}".format(parser.regions))
+ print(" Errors: {}".format(parser.errors))
+ finally:
+ for file in files:
+ file.close()
+
+if __name__ == '__main__':
+ import sys
+ main(sys.argv);
diff --git a/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/spec_report.py b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/spec_report.py
new file mode 100644
index 0000000000..beb140eb8c
--- /dev/null
+++ b/testing/web-platform/tests/webvtt/parsing/file-parsing/tools/spec_report.py
@@ -0,0 +1,99 @@
+import os
+import sys
+import glob
+import html
+import fnmatch
+from os import path
+
+import coverage
+
+OUTPUT_TEMPLATE = """
+<!DOCTYPE html>
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ <title>Spec Coverage</title>
+ <link rel="stylesheet" href="style.css" type="text/css">
+ <style>
+ .covered {
+ }
+
+ .missed {
+ background-color: lightcoral;
+ }
+ code {
+ margin: 0;
+ padding: 0;
+ display:block;
+ white-space:pre-wrap;
+ }
+ </style>
+</head>
+<body>
+ %head
+ <div><pre>
+ %body
+ </pre></div>
+</body>
+</html>
+"""
+
+LINE_TEMPLATE = "<code class=\"%class\">%lineno| %source</code>"
+
+def write_report(data, source_file, output_file):
+ module_name, executable_lines, excluded_lines, missing_lines, _ = data
+ missing_lines = set(missing_lines)
+
+ with open(output_file, "w") as output, open(source_file, "r") as source:
+ lines = source.readlines()
+
+ file_report = []
+ padding = len(str(len(lines)))
+
+ for index, line in enumerate(lines):
+ line = line[0:-1]
+ lineno = index + 1
+ line_number = str(lineno).rjust(padding)
+
+ covered = lineno not in missing_lines
+ line_class = 'covered' if covered else 'missed'
+
+ formatted_line = (LINE_TEMPLATE.replace('%class', line_class)
+ .replace('%lineno', line_number)
+ .replace('%source', html.escape(line)))
+ file_report.append(formatted_line)
+
+ report_body = ''.join(file_report)
+
+ report_header = ''
+
+ report = (OUTPUT_TEMPLATE.replace('%head', report_header)
+ .replace('%body', report_body))
+ output.write(report)
+
+def main(argv):
+ parsing_path = path.normpath(path.join(path.dirname(__file__), ".."))
+
+ files = argv[1:]
+ if not files:
+ files = [os.path.join(root, file) for root, _, files in os.walk(parsing_path)
+ for file in fnmatch.filter(files, '*.vtt')]
+
+ cov = coverage.Coverage()
+ cov.start()
+
+ for file_path in files:
+ with open(file_path, "r") as file:
+ source = file.read()
+
+ import parser
+ p = parser.VTTParser(source)
+ p.parse()
+
+ cov.stop()
+
+ data = cov.analysis2(parser.__file__)
+ write_report(data, parser.__file__, "report.html")
+
+if __name__ == '__main__':
+ main(sys.argv)