URLPattern: Refactor WPT tests to match URL WPT test structure.

The URL API tests use a data file that is loaded in the the test runner:

https://github.com/web-platform-tests/wpt/blob/master/url/resources/urltestdata.json
https://github.com/web-platform-tests/wpt/blob/master/url/url-constructor.html

Purportedly this helps with other platforms that may want to implement
the API maintain test parity by writing their own test runner around the
data file.

This seems like a good idea since we will likely need to test a polyfill
in the future and it could also be used if nodejs adopts the API.

This CL is roughly a direct translation of the current test cases.

Bug: 1141510
Change-Id: I6cf7dea233fed7751306822738fe86ec3464368e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2567178
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834725}
diff --git a/urlpattern/input.https.any.js b/urlpattern/input.https.any.js
deleted file mode 100644
index 71a8fb2..0000000
--- a/urlpattern/input.https.any.js
+++ /dev/null
@@ -1,88 +0,0 @@
-// META: global=window,worker
-// META: script=resources/utils.js
-
-// This file attempts to test the different ways you can pass input values
-// to be matched; e.g. as strings vs structured component parts.
-
-test(() => {
-  runTest({ pathname: '/foo/bar' }, [
-    { input: "https://example.com/foo/bar", expected: true },
-    { input: "https://example.com/foo/bar/baz", expected: false },
-  ]);
-}, "init single component, input string");
-
-test(() => {
-  runTest({ pathname: '/foo/bar' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-  ]);
-}, "init single component, input single component");
-
-test(() => {
-  runTest({ pathname: '/foo/bar' }, [
-    { input: { hostname: 'example.com', pathname: '/foo/bar' },
-      expected: true },
-    { input: { hostname: 'example.com', pathname: '/foo/bar/baz' },
-      expected: false },
-  ]);
-}, "init single component, input two components");
-
-test(() => {
-  runTest({ pathname: '/foo/bar' }, [
-    { input: { pathname: '/foo/bar', baseURL: 'https://example.com' },
-      expected: true },
-    { input: { pathname: '/foo/bar/baz', baseURL: 'https://example.com' },
-      expected: false },
-  ]);
-}, "init single component, input baseURL and single component");
-
-test(() => {
-  runTest({ pathname: '/foo/bar', baseURL: 'https://example.com?query#hash' }, [
-    { input: "https://example.com/foo/bar", expected: true },
-    { input: "https://example.com/foo/bar/baz", expected: false },
-    { input: "https://example2.com/foo/bar", expected: false },
-    { input: "http://example.com/foo/bar", expected: false },
-  ]);
-}, "init baseURL and single component, input string");
-
-test(() => {
-  runTest({ pathname: '/foo/bar', baseURL: 'https://example.com?query#hash' }, [
-    { input: { pathname: '/foo/bar' }, expected: false },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-  ]);
-}, "init baseURL and single component, input single component");
-
-test(() => {
-  runTest({ pathname: '/foo/bar', baseURL: 'https://example.com?query#hash' }, [
-    { input: { hostname: 'example.com', pathname: '/foo/bar' },
-      expected: false },
-    { input: { hostname: 'example.com', pathname: '/foo/bar/baz' },
-      expected: false },
-    { input: { hostname: 'example2.com', pathname: '/foo/bar' },
-      expected: false },
-  ]);
-}, "init baseURL and single component, input two components");
-
-test(() => {
-  runTest({ pathname: '/foo/bar', baseURL: 'https://example.com?query#hash' }, [
-    { input: { protocol: 'https', hostname: 'example.com',
-               pathname: '/foo/bar' },
-      expected: true },
-    { input: { protocol: 'https', hostname: 'example.com',
-               pathname: '/foo/bar/baz' },
-      expected: false },
-  ]);
-}, "init single component, input three components");
-
-test(() => {
-  runTest({ pathname: '/foo/bar', baseURL: 'https://example.com?query#hash' }, [
-    { input: { pathname: '/foo/bar', baseURL: 'https://example.com' },
-      expected: true },
-    { input: { pathname: '/foo/bar/baz', baseURL: 'https://example.com' },
-      expected: false },
-    { input: { pathname: '/foo/bar', baseURL: 'https://example2.com' },
-      expected: false },
-    { input: { pathname: '/foo/bar', baseURL: 'http://example.com' },
-      expected: false },
-  ]);
-}, "init baseURL and single component, input baseURL and single component");
diff --git a/urlpattern/pathname.https.any.js b/urlpattern/pathname.https.any.js
deleted file mode 100644
index 5de41cc..0000000
--- a/urlpattern/pathname.https.any.js
+++ /dev/null
@@ -1,139 +0,0 @@
-// META: global=window,worker
-// META: script=resources/utils.js
-
-test(() => {
-  runTest({ pathname: '/foo/bar' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/ba' }, expected: false },
-    { input: { pathname: '/foo/bar/' }, expected: false },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-  ]);
-}, "fixed string");
-
-test(() => {
-  runTest({ pathname: '/foo/:bar' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/index.html' }, expected: true },
-    { input: { pathname: '/foo/bar/' }, expected: false },
-    { input: { pathname: '/foo/' }, expected: false },
-  ]);
-}, "named group");
-
-test(() => {
-  runTest({ pathname: '/foo/(.*)' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: true },
-    { input: { pathname: '/foo' }, expected: false },
-  ]);
-}, "regexp group");
-
-test(() => {
-  runTest({ pathname: '/foo/:bar(.*)' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: true },
-    { input: { pathname: '/foo' }, expected: false },
-  ]);
-}, "named regexp group");
-
-test(() => {
-  runTest({ pathname: '/foo/:bar?' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-  ]);
-}, "optional named group");
-
-test(() => {
-  runTest({ pathname: '/foo/:bar+' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo' }, expected: false },
-    { input: { pathname: '/foo/' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-  ]);
-}, "repeated named group");
-
-test(() => {
-  runTest({ pathname: '/foo/:bar*' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-  ]);
-}, "optional repeated named group");
-
-test(() => {
-  runTest({ pathname: '/foo/(.*)?' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: true },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/fo' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-  ]);
-}, "optional regexp group");
-
-test(() => {
-  runTest({ pathname: '/foo/(.*)+' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: true },
-    { input: { pathname: '/foo' }, expected: false },
-    { input: { pathname: '/fo' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-  ]);
-}, "repeated regexp group");
-
-test(() => {
-  runTest({ pathname: '/foo/(.*)*' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: true },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/fo' }, expected: false },
-    { input: { pathname: '/foobar' }, expected: false },
-  ]);
-}, "optional repeated regexp group");
-
-test(() => {
-  runTest({ pathname: '/foo{/bar}' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-    { input: { pathname: '/foo/' }, expected: false },
-    { input: { pathname: '/foo' }, expected: false },
-  ]);
-}, "group");
-
-test(() => {
-  runTest({ pathname: '/foo{/bar}?' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: false },
-  ]);
-}, "optional group");
-
-test(() => {
-  runTest({ pathname: '/foo{/bar}+' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-    { input: { pathname: '/foo' }, expected: false },
-    { input: { pathname: '/foo/' }, expected: false },
-  ]);
-}, "repeated group");
-
-test(() => {
-  runTest({ pathname: '/foo{/bar}*' }, [
-    { input: { pathname: '/foo/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/bar' }, expected: true },
-    { input: { pathname: '/foo/bar/baz' }, expected: false },
-    { input: { pathname: '/foo' }, expected: true },
-    { input: { pathname: '/foo/' }, expected: false },
-  ]);
-}, "repeated optional group");
diff --git a/urlpattern/resources/urlpatterntestdata.json b/urlpattern/resources/urlpatterntestdata.json
new file mode 100644
index 0000000..9bdf4d2
--- /dev/null
+++ b/urlpattern/resources/urlpatterntestdata.json
@@ -0,0 +1,455 @@
+[
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/ba" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/bar/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": "https://example.com/foo/bar",
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": "https://example.com/foo/bar/baz",
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "hostname": "example.com", "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "hostname": "example.com", "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/bar", "baseURL": "https://example.com" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar" },
+    "input": { "pathname": "/foo/bar/baz", "baseURL": "https://example.com" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "hostname": "example.com", "pathname": "/foo/bar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "protocol": "https", "hostname": "example.com",
+               "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "protocol": "https", "hostname": "example.com",
+               "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "protocol": "https", "hostname": "example.com",
+               "pathname": "/foo/bar", "search": "otherquery",
+               "hash": "otherhash" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": "https://example.com/foo/bar",
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": "https://example.com/foo/bar?otherquery#otherhash",
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": "https://example.com/foo/bar/baz",
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": "https://other.com/foo/bar",
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": "http://other.com/foo/bar",
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "pathname": "/foo/bar", "baseURL": "https://example.com" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "pathname": "/foo/bar/baz", "baseURL": "https://example.com" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "pathname": "/foo/bar", "baseURL": "https://other.com" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/bar",
+                 "baseURL": "https://example.com?query#hash" },
+    "input": { "pathname": "/foo/bar", "baseURL": "http://example.com" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar" },
+    "input": { "pathname": "/foo/index.html" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar" },
+    "input": { "pathname": "/foo/bar/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)" },
+    "input": { "pathname": "/foo/" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar(.*)" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar(.*)" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar(.*)" },
+    "input": { "pathname": "/foo/" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar(.*)" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar?" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar?" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar?" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar?" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar?" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar+" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar+" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar+" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar+" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar+" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar*" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar*" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar*" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar*" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/:bar*" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/foo/" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)?" },
+    "input": { "pathname": "/fo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/foo/" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)+" },
+    "input": { "pathname": "/fo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/foo/" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/foobar" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo/(.*)*" },
+    "input": { "pathname": "/fo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}?" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}?" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}?" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}?" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}+" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}+" },
+    "input": { "pathname": "/foo/bar/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}+" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}+" },
+    "input": { "pathname": "/foo" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}+" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}*" },
+    "input": { "pathname": "/foo/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}*" },
+    "input": { "pathname": "/foo/bar/bar" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}*" },
+    "input": { "pathname": "/foo/bar/baz" },
+    "expected": false
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}*" },
+    "input": { "pathname": "/foo" },
+    "expected": true
+  },
+  {
+    "pattern": { "pathname": "/foo{/bar}*" },
+    "input": { "pathname": "/foo/" },
+    "expected": false
+  }
+]
diff --git a/urlpattern/resources/utils.js b/urlpattern/resources/utils.js
deleted file mode 100644
index 9132a52..0000000
--- a/urlpattern/resources/utils.js
+++ /dev/null
@@ -1,7 +0,0 @@
-function runTest(pattern, expected_list) {
-  const p = new URLPattern(pattern);
-  for (let entry of expected_list) {
-    assert_equals(p.test(entry.input), entry.expected,
-                  `input: ${JSON.stringify(entry.input)}`);
-  }
-}
diff --git a/urlpattern/urlpattern.https.any.js b/urlpattern/urlpattern.https.any.js
new file mode 100644
index 0000000..212352d
--- /dev/null
+++ b/urlpattern/urlpattern.https.any.js
@@ -0,0 +1,16 @@
+// META: global=window,worker
+
+function runTests(data) {
+  for (let entry of data) {
+    test(function() {
+      const pattern = new URLPattern(entry.pattern);
+      assert_equals(pattern.test(entry.input), entry.expected);
+    }, `Pattern: ${JSON.stringify(entry.pattern)} Input: ${JSON.stringify(entry.input)}`);
+  }
+}
+
+promise_test(async function() {
+  const response = await fetch('resources/urlpatterntestdata.json');
+  const data = await response.json();
+  runTests(data);
+}, 'Loading data...');