summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2017-01-28 17:23:47 +0800
committerJames M Snell <jasnell@gmail.com>2017-01-30 10:19:37 -0800
commit147d2a6419cb1e1dae5f9c2abf04cc21c52e0e0e (patch)
tree8b7c671aca9f23639a911f2f39976a8464136c4c
parent49e5f61ef6b0d2800db19b0ca758ec04e457bf45 (diff)
downloadandroid-node-v8-147d2a6419cb1e1dae5f9c2abf04cc21c52e0e0e.tar.gz
android-node-v8-147d2a6419cb1e1dae5f9c2abf04cc21c52e0e0e.tar.bz2
android-node-v8-147d2a6419cb1e1dae5f9c2abf04cc21c52e0e0e.zip
url, test: break up test-url.js
PR-URL: https://github.com/nodejs/node/pull/11049 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
-rw-r--r--test/parallel/test-url-format-invalid-input.js20
-rw-r--r--test/parallel/test-url-format.js252
-rw-r--r--test/parallel/test-url-parse-format.js925
-rw-r--r--test/parallel/test-url-parse-invalid-input.js18
-rw-r--r--test/parallel/test-url-parse-query.js90
-rw-r--r--test/parallel/test-url-relative.js429
-rw-r--r--test/parallel/test-url.js1714
7 files changed, 1734 insertions, 1714 deletions
diff --git a/test/parallel/test-url-format-invalid-input.js b/test/parallel/test-url-format-invalid-input.js
new file mode 100644
index 0000000000..6361e56f40
--- /dev/null
+++ b/test/parallel/test-url-format-invalid-input.js
@@ -0,0 +1,20 @@
+/* eslint-disable max-len */
+'use strict';
+require('../common');
+const assert = require('assert');
+const url = require('url');
+
+// https://github.com/nodejs/node/pull/1036
+const throws = [
+ undefined,
+ null,
+ true,
+ false,
+ 0,
+ function() {}
+];
+for (let i = 0; i < throws.length; i++) {
+ assert.throws(function() { url.format(throws[i]); }, TypeError);
+}
+assert.strictEqual(url.format(''), '');
+assert.strictEqual(url.format({}), '');
diff --git a/test/parallel/test-url-format.js b/test/parallel/test-url-format.js
new file mode 100644
index 0000000000..fa4805bc8a
--- /dev/null
+++ b/test/parallel/test-url-format.js
@@ -0,0 +1,252 @@
+/* eslint-disable max-len */
+'use strict';
+require('../common');
+const assert = require('assert');
+const url = require('url');
+
+// some extra formatting tests, just to verify
+// that it'll format slightly wonky content to a valid url.
+const formatTests = {
+ 'http://example.com?': {
+ href: 'http://example.com/?',
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ search: '?',
+ query: {},
+ pathname: '/'
+ },
+ 'http://example.com?foo=bar#frag': {
+ href: 'http://example.com/?foo=bar#frag',
+ protocol: 'http:',
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?foo=bar',
+ query: 'foo=bar',
+ pathname: '/'
+ },
+ 'http://example.com?foo=@bar#frag': {
+ href: 'http://example.com/?foo=@bar#frag',
+ protocol: 'http:',
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?foo=@bar',
+ query: 'foo=@bar',
+ pathname: '/'
+ },
+ 'http://example.com?foo=/bar/#frag': {
+ href: 'http://example.com/?foo=/bar/#frag',
+ protocol: 'http:',
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?foo=/bar/',
+ query: 'foo=/bar/',
+ pathname: '/'
+ },
+ 'http://example.com?foo=?bar/#frag': {
+ href: 'http://example.com/?foo=?bar/#frag',
+ protocol: 'http:',
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?foo=?bar/',
+ query: 'foo=?bar/',
+ pathname: '/'
+ },
+ 'http://example.com#frag=?bar/#frag': {
+ href: 'http://example.com/#frag=?bar/#frag',
+ protocol: 'http:',
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag=?bar/#frag',
+ pathname: '/'
+ },
+ 'http://google.com" onload="alert(42)/': {
+ href: 'http://google.com/%22%20onload=%22alert(42)/',
+ protocol: 'http:',
+ host: 'google.com',
+ pathname: '/%22%20onload=%22alert(42)/'
+ },
+ 'http://a.com/a/b/c?s#h': {
+ href: 'http://a.com/a/b/c?s#h',
+ protocol: 'http',
+ host: 'a.com',
+ pathname: 'a/b/c',
+ hash: 'h',
+ search: 's'
+ },
+ 'xmpp:isaacschlueter@jabber.org': {
+ href: 'xmpp:isaacschlueter@jabber.org',
+ protocol: 'xmpp:',
+ host: 'jabber.org',
+ auth: 'isaacschlueter',
+ hostname: 'jabber.org'
+ },
+ 'http://atpass:foo%40bar@127.0.0.1/': {
+ href: 'http://atpass:foo%40bar@127.0.0.1/',
+ auth: 'atpass:foo@bar',
+ hostname: '127.0.0.1',
+ protocol: 'http:',
+ pathname: '/'
+ },
+ 'http://atslash%2F%40:%2F%40@foo/': {
+ href: 'http://atslash%2F%40:%2F%40@foo/',
+ auth: 'atslash/@:/@',
+ hostname: 'foo',
+ protocol: 'http:',
+ pathname: '/'
+ },
+ 'svn+ssh://foo/bar': {
+ href: 'svn+ssh://foo/bar',
+ hostname: 'foo',
+ protocol: 'svn+ssh:',
+ pathname: '/bar',
+ slashes: true
+ },
+ 'dash-test://foo/bar': {
+ href: 'dash-test://foo/bar',
+ hostname: 'foo',
+ protocol: 'dash-test:',
+ pathname: '/bar',
+ slashes: true
+ },
+ 'dash-test:foo/bar': {
+ href: 'dash-test:foo/bar',
+ hostname: 'foo',
+ protocol: 'dash-test:',
+ pathname: '/bar'
+ },
+ 'dot.test://foo/bar': {
+ href: 'dot.test://foo/bar',
+ hostname: 'foo',
+ protocol: 'dot.test:',
+ pathname: '/bar',
+ slashes: true
+ },
+ 'dot.test:foo/bar': {
+ href: 'dot.test:foo/bar',
+ hostname: 'foo',
+ protocol: 'dot.test:',
+ pathname: '/bar'
+ },
+ // ipv6 support
+ 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
+ href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
+ protocol: 'coap:',
+ auth: 'u:p',
+ hostname: '::1',
+ port: '61616',
+ pathname: '/.well-known/r',
+ search: 'n=Temperature'
+ },
+ 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
+ href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
+ protocol: 'coap',
+ host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
+ pathname: '/s/stopButton'
+ },
+
+ // encode context-specific delimiters in path and query, but do not touch
+ // other non-delimiter chars like `%`.
+ // <https://github.com/joyent/node/issues/4082>
+
+ // `#`,`?` in path
+ '/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
+ href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
+ pathname: '/path/to/%#?+=&.txt',
+ query: {
+ foo: 'theA1'
+ },
+ hash: '#bar'
+ },
+
+ // `#`,`?` in path + `#` in query
+ '/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
+ href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
+ pathname: '/path/to/%#?+=&.txt',
+ query: {
+ foo: 'the#1'
+ },
+ hash: '#bar'
+ },
+
+ // `?` and `#` in path and search
+ 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
+ href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
+ protocol: 'http:',
+ hostname: 'ex.com',
+ hash: '#frag',
+ search: '?abc=the#1?&foo=bar',
+ pathname: '/foo?100%m#r',
+ },
+
+ // `?` and `#` in search only
+ 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
+ href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
+ protocol: 'http:',
+ hostname: 'ex.com',
+ hash: '#frag',
+ search: '?abc=the#1?&foo=bar',
+ pathname: '/fooA100%mBr',
+ },
+
+ // multiple `#` in search
+ 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': {
+ href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag',
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?foo=bar#1#2#3&abc=#4##5',
+ query: {},
+ pathname: '/'
+ },
+
+ // more than 255 characters in hostname which exceeds the limit
+ [`http://${'a'.repeat(255)}.com/node`]: {
+ href: 'http:///node',
+ protocol: 'http:',
+ slashes: true,
+ host: '',
+ hostname: '',
+ pathname: '/node',
+ path: '/node'
+ },
+
+ // greater than or equal to 63 characters after `.` in hostname
+ [`http://www.${'z'.repeat(63)}example.com/node`]: {
+ href: `http://www.${'z'.repeat(63)}example.com/node`,
+ protocol: 'http:',
+ slashes: true,
+ host: `www.${'z'.repeat(63)}example.com`,
+ hostname: `www.${'z'.repeat(63)}example.com`,
+ pathname: '/node',
+ path: '/node'
+ },
+
+ // https://github.com/nodejs/node/issues/3361
+ 'file:///home/user': {
+ href: 'file:///home/user',
+ protocol: 'file',
+ pathname: '/home/user',
+ path: '/home/user'
+ }
+};
+for (const u in formatTests) {
+ const expect = formatTests[u].href;
+ delete formatTests[u].href;
+ const actual = url.format(u);
+ const actualObj = url.format(formatTests[u]);
+ assert.strictEqual(actual, expect,
+ 'wonky format(' + u + ') == ' + expect +
+ '\nactual:' + actual);
+ assert.strictEqual(actualObj, expect,
+ 'wonky format(' + JSON.stringify(formatTests[u]) +
+ ') == ' + expect +
+ '\nactual: ' + actualObj);
+}
diff --git a/test/parallel/test-url-parse-format.js b/test/parallel/test-url-parse-format.js
new file mode 100644
index 0000000000..f75f979b29
--- /dev/null
+++ b/test/parallel/test-url-parse-format.js
@@ -0,0 +1,925 @@
+/* eslint-disable max-len */
+'use strict';
+require('../common');
+const assert = require('assert');
+const inspect = require('util').inspect;
+
+const url = require('url');
+
+// URLs to parse, and expected data
+// { url : parsed }
+const parseTests = {
+ '//some_path': {
+ href: '//some_path',
+ pathname: '//some_path',
+ path: '//some_path'
+ },
+
+ 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'evil-phisher',
+ hostname: 'evil-phisher',
+ pathname: '/foo.html',
+ path: '/foo.html',
+ hash: '#h%5Ca%5Cs%5Ch',
+ href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch'
+ },
+
+ 'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'evil-phisher',
+ hostname: 'evil-phisher',
+ pathname: '/foo.html',
+ search: '?json=%22%5C%22foo%5C%22%22',
+ query: 'json=%22%5C%22foo%5C%22%22',
+ path: '/foo.html?json=%22%5C%22foo%5C%22%22',
+ hash: '#h%5Ca%5Cs%5Ch',
+ href: 'http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch'
+ },
+
+ 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'evil-phisher',
+ hostname: 'evil-phisher',
+ pathname: '/foo.html',
+ path: '/foo.html',
+ hash: '#h%5Ca%5Cs%5Ch?blarg',
+ href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg'
+ },
+
+
+ 'http:\\\\evil-phisher\\foo.html': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'evil-phisher',
+ hostname: 'evil-phisher',
+ pathname: '/foo.html',
+ path: '/foo.html',
+ href: 'http://evil-phisher/foo.html'
+ },
+
+ 'HTTP://www.example.com/': {
+ href: 'http://www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'HTTP://www.example.com': {
+ href: 'http://www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://www.ExAmPlE.com/': {
+ href: 'http://www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://user:pw@www.ExAmPlE.com/': {
+ href: 'http://user:pw@www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pw',
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://USER:PW@www.ExAmPlE.com/': {
+ href: 'http://USER:PW@www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ auth: 'USER:PW',
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://user@www.example.com/': {
+ href: 'http://user@www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user',
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://user%3Apw@www.example.com/': {
+ href: 'http://user:pw@www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pw',
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://x.com/path?that\'s#all, folks': {
+ href: 'http://x.com/path?that%27s#all,%20folks',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x.com',
+ hostname: 'x.com',
+ search: '?that%27s',
+ query: 'that%27s',
+ pathname: '/path',
+ hash: '#all,%20folks',
+ path: '/path?that%27s'
+ },
+
+ 'HTTP://X.COM/Y': {
+ href: 'http://x.com/Y',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x.com',
+ hostname: 'x.com',
+ pathname: '/Y',
+ path: '/Y'
+ },
+
+ // whitespace in the front
+ ' http://www.example.com/': {
+ href: 'http://www.example.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.example.com',
+ hostname: 'www.example.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ // + not an invalid host character
+ // per https://url.spec.whatwg.org/#host-parsing
+ 'http://x.y.com+a/b/c': {
+ href: 'http://x.y.com+a/b/c',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x.y.com+a',
+ hostname: 'x.y.com+a',
+ pathname: '/b/c',
+ path: '/b/c'
+ },
+
+ // an unexpected invalid char in the hostname.
+ 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i': {
+ href: 'http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x.y.com',
+ hostname: 'x.y.com',
+ pathname: ';a/b/c',
+ search: '?d=e',
+ query: 'd=e',
+ hash: '#f%20g%3Ch%3Ei',
+ path: ';a/b/c?d=e'
+ },
+
+ // make sure that we don't accidentally lcast the path parts.
+ 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i': {
+ href: 'http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x.y.com',
+ hostname: 'x.y.com',
+ pathname: ';A/b/c',
+ search: '?d=e',
+ query: 'd=e',
+ hash: '#f%20g%3Ch%3Ei',
+ path: ';A/b/c?d=e'
+ },
+
+ 'http://x...y...#p': {
+ href: 'http://x...y.../#p',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x...y...',
+ hostname: 'x...y...',
+ hash: '#p',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://x/p/"quoted"': {
+ href: 'http://x/p/%22quoted%22',
+ protocol: 'http:',
+ slashes: true,
+ host: 'x',
+ hostname: 'x',
+ pathname: '/p/%22quoted%22',
+ path: '/p/%22quoted%22'
+ },
+
+ '<http://goo.corn/bread> Is a URL!': {
+ href: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
+ pathname: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
+ path: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!'
+ },
+
+ 'http://www.narwhaljs.org/blog/categories?id=news': {
+ href: 'http://www.narwhaljs.org/blog/categories?id=news',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.narwhaljs.org',
+ hostname: 'www.narwhaljs.org',
+ search: '?id=news',
+ query: 'id=news',
+ pathname: '/blog/categories',
+ path: '/blog/categories?id=news'
+ },
+
+ 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=': {
+ href: 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
+ protocol: 'http:',
+ slashes: true,
+ host: 'mt0.google.com',
+ hostname: 'mt0.google.com',
+ pathname: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
+ path: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
+ },
+
+ 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
+ href: 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api' +
+ '&x=2&y=2&z=3&s=',
+ protocol: 'http:',
+ slashes: true,
+ host: 'mt0.google.com',
+ hostname: 'mt0.google.com',
+ search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
+ query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
+ pathname: '/vt/lyrs=m@114',
+ path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
+ },
+
+ 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
+ href: 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' +
+ '&hl=en&src=api&x=2&y=2&z=3&s=',
+ protocol: 'http:',
+ slashes: true,
+ host: 'mt0.google.com',
+ auth: 'user:pass',
+ hostname: 'mt0.google.com',
+ search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
+ query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
+ pathname: '/vt/lyrs=m@114',
+ path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
+ },
+
+ 'file:///etc/passwd': {
+ href: 'file:///etc/passwd',
+ slashes: true,
+ protocol: 'file:',
+ pathname: '/etc/passwd',
+ hostname: '',
+ host: '',
+ path: '/etc/passwd'
+ },
+
+ 'file://localhost/etc/passwd': {
+ href: 'file://localhost/etc/passwd',
+ protocol: 'file:',
+ slashes: true,
+ pathname: '/etc/passwd',
+ hostname: 'localhost',
+ host: 'localhost',
+ path: '/etc/passwd'
+ },
+
+ 'file://foo/etc/passwd': {
+ href: 'file://foo/etc/passwd',
+ protocol: 'file:',
+ slashes: true,
+ pathname: '/etc/passwd',
+ hostname: 'foo',
+ host: 'foo',
+ path: '/etc/passwd'
+ },
+
+ 'file:///etc/node/': {
+ href: 'file:///etc/node/',
+ slashes: true,
+ protocol: 'file:',
+ pathname: '/etc/node/',
+ hostname: '',
+ host: '',
+ path: '/etc/node/'
+ },
+
+ 'file://localhost/etc/node/': {
+ href: 'file://localhost/etc/node/',
+ protocol: 'file:',
+ slashes: true,
+ pathname: '/etc/node/',
+ hostname: 'localhost',
+ host: 'localhost',
+ path: '/etc/node/'
+ },
+
+ 'file://foo/etc/node/': {
+ href: 'file://foo/etc/node/',
+ protocol: 'file:',
+ slashes: true,
+ pathname: '/etc/node/',
+ hostname: 'foo',
+ host: 'foo',
+ path: '/etc/node/'
+ },
+
+ 'http:/baz/../foo/bar': {
+ href: 'http:/baz/../foo/bar',
+ protocol: 'http:',
+ pathname: '/baz/../foo/bar',
+ path: '/baz/../foo/bar'
+ },
+
+ 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag': {
+ href: 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag',
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com:8000',
+ auth: 'user:pass',
+ port: '8000',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?baz=quux',
+ query: 'baz=quux',
+ pathname: '/foo/bar',
+ path: '/foo/bar?baz=quux'
+ },
+
+ '//user:pass@example.com:8000/foo/bar?baz=quux#frag': {
+ href: '//user:pass@example.com:8000/foo/bar?baz=quux#frag',
+ slashes: true,
+ host: 'example.com:8000',
+ auth: 'user:pass',
+ port: '8000',
+ hostname: 'example.com',
+ hash: '#frag',
+ search: '?baz=quux',
+ query: 'baz=quux',
+ pathname: '/foo/bar',
+ path: '/foo/bar?baz=quux'
+ },
+
+ '/foo/bar?baz=quux#frag': {
+ href: '/foo/bar?baz=quux#frag',
+ hash: '#frag',
+ search: '?baz=quux',
+ query: 'baz=quux',
+ pathname: '/foo/bar',
+ path: '/foo/bar?baz=quux'
+ },
+
+ 'http:/foo/bar?baz=quux#frag': {
+ href: 'http:/foo/bar?baz=quux#frag',
+ protocol: 'http:',
+ hash: '#frag',
+ search: '?baz=quux',
+ query: 'baz=quux',
+ pathname: '/foo/bar',
+ path: '/foo/bar?baz=quux'
+ },
+
+ 'mailto:foo@bar.com?subject=hello': {
+ href: 'mailto:foo@bar.com?subject=hello',
+ protocol: 'mailto:',
+ host: 'bar.com',
+ auth: 'foo',
+ hostname: 'bar.com',
+ search: '?subject=hello',
+ query: 'subject=hello',
+ path: '?subject=hello'
+ },
+
+ 'javascript:alert(\'hello\');': {
+ href: 'javascript:alert(\'hello\');',
+ protocol: 'javascript:',
+ pathname: 'alert(\'hello\');',
+ path: 'alert(\'hello\');'
+ },
+
+ 'xmpp:isaacschlueter@jabber.org': {
+ href: 'xmpp:isaacschlueter@jabber.org',
+ protocol: 'xmpp:',
+ host: 'jabber.org',
+ auth: 'isaacschlueter',
+ hostname: 'jabber.org'
+ },
+
+ 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar': {
+ href: 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar',
+ protocol: 'http:',
+ slashes: true,
+ host: '127.0.0.1:8080',
+ auth: 'atpass:foo@bar',
+ hostname: '127.0.0.1',
+ port: '8080',
+ pathname: '/path',
+ search: '?search=foo',
+ query: 'search=foo',
+ hash: '#bar',
+ path: '/path?search=foo'
+ },
+
+ 'svn+ssh://foo/bar': {
+ href: 'svn+ssh://foo/bar',
+ host: 'foo',
+ hostname: 'foo',
+ protocol: 'svn+ssh:',
+ pathname: '/bar',
+ path: '/bar',
+ slashes: true
+ },
+
+ 'dash-test://foo/bar': {
+ href: 'dash-test://foo/bar',
+ host: 'foo',
+ hostname: 'foo',
+ protocol: 'dash-test:',
+ pathname: '/bar',
+ path: '/bar',
+ slashes: true
+ },
+
+ 'dash-test:foo/bar': {
+ href: 'dash-test:foo/bar',
+ host: 'foo',
+ hostname: 'foo',
+ protocol: 'dash-test:',
+ pathname: '/bar',
+ path: '/bar'
+ },
+
+ 'dot.test://foo/bar': {
+ href: 'dot.test://foo/bar',
+ host: 'foo',
+ hostname: 'foo',
+ protocol: 'dot.test:',
+ pathname: '/bar',
+ path: '/bar',
+ slashes: true
+ },
+
+ 'dot.test:foo/bar': {
+ href: 'dot.test:foo/bar',
+ host: 'foo',
+ hostname: 'foo',
+ protocol: 'dot.test:',
+ pathname: '/bar',
+ path: '/bar'
+ },
+
+ // IDNA tests
+ 'http://www.日本語.com/': {
+ href: 'http://www.xn--wgv71a119e.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.xn--wgv71a119e.com',
+ hostname: 'www.xn--wgv71a119e.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://example.Bücher.com/': {
+ href: 'http://example.xn--bcher-kva.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.xn--bcher-kva.com',
+ hostname: 'example.xn--bcher-kva.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://www.Äffchen.com/': {
+ href: 'http://www.xn--ffchen-9ta.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.xn--ffchen-9ta.com',
+ hostname: 'www.xn--ffchen-9ta.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i': {
+ href: 'http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
+ protocol: 'http:',
+ slashes: true,
+ host: 'www.xn--ffchen-9ta.com',
+ hostname: 'www.xn--ffchen-9ta.com',
+ pathname: ';A/b/c',
+ search: '?d=e',
+ query: 'd=e',
+ hash: '#f%20g%3Ch%3Ei',
+ path: ';A/b/c?d=e'
+ },
+
+ 'http://SÉLIER.COM/': {
+ href: 'http://xn--slier-bsa.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'xn--slier-bsa.com',
+ hostname: 'xn--slier-bsa.com',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://ليهمابتكلموشعربي؟.ي؟/': {
+ href: 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
+ hostname: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://➡.ws/➡': {
+ href: 'http://xn--hgi.ws/➡',
+ protocol: 'http:',
+ slashes: true,
+ host: 'xn--hgi.ws',
+ hostname: 'xn--hgi.ws',
+ pathname: '/➡',
+ path: '/➡'
+ },
+
+ 'http://bucket_name.s3.amazonaws.com/image.jpg': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'bucket_name.s3.amazonaws.com',
+ hostname: 'bucket_name.s3.amazonaws.com',
+ pathname: '/image.jpg',
+ href: 'http://bucket_name.s3.amazonaws.com/image.jpg',
+ path: '/image.jpg'
+ },
+
+ 'git+http://github.com/joyent/node.git': {
+ protocol: 'git+http:',
+ slashes: true,
+ host: 'github.com',
+ hostname: 'github.com',
+ pathname: '/joyent/node.git',
+ path: '/joyent/node.git',
+ href: 'git+http://github.com/joyent/node.git'
+ },
+
+ //if local1@domain1 is uses as a relative URL it may
+ //be parse into auth@hostname, but here there is no
+ //way to make it work in url.parse, I add the test to be explicit
+ 'local1@domain1': {
+ pathname: 'local1@domain1',
+ path: 'local1@domain1',
+ href: 'local1@domain1'
+ },
+
+ //While this may seem counter-intuitive, a browser will parse
+ //<a href='www.google.com'> as a path.
+ 'www.example.com': {
+ href: 'www.example.com',
+ pathname: 'www.example.com',
+ path: 'www.example.com'
+ },
+
+ // ipv6 support
+ '[fe80::1]': {
+ href: '[fe80::1]',
+ pathname: '[fe80::1]',
+ path: '[fe80::1]'
+ },
+
+ 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': {
+ protocol: 'coap:',
+ slashes: true,
+ host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]',
+ hostname: 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
+ href: 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': {
+ protocol: 'coap:',
+ slashes: true,
+ host: '[1080:0:0:0:8:800:200c:417a]:61616',
+ port: '61616',
+ hostname: '1080:0:0:0:8:800:200c:417a',
+ href: 'coap://[1080:0:0:0:8:800:200c:417a]:61616/',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://user:password@[3ffe:2a00:100:7031::1]:8080': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:password',
+ host: '[3ffe:2a00:100:7031::1]:8080',
+ port: '8080',
+ hostname: '3ffe:2a00:100:7031::1',
+ href: 'http://user:password@[3ffe:2a00:100:7031::1]:8080/',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': {
+ protocol: 'coap:',
+ slashes: true,
+ auth: 'u:p',
+ host: '[::192.9.5.5]:61616',
+ port: '61616',
+ hostname: '::192.9.5.5',
+ href: 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature',
+ search: '?n=Temperature',
+ query: 'n=Temperature',
+ pathname: '/.well-known/r',
+ path: '/.well-known/r?n=Temperature'
+ },
+
+ // empty port
+ 'http://example.com:': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ href: 'http://example.com/',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://example.com:/a/b.html': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ href: 'http://example.com/a/b.html',
+ pathname: '/a/b.html',
+ path: '/a/b.html'
+ },
+
+ 'http://example.com:?a=b': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ href: 'http://example.com/?a=b',
+ search: '?a=b',
+ query: 'a=b',
+ pathname: '/',
+ path: '/?a=b'
+ },
+
+ 'http://example.com:#abc': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ href: 'http://example.com/#abc',
+ hash: '#abc',
+ pathname: '/',
+ path: '/'
+ },
+
+ 'http://[fe80::1]:/a/b?a=b#abc': {
+ protocol: 'http:',
+ slashes: true,
+ host: '[fe80::1]',
+ hostname: 'fe80::1',
+ href: 'http://[fe80::1]/a/b?a=b#abc',
+ search: '?a=b',
+ query: 'a=b',
+ hash: '#abc',
+ pathname: '/a/b',
+ path: '/a/b?a=b'
+ },
+
+ 'http://-lovemonsterz.tumblr.com/rss': {
+ protocol: 'http:',
+ slashes: true,
+ host: '-lovemonsterz.tumblr.com',
+ hostname: '-lovemonsterz.tumblr.com',
+ href: 'http://-lovemonsterz.tumblr.com/rss',
+ pathname: '/rss',
+ path: '/rss',
+ },
+
+ 'http://-lovemonsterz.tumblr.com:80/rss': {
+ protocol: 'http:',
+ slashes: true,
+ port: '80',
+ host: '-lovemonsterz.tumblr.com:80',
+ hostname: '-lovemonsterz.tumblr.com',
+ href: 'http://-lovemonsterz.tumblr.com:80/rss',
+ pathname: '/rss',
+ path: '/rss',
+ },
+
+ 'http://user:pass@-lovemonsterz.tumblr.com/rss': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pass',
+ host: '-lovemonsterz.tumblr.com',
+ hostname: '-lovemonsterz.tumblr.com',
+ href: 'http://user:pass@-lovemonsterz.tumblr.com/rss',
+ pathname: '/rss',
+ path: '/rss',
+ },
+
+ 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pass',
+ port: '80',
+ host: '-lovemonsterz.tumblr.com:80',
+ hostname: '-lovemonsterz.tumblr.com',
+ href: 'http://user:pass@-lovemonsterz.tumblr.com:80/rss',
+ pathname: '/rss',
+ path: '/rss',
+ },
+
+ 'http://_jabber._tcp.google.com/test': {
+ protocol: 'http:',
+ slashes: true,
+ host: '_jabber._tcp.google.com',
+ hostname: '_jabber._tcp.google.com',
+ href: 'http://_jabber._tcp.google.com/test',
+ pathname: '/test',
+ path: '/test',
+ },
+
+ 'http://user:pass@_jabber._tcp.google.com/test': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pass',
+ host: '_jabber._tcp.google.com',
+ hostname: '_jabber._tcp.google.com',
+ href: 'http://user:pass@_jabber._tcp.google.com/test',
+ pathname: '/test',
+ path: '/test',
+ },
+
+ 'http://_jabber._tcp.google.com:80/test': {
+ protocol: 'http:',
+ slashes: true,
+ port: '80',
+ host: '_jabber._tcp.google.com:80',
+ hostname: '_jabber._tcp.google.com',
+ href: 'http://_jabber._tcp.google.com:80/test',
+ pathname: '/test',
+ path: '/test',
+ },
+
+ 'http://user:pass@_jabber._tcp.google.com:80/test': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'user:pass',
+ port: '80',
+ host: '_jabber._tcp.google.com:80',
+ hostname: '_jabber._tcp.google.com',
+ href: 'http://user:pass@_jabber._tcp.google.com:80/test',
+ pathname: '/test',
+ path: '/test',
+ },
+
+ 'http://x:1/\' <>"`/{}|\\^~`/': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'x:1',
+ port: '1',
+ hostname: 'x',
+ pathname: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
+ path: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
+ href: 'http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/'
+ },
+
+ 'http://a@b@c/': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'a@b',
+ host: 'c',
+ hostname: 'c',
+ href: 'http://a%40b@c/',
+ path: '/',
+ pathname: '/'
+ },
+
+ 'http://a@b?@c': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'a',
+ host: 'b',
+ hostname: 'b',
+ href: 'http://a@b/?@c',
+ path: '/?@c',
+ pathname: '/',
+ search: '?@c',
+ query: '@c'
+ },
+
+ 'http://a.b/\tbc\ndr\ref g"hq\'j<kl>?mn\\op^q=r`99{st|uv}wz': {
+ protocol: 'http:',
+ slashes: true,
+ host: 'a.b',
+ port: null,
+ hostname: 'a.b',
+ hash: null,
+ pathname: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E',
+ path: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
+ search: '?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
+ query: 'mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
+ href: 'http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz'
+ },
+
+ 'http://a\r" \t\n<\'b:b@c\r\nd/e?f': {
+ protocol: 'http:',
+ slashes: true,
+ auth: 'a\r" \t\n<\'b:b',
+ host: 'c',
+ port: null,
+ hostname: 'c',
+ hash: null,
+ search: '?f',
+ query: 'f',
+ pathname: '%0D%0Ad/e',
+ path: '%0D%0Ad/e?f',
+ href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f'
+ },
+
+ // git urls used by npm
+ 'git+ssh://git@github.com:npm/npm': {
+ protocol: 'git+ssh:',
+ slashes: true,
+ auth: 'git',
+ host: 'github.com',
+ port: null,
+ hostname: 'github.com',
+ hash: null,
+ search: null,
+ query: null,
+ pathname: '/:npm/npm',
+ path: '/:npm/npm',
+ href: 'git+ssh://git@github.com/:npm/npm'
+ },
+
+ 'https://*': {
+ protocol: 'https:',
+ slashes: true,
+ auth: null,
+ host: '',
+ port: null,
+ hostname: '',
+ hash: null,
+ search: null,
+ query: null,
+ pathname: '/*',
+ path: '/*',
+ href: 'https:///*'
+ }
+};
+
+for (const u in parseTests) {
+ let actual = url.parse(u);
+ const spaced = url.parse(` \t ${u}\n\t`);
+ let expected = Object.assign(new url.Url(), parseTests[u]);
+
+ Object.keys(actual).forEach(function(i) {
+ if (expected[i] === undefined && actual[i] === null) {
+ expected[i] = null;
+ }
+ });
+
+ assert.deepStrictEqual(
+ actual,
+ expected,
+ `expected ${inspect(expected)}, got ${inspect(actual)}`
+ );
+ assert.deepStrictEqual(
+ spaced,
+ expected,
+ `expected ${inspect(expected)}, got ${inspect(spaced)}`
+ );
+
+ expected = parseTests[u].href;
+ actual = url.format(parseTests[u]);
+
+ assert.strictEqual(actual, expected,
+ 'format(' + u + ') == ' + u + '\nactual:' + actual);
+}
diff --git a/test/parallel/test-url-parse-invalid-input.js b/test/parallel/test-url-parse-invalid-input.js
new file mode 100644
index 0000000000..17fac57e14
--- /dev/null
+++ b/test/parallel/test-url-parse-invalid-input.js
@@ -0,0 +1,18 @@
+'use strict';
+require('../common');
+const assert = require('assert');
+const url = require('url');
+
+// https://github.com/joyent/node/issues/568
+[
+ undefined,
+ null,
+ true,
+ false,
+ 0.0,
+ 0,
+ [],
+ {}
+].forEach(function(val) {
+ assert.throws(function() { url.parse(val); }, TypeError);
+});
diff --git a/test/parallel/test-url-parse-query.js b/test/parallel/test-url-parse-query.js
new file mode 100644
index 0000000000..34c31d8a3c
--- /dev/null
+++ b/test/parallel/test-url-parse-query.js
@@ -0,0 +1,90 @@
+'use strict';
+require('../common');
+const assert = require('assert');
+const url = require('url');
+
+function createWithNoPrototype(properties = []) {
+ const noProto = Object.create(null);
+ properties.forEach((property) => {
+ noProto[property.key] = property.value;
+ });
+ return noProto;
+}
+
+function check(actual, expected) {
+ assert.notStrictEqual(Object.getPrototypeOf(actual), Object.prototype);
+ assert.deepStrictEqual(Object.keys(actual).sort(),
+ Object.keys(expected).sort());
+ Object.keys(expected).forEach(function(key) {
+ assert.deepStrictEqual(actual[key], expected[key]);
+ });
+}
+
+const parseTestsWithQueryString = {
+ '/foo/bar?baz=quux#frag': {
+ href: '/foo/bar?baz=quux#frag',
+ hash: '#frag',
+ search: '?baz=quux',
+ query: createWithNoPrototype([{key: 'baz', value: 'quux'}]),
+ pathname: '/foo/bar',
+ path: '/foo/bar?baz=quux'
+ },
+ 'http://example.com': {
+ href: 'http://example.com/',
+ protocol: 'http:',
+ slashes: true,
+ host: 'example.com',
+ hostname: 'example.com',
+ query: createWithNoPrototype(),
+ search: '',
+ pathname: '/',
+ path: '/'
+ },
+ '/example': {
+ protocol: null,
+ slashes: null,
+ auth: undefined,
+ host: null,
+ port: null,
+ hostname: null,
+ hash: null,
+ search: '',
+ query: createWithNoPrototype(),
+ pathname: '/example',
+ path: '/example',
+ href: '/example'
+ },
+ '/example?query=value': {
+ protocol: null,
+ slashes: null,
+ auth: undefined,
+ host: null,
+ port: null,
+ hostname: null,
+ hash: null,
+ search: '?query=value',
+ query: createWithNoPrototype([{ key: 'query', value: 'value' }]),
+ pathname: '/example',
+ path: '/example?query=value',
+ href: '/example?query=value'
+ }
+};
+for (const u in parseTestsWithQueryString) {
+ const actual = url.parse(u, true);
+ const expected = Object.assign(new url.Url(), parseTestsWithQueryString[u]);
+ for (const i in actual) {
+ if (actual[i] === null && expected[i] === undefined) {
+ expected[i] = null;
+ }
+ }
+
+ const properties = Object.keys(actual).sort();
+ assert.deepStrictEqual(properties, Object.keys(expected).sort());
+ properties.forEach((property) => {
+ if (property === 'query') {
+ check(actual[property], expected[property]);
+ } else {
+ assert.deepStrictEqual(actual[property], expected[property]);
+ }
+ });
+}
diff --git a/test/parallel/test-url-relative.js b/test/parallel/test-url-relative.js
new file mode 100644
index 0000000000..0d9384a704
--- /dev/null
+++ b/test/parallel/test-url-relative.js
@@ -0,0 +1,429 @@
+/* eslint-disable max-len */
+'use strict';
+require('../common');
+const assert = require('assert');
+const inspect = require('util').inspect;
+const url = require('url');
+
+/*
+ [from, path, expected]
+*/
+const relativeTests = [
+ ['/foo/bar/baz', 'quux', '/foo/bar/quux'],
+ ['/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'],
+ ['/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'],
+ ['/foo/bar/baz', '../quux/baz', '/foo/quux/baz'],
+ ['/foo/bar/baz', '/bar', '/bar'],
+ ['/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'],
+ ['/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'],
+ ['/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'],
+ ['/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'],
+ ['/foo', '.', '/'],
+ ['/foo', '..', '/'],
+ ['/foo/', '.', '/foo/'],
+ ['/foo/', '..', '/'],
+ ['/foo/bar', '.', '/foo/'],
+ ['/foo/bar', '..', '/'],
+ ['/foo/bar/', '.', '/foo/bar/'],
+ ['/foo/bar/', '..', '/foo/'],
+ ['foo/bar', '../../../baz', '../../baz'],
+ ['foo/bar/', '../../../baz', '../baz'],
+ ['http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'https:/p/a/t/h?s#hash2',
+ 'https://p/a/t/h?s#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'https://u:p@h.com/p/a/t/h?s#hash2',
+ 'https://u:p@h.com/p/a/t/h?s#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'https:/a/b/c/d',
+ 'https://a/b/c/d'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'http:#hash2',
+ 'http://example.com/b//c//d;p?q#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'http:/p/a/t/h?s#hash2',
+ 'http://example.com/p/a/t/h?s#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'http://u:p@h.com/p/a/t/h?s#hash2',
+ 'http://u:p@h.com/p/a/t/h?s#hash2'],
+ ['http://example.com/b//c//d;p?q#blarg',
+ 'http:/a/b/c/d',
+ 'http://example.com/a/b/c/d'],
+ ['/foo/bar/baz', '/../etc/passwd', '/etc/passwd'],
+ ['http://localhost', 'file:///Users/foo', 'file:///Users/foo'],
+ ['http://localhost', 'file://foo/Users', 'file://foo/Users']
+];
+relativeTests.forEach(function(relativeTest) {
+ const a = url.resolve(relativeTest[0], relativeTest[1]);
+ const e = relativeTest[2];
+ assert.strictEqual(a, e,
+ 'resolve(' + [relativeTest[0], relativeTest[1]] + ') == ' + e +
+ '\n actual=' + a);
+});
+
+//
+// Tests below taken from Chiron
+// http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js
+//
+// Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
+// used with permission under MIT License
+//
+// Changes marked with @isaacs
+
+const bases = [
+ 'http://a/b/c/d;p?q',
+ 'http://a/b/c/d;p?q=1/2',
+ 'http://a/b/c/d;p=1/2?q',
+ 'fred:///s//a/b/c',
+ 'http:///s//a/b/c'
+];
+
+//[to, from, result]
+const relativeTests2 = [
+ // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html
+ ['../c', 'foo:a/b', 'foo:c'],
+ ['foo:.', 'foo:a', 'foo:'],
+ ['/foo/../../../bar', 'zz:abc', 'zz:/bar'],
+ ['/foo/../bar', 'zz:abc', 'zz:/bar'],
+ // @isaacs Disagree. Not how web browsers resolve this.
+ ['foo/../../../bar', 'zz:abc', 'zz:bar'],
+ // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added
+ ['foo/../bar', 'zz:abc', 'zz:bar'],
+ ['zz:.', 'zz:abc', 'zz:'],
+ ['/.', bases[0], 'http://a/'],
+ ['/.foo', bases[0], 'http://a/.foo'],
+ ['.foo', bases[0], 'http://a/b/c/.foo'],
+
+ // http://gbiv.com/protocols/uri/test/rel_examples1.html
+ // examples from RFC 2396
+ ['g:h', bases[0], 'g:h'],
+ ['g', bases[0], 'http://a/b/c/g'],
+ ['./g', bases[0], 'http://a/b/c/g'],
+ ['g/', bases[0], 'http://a/b/c/g/'],
+ ['/g', bases[0], 'http://a/g'],
+ ['//g', bases[0], 'http://g/'],
+ // changed with RFC 2396bis
+ //('?y', bases[0], 'http://a/b/c/d;p?y'],
+ ['?y', bases[0], 'http://a/b/c/d;p?y'],
+ ['g?y', bases[0], 'http://a/b/c/g?y'],
+ // changed with RFC 2396bis
+ //('#s', bases[0], CURRENT_DOC_URI + '#s'],
+ ['#s', bases[0], 'http://a/b/c/d;p?q#s'],
+ ['g#s', bases[0], 'http://a/b/c/g#s'],
+ ['g?y#s', bases[0], 'http://a/b/c/g?y#s'],
+ [';x', bases[0], 'http://a/b/c/;x'],
+ ['g;x', bases[0], 'http://a/b/c/g;x'],
+ ['g;x?y#s', bases[0], 'http://a/b/c/g;x?y#s'],
+ // changed with RFC 2396bis
+ //('', bases[0], CURRENT_DOC_URI],
+ ['', bases[0], 'http://a/b/c/d;p?q'],
+ ['.', bases[0], 'http://a/b/c/'],
+ ['./', bases[0], 'http://a/b/c/'],
+ ['..', bases[0], 'http://a/b/'],
+ ['../', bases[0], 'http://a/b/'],
+ ['../g', bases[0], 'http://a/b/g'],
+ ['../..', bases[0], 'http://a/'],
+ ['../../', bases[0], 'http://a/'],
+ ['../../g', bases[0], 'http://a/g'],
+ ['../../../g', bases[0], ('http://a/../g', 'http://a/g')],
+ ['../../../../g', bases[0], ('http://a/../../g', 'http://a/g')],
+ // changed with RFC 2396bis
+ //('/./g', bases[0], 'http://a/./g'],
+ ['/./g', bases[0], 'http://a/g'],
+ // changed with RFC 2396bis
+ //('/../g', bases[0], 'http://a/../g'],
+ ['/../g', bases[0], 'http://a/g'],
+ ['g.', bases[0], 'http://a/b/c/g.'],
+ ['.g', bases[0], 'http://a/b/c/.g'],
+ ['g..', bases[0], 'http://a/b/c/g..'],
+ ['..g', bases[0], 'http://a/b/c/..g'],
+ ['./../g', bases[0], 'http://a/b/g'],
+ ['./g/.', bases[0], 'http://a/b/c/g/'],
+ ['g/./h', bases[0], 'http://a/b/c/g/h'],
+ ['g/../h', bases[0], 'http://a/b/c/h'],
+ ['g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'],
+ ['g;x=1/../y', bases[0], 'http://a/b/c/y'],
+ ['g?y/./x', bases[0], 'http://a/b/c/g?y/./x'],
+ ['g?y/../x', bases[0], 'http://a/b/c/g?y/../x'],
+ ['g#s/./x', bases[0], 'http://a/b/c/g#s/./x'],
+ ['g#s/../x', bases[0], 'http://a/b/c/g#s/../x'],
+ ['http:g', bases[0], ('http:g', 'http://a/b/c/g')],
+ ['http:', bases[0], ('http:', bases[0])],
+ // not sure where this one originated
+ ['/a/b/c/./../../g', bases[0], 'http://a/a/g'],
+
+ // http://gbiv.com/protocols/uri/test/rel_examples2.html
+ // slashes in base URI's query args
+ ['g', bases[1], 'http://a/b/c/g'],
+ ['./g', bases[1], 'http://a/b/c/g'],
+ ['g/', bases[1], 'http://a/b/c/g/'],
+ ['/g', bases[1], 'http://a/g'],
+ ['//g', bases[1], 'http://g/'],
+ // changed in RFC 2396bis
+ //('?y', bases[1], 'http://a/b/c/?y'],
+ ['?y', bases[1], 'http://a/b/c/d;p?y'],
+ ['g?y', bases[1], 'http://a/b/c/g?y'],
+ ['g?y/./x', bases[1], 'http://a/b/c/g?y/./x'],
+ ['g?y/../x', bases[1], 'http://a/b/c/g?y/../x'],
+ ['g#s', bases[1], 'http://a/b/c/g#s'],
+ ['g#s/./x', bases[1], 'http://a/b/c/g#s/./x'],
+ ['g#s/../x', bases[1], 'http://a/b/c/g#s/../x'],
+ ['./', bases[1], 'http://a/b/c/'],
+ ['../', bases[1], 'http://a/b/'],
+ ['../g', bases[1], 'http://a/b/g'],
+ ['../../', bases[1], 'http://a/'],
+ ['../../g', bases[1], 'http://a/g'],
+
+ // http://gbiv.com/protocols/uri/test/rel_examples3.html
+ // slashes in path params
+ // all of these changed in RFC 2396bis
+ ['g', bases[2], 'http://a/b/c/d;p=1/g'],
+ ['./g', bases[2], 'http://a/b/c/d;p=1/g'],
+ ['g/', bases[2], 'http://a/b/c/d;p=1/g/'],
+ ['g?y', bases[2], 'http://a/b/c/d;p=1/g?y'],
+ [';x', bases[2], 'http://a/b/c/d;p=1/;x'],
+ ['g;x', bases[2], 'http://a/b/c/d;p=1/g;x'],
+ ['g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'],
+ ['g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'],
+ ['./', bases[2], 'http://a/b/c/d;p=1/'],
+ ['../', bases[2], 'http://a/b/c/'],
+ ['../g', bases[2], 'http://a/b/c/g'],
+ ['../../', bases[2], 'http://a/b/'],
+ ['../../g', bases[2], 'http://a/b/g'],
+
+ // http://gbiv.com/protocols/uri/test/rel_examples4.html
+ // double and triple slash, unknown scheme
+ ['g:h', bases[3], 'g:h'],
+ ['g', bases[3], 'fred:///s//a/b/g'],
+ ['./g', bases[3], 'fred:///s//a/b/g'],
+ ['g/', bases[3], 'fred:///s//a/b/g/'],
+ ['/g', bases[3], 'fred:///g'], // may change to fred:///s//a/g
+ ['//g', bases[3], 'fred://g'], // may change to fred:///s//g
+ ['//g/x', bases[3], 'fred://g/x'], // may change to fred:///s//g/x
+ ['///g', bases[3], 'fred:///g'],
+ ['./', bases[3], 'fred:///s//a/b/'],
+ ['../', bases[3], 'fred:///s//a/'],
+ ['../g', bases[3], 'fred:///s//a/g'],
+
+ ['../../', bases[3], 'fred:///s//'],
+ ['../../g', bases[3], 'fred:///s//g'],
+ ['../../../g', bases[3], 'fred:///s/g'],
+ // may change to fred:///s//a/../../../g
+ ['../../../../g', bases[3], 'fred:///g'],
+
+ // http://gbiv.com/protocols/uri/test/rel_examples5.html
+ // double and triple slash, well-known scheme
+ ['g:h', bases[4], 'g:h'],
+ ['g', bases[4], 'http:///s//a/b/g'],
+ ['./g', bases[4], 'http:///s//a/b/g'],
+ ['g/', bases[4], 'http:///s//a/b/g/'],
+ ['/g', bases[4], 'http:///g'], // may change to http:///s//a/g
+ ['//g', bases[4], 'http://g/'], // may change to http:///s//g
+ ['//g/x', bases[4], 'http://g/x'], // may change to http:///s//g/x
+ ['///g', bases[4], 'http:///g'],
+ ['./', bases[4], 'http:///s//a/b/'],
+ ['../', bases[4], 'http:///s//a/'],
+ ['../g', bases[4], 'http:///s//a/g'],
+ ['../../', bases[4], 'http:///s//'],
+ ['../../g', bases[4], 'http:///s//g'],
+ // may change to http:///s//a/../../g
+ ['../../../g', bases[4], 'http:///s/g'],
+ // may change to http:///s//a/../../../g
+ ['../../../../g', bases[4], 'http:///g'],
+
+ // from Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py
+ ['bar:abc', 'foo:xyz', 'bar:abc'],
+ ['../abc', 'http://example/x/y/z', 'http://example/x/abc'],
+ ['http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'],
+ ['../r', 'http://ex/x/y/z', 'http://ex/x/r'],
+ ['q/r', 'http://ex/x/y', 'http://ex/x/q/r'],
+ ['q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'],
+ ['q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'],
+ ['ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'],
+ ['', 'http://ex/x/y', 'http://ex/x/y'],
+ ['', 'http://ex/x/y/', 'http://ex/x/y/'],
+ ['', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'],
+ ['z/', 'http://ex/x/y/', 'http://ex/x/y/z/'],
+ ['#Animal',
+ 'file:/swap/test/animal.rdf',
+ 'file:/swap/test/animal.rdf#Animal'],
+ ['../abc', 'file:/e/x/y/z', 'file:/e/x/abc'],
+ ['/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'],
+ ['../r', 'file:/ex/x/y/z', 'file:/ex/x/r'],
+ ['/r', 'file:/ex/x/y/z', 'file:/r'],
+ ['q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'],
+ ['q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'],
+ ['q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'],
+ ['q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'],
+ ['ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'],
+ ['', 'file:/ex/x/y', 'file:/ex/x/y'],
+ ['', 'file:/ex/x/y/', 'file:/ex/x/y/'],
+ ['', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'],
+ ['z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'],
+ ['file://meetings.example.com/cal#m1',
+ 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3',
+ 'file://meetings.example.com/cal#m1'],
+ ['file://meetings.example.com/cal#m1',
+ 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3',
+ 'file://meetings.example.com/cal#m1'],
+ ['./#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'],
+ ['./#', 'file:/some/dir/foo', 'file:/some/dir/#'],
+ // Ryan Lee
+ ['./', 'http://example/x/abc.efg', 'http://example/x/'],
+
+
+ // Graham Klyne's tests
+ // http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls
+ // 01-31 are from Connelly's cases
+
+ // 32-49
+ ['./q:r', 'http://ex/x/y', 'http://ex/x/q:r'],
+ ['./p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'],
+ ['?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'],
+ ['y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'],
+ ['local/qual@domain.org#frag',
+ 'mailto:local',
+ 'mailto:local/qual@domain.org#frag'],
+ ['more/qual2@domain2.org#frag',
+ 'mailto:local/qual1@domain1.org',
+ 'mailto:local/more/qual2@domain2.org#frag'],
+ ['y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'],
+ ['/x/y?q', 'http://ex?p', 'http://ex/x/y?q'],
+ ['c/d', 'foo:a/b', 'foo:a/c/d'],
+ ['/c/d', 'foo:a/b', 'foo:/c/d'],
+ ['', 'foo:a/b?c#d', 'foo:a/b?c'],
+ ['b/c', 'foo:a', 'foo:b/c'],
+ ['../b/c', 'foo:/a/y/z', 'foo:/a/b/c'],
+ ['./b/c', 'foo:a', 'foo:b/c'],
+ ['/./b/c', 'foo:a', 'foo:/b/c'],
+ ['../../d', 'foo://a//b/c', 'foo://a/d'],
+ ['.', 'foo:a', 'foo:'],
+ ['..', 'foo:a', 'foo:'],
+
+ // 50-57[cf. TimBL comments --
+ // http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html,
+ // http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html)
+ ['abc', 'http://example/x/y%2Fz', 'http://example/x/abc'],
+ ['../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'],
+ ['../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'],
+ ['abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'],
+ ['q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'],
+ ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
+ ['/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'],
+ ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
+
+ // 70-77
+ ['local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'],
+ ['local2@domain2?query2',
+ 'mailto:local1@domain1',
+ 'mailto:local2@domain2?query2'],
+ ['local2@domain2?query2',
+ 'mailto:local1@domain1?query1',
+ 'mailto:local2@domain2?query2'],
+ ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
+ ['local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'],
+ ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
+ ['http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'],
+ ['http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'],
+
+ // 82-88
+ // @isaacs Disagree. Not how browsers do it.
+ // ['http:this', 'http://example.org/base/uri', 'http:this'],
+ // @isaacs Added
+ ['http:this', 'http://example.org/base/uri', 'http://example.org/base/this'],
+ ['http:this', 'http:base', 'http:this'],
+ ['.//g', 'f:/a', 'f://g'],
+ ['b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'],
+ ['m2@example.ord/c2@example.org',
+ 'mid:m@example.ord/c@example.org',
+ 'mid:m@example.ord/m2@example.ord/c2@example.org'],
+ ['mini1.xml',
+ 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/',
+ 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'],
+ ['../b/c', 'foo:a/y/z', 'foo:a/b/c'],
+
+ //changeing auth
+ ['http://diff:auth@www.example.com',
+ 'http://asdf:qwer@www.example.com',
+ 'http://diff:auth@www.example.com/'],
+
+ // changing port
+ ['https://example.com:81/',
+ 'https://example.com:82/',
+ 'https://example.com:81/'],
+
+ // https://github.com/nodejs/node/issues/1435
+ ['https://another.host.com/',
+ 'https://user:password@example.org/',
+ 'https://another.host.com/'],
+ ['//another.host.com/',
+ 'https://user:password@example.org/',
+ 'https://another.host.com/'],
+ ['http://another.host.com/',
+ 'https://user:password@example.org/',
+ 'http://another.host.com/'],
+ ['mailto:another.host.com',
+ 'mailto:user@example.org',
+ 'mailto:another.host.com'],
+ ['https://example.com/foo',
+ 'https://user:password@example.com',
+ 'https://user:password@example.com/foo'],
+];
+relativeTests2.forEach(function(relativeTest) {
+ const a = url.resolve(relativeTest[1], relativeTest[0]);
+ const e = url.format(relativeTest[2]);
+ assert.strictEqual(a, e,
+ 'resolve(' + [relativeTest[1], relativeTest[0]] + ') == ' + e +
+ '\n actual=' + a);
+});
+
+//if format and parse are inverse operations then
+//resolveObject(parse(x), y) == parse(resolve(x, y))
+
+//format: [from, path, expected]
+relativeTests.forEach(function(relativeTest) {
+ let actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]);
+ let expected = url.parse(relativeTest[2]);
+
+
+ assert.deepStrictEqual(actual, expected);
+
+ expected = relativeTest[2];
+ actual = url.format(actual);
+
+ assert.strictEqual(actual, expected,
+ 'format(' + actual + ') == ' + expected + '\nactual:' + actual);
+});
+
+//format: [to, from, result]
+// the test: ['.//g', 'f:/a', 'f://g'] is a fundamental problem
+// url.parse('f:/a') does not have a host
+// url.resolve('f:/a', './/g') does not have a host because you have moved
+// down to the g directory. i.e. f: //g, however when this url is parsed
+// f:// will indicate that the host is g which is not the case.
+// it is unclear to me how to keep this information from being lost
+// it may be that a pathname of ////g should collapse to /g but this seems
+// to be a lot of work for an edge case. Right now I remove the test
+if (relativeTests2[181][0] === './/g' &&
+ relativeTests2[181][1] === 'f:/a' &&
+ relativeTests2[181][2] === 'f://g') {
+ relativeTests2.splice(181, 1);
+}
+relativeTests2.forEach(function(relativeTest) {
+ let actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]);
+ let expected = url.parse(relativeTest[2]);
+
+ assert.deepStrictEqual(
+ actual,
+ expected,
+ `expected ${inspect(expected)} but got ${inspect(actual)}`
+ );
+
+ expected = url.format(relativeTest[2]);
+ actual = url.format(actual);
+
+ assert.strictEqual(actual, expected,
+ 'format(' + relativeTest[1] + ') == ' + expected +
+ '\nactual:' + actual);
+});
diff --git a/test/parallel/test-url.js b/test/parallel/test-url.js
deleted file mode 100644
index 8c67c6855c..0000000000
--- a/test/parallel/test-url.js
+++ /dev/null
@@ -1,1714 +0,0 @@
-/* eslint-disable max-len */
-'use strict';
-require('../common');
-const assert = require('assert');
-const inspect = require('util').inspect;
-
-const url = require('url');
-
-// URLs to parse, and expected data
-// { url : parsed }
-const parseTests = {
- '//some_path': {
- href: '//some_path',
- pathname: '//some_path',
- path: '//some_path'
- },
-
- 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h': {
- protocol: 'http:',
- slashes: true,
- host: 'evil-phisher',
- hostname: 'evil-phisher',
- pathname: '/foo.html',
- path: '/foo.html',
- hash: '#h%5Ca%5Cs%5Ch',
- href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch'
- },
-
- 'http:\\\\evil-phisher\\foo.html?json="\\"foo\\""#h\\a\\s\\h': {
- protocol: 'http:',
- slashes: true,
- host: 'evil-phisher',
- hostname: 'evil-phisher',
- pathname: '/foo.html',
- search: '?json=%22%5C%22foo%5C%22%22',
- query: 'json=%22%5C%22foo%5C%22%22',
- path: '/foo.html?json=%22%5C%22foo%5C%22%22',
- hash: '#h%5Ca%5Cs%5Ch',
- href: 'http://evil-phisher/foo.html?json=%22%5C%22foo%5C%22%22#h%5Ca%5Cs%5Ch'
- },
-
- 'http:\\\\evil-phisher\\foo.html#h\\a\\s\\h?blarg': {
- protocol: 'http:',
- slashes: true,
- host: 'evil-phisher',
- hostname: 'evil-phisher',
- pathname: '/foo.html',
- path: '/foo.html',
- hash: '#h%5Ca%5Cs%5Ch?blarg',
- href: 'http://evil-phisher/foo.html#h%5Ca%5Cs%5Ch?blarg'
- },
-
-
- 'http:\\\\evil-phisher\\foo.html': {
- protocol: 'http:',
- slashes: true,
- host: 'evil-phisher',
- hostname: 'evil-phisher',
- pathname: '/foo.html',
- path: '/foo.html',
- href: 'http://evil-phisher/foo.html'
- },
-
- 'HTTP://www.example.com/': {
- href: 'http://www.example.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'HTTP://www.example.com': {
- href: 'http://www.example.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://www.ExAmPlE.com/': {
- href: 'http://www.example.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://user:pw@www.ExAmPlE.com/': {
- href: 'http://user:pw@www.example.com/',
- protocol: 'http:',
- slashes: true,
- auth: 'user:pw',
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://USER:PW@www.ExAmPlE.com/': {
- href: 'http://USER:PW@www.example.com/',
- protocol: 'http:',
- slashes: true,
- auth: 'USER:PW',
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://user@www.example.com/': {
- href: 'http://user@www.example.com/',
- protocol: 'http:',
- slashes: true,
- auth: 'user',
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://user%3Apw@www.example.com/': {
- href: 'http://user:pw@www.example.com/',
- protocol: 'http:',
- slashes: true,
- auth: 'user:pw',
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://x.com/path?that\'s#all, folks': {
- href: 'http://x.com/path?that%27s#all,%20folks',
- protocol: 'http:',
- slashes: true,
- host: 'x.com',
- hostname: 'x.com',
- search: '?that%27s',
- query: 'that%27s',
- pathname: '/path',
- hash: '#all,%20folks',
- path: '/path?that%27s'
- },
-
- 'HTTP://X.COM/Y': {
- href: 'http://x.com/Y',
- protocol: 'http:',
- slashes: true,
- host: 'x.com',
- hostname: 'x.com',
- pathname: '/Y',
- path: '/Y'
- },
-
- // whitespace in the front
- ' http://www.example.com/': {
- href: 'http://www.example.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.example.com',
- hostname: 'www.example.com',
- pathname: '/',
- path: '/'
- },
-
- // + not an invalid host character
- // per https://url.spec.whatwg.org/#host-parsing
- 'http://x.y.com+a/b/c': {
- href: 'http://x.y.com+a/b/c',
- protocol: 'http:',
- slashes: true,
- host: 'x.y.com+a',
- hostname: 'x.y.com+a',
- pathname: '/b/c',
- path: '/b/c'
- },
-
- // an unexpected invalid char in the hostname.
- 'HtTp://x.y.cOm;a/b/c?d=e#f g<h>i': {
- href: 'http://x.y.com/;a/b/c?d=e#f%20g%3Ch%3Ei',
- protocol: 'http:',
- slashes: true,
- host: 'x.y.com',
- hostname: 'x.y.com',
- pathname: ';a/b/c',
- search: '?d=e',
- query: 'd=e',
- hash: '#f%20g%3Ch%3Ei',
- path: ';a/b/c?d=e'
- },
-
- // make sure that we don't accidentally lcast the path parts.
- 'HtTp://x.y.cOm;A/b/c?d=e#f g<h>i': {
- href: 'http://x.y.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
- protocol: 'http:',
- slashes: true,
- host: 'x.y.com',
- hostname: 'x.y.com',
- pathname: ';A/b/c',
- search: '?d=e',
- query: 'd=e',
- hash: '#f%20g%3Ch%3Ei',
- path: ';A/b/c?d=e'
- },
-
- 'http://x...y...#p': {
- href: 'http://x...y.../#p',
- protocol: 'http:',
- slashes: true,
- host: 'x...y...',
- hostname: 'x...y...',
- hash: '#p',
- pathname: '/',
- path: '/'
- },
-
- 'http://x/p/"quoted"': {
- href: 'http://x/p/%22quoted%22',
- protocol: 'http:',
- slashes: true,
- host: 'x',
- hostname: 'x',
- pathname: '/p/%22quoted%22',
- path: '/p/%22quoted%22'
- },
-
- '<http://goo.corn/bread> Is a URL!': {
- href: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
- pathname: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!',
- path: '%3Chttp://goo.corn/bread%3E%20Is%20a%20URL!'
- },
-
- 'http://www.narwhaljs.org/blog/categories?id=news': {
- href: 'http://www.narwhaljs.org/blog/categories?id=news',
- protocol: 'http:',
- slashes: true,
- host: 'www.narwhaljs.org',
- hostname: 'www.narwhaljs.org',
- search: '?id=news',
- query: 'id=news',
- pathname: '/blog/categories',
- path: '/blog/categories?id=news'
- },
-
- 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=': {
- href: 'http://mt0.google.com/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
- protocol: 'http:',
- slashes: true,
- host: 'mt0.google.com',
- hostname: 'mt0.google.com',
- pathname: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s=',
- path: '/vt/lyrs=m@114&hl=en&src=api&x=2&y=2&z=3&s='
- },
-
- 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
- href: 'http://mt0.google.com/vt/lyrs=m@114???&hl=en&src=api' +
- '&x=2&y=2&z=3&s=',
- protocol: 'http:',
- slashes: true,
- host: 'mt0.google.com',
- hostname: 'mt0.google.com',
- search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
- query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
- pathname: '/vt/lyrs=m@114',
- path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
- },
-
- 'http://user:pass@mt0.google.com/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s=': {
- href: 'http://user:pass@mt0.google.com/vt/lyrs=m@114???' +
- '&hl=en&src=api&x=2&y=2&z=3&s=',
- protocol: 'http:',
- slashes: true,
- host: 'mt0.google.com',
- auth: 'user:pass',
- hostname: 'mt0.google.com',
- search: '???&hl=en&src=api&x=2&y=2&z=3&s=',
- query: '??&hl=en&src=api&x=2&y=2&z=3&s=',
- pathname: '/vt/lyrs=m@114',
- path: '/vt/lyrs=m@114???&hl=en&src=api&x=2&y=2&z=3&s='
- },
-
- 'file:///etc/passwd': {
- href: 'file:///etc/passwd',
- slashes: true,
- protocol: 'file:',
- pathname: '/etc/passwd',
- hostname: '',
- host: '',
- path: '/etc/passwd'
- },
-
- 'file://localhost/etc/passwd': {
- href: 'file://localhost/etc/passwd',
- protocol: 'file:',
- slashes: true,
- pathname: '/etc/passwd',
- hostname: 'localhost',
- host: 'localhost',
- path: '/etc/passwd'
- },
-
- 'file://foo/etc/passwd': {
- href: 'file://foo/etc/passwd',
- protocol: 'file:',
- slashes: true,
- pathname: '/etc/passwd',
- hostname: 'foo',
- host: 'foo',
- path: '/etc/passwd'
- },
-
- 'file:///etc/node/': {
- href: 'file:///etc/node/',
- slashes: true,
- protocol: 'file:',
- pathname: '/etc/node/',
- hostname: '',
- host: '',
- path: '/etc/node/'
- },
-
- 'file://localhost/etc/node/': {
- href: 'file://localhost/etc/node/',
- protocol: 'file:',
- slashes: true,
- pathname: '/etc/node/',
- hostname: 'localhost',
- host: 'localhost',
- path: '/etc/node/'
- },
-
- 'file://foo/etc/node/': {
- href: 'file://foo/etc/node/',
- protocol: 'file:',
- slashes: true,
- pathname: '/etc/node/',
- hostname: 'foo',
- host: 'foo',
- path: '/etc/node/'
- },
-
- 'http:/baz/../foo/bar': {
- href: 'http:/baz/../foo/bar',
- protocol: 'http:',
- pathname: '/baz/../foo/bar',
- path: '/baz/../foo/bar'
- },
-
- 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag': {
- href: 'http://user:pass@example.com:8000/foo/bar?baz=quux#frag',
- protocol: 'http:',
- slashes: true,
- host: 'example.com:8000',
- auth: 'user:pass',
- port: '8000',
- hostname: 'example.com',
- hash: '#frag',
- search: '?baz=quux',
- query: 'baz=quux',
- pathname: '/foo/bar',
- path: '/foo/bar?baz=quux'
- },
-
- '//user:pass@example.com:8000/foo/bar?baz=quux#frag': {
- href: '//user:pass@example.com:8000/foo/bar?baz=quux#frag',
- slashes: true,
- host: 'example.com:8000',
- auth: 'user:pass',
- port: '8000',
- hostname: 'example.com',
- hash: '#frag',
- search: '?baz=quux',
- query: 'baz=quux',
- pathname: '/foo/bar',
- path: '/foo/bar?baz=quux'
- },
-
- '/foo/bar?baz=quux#frag': {
- href: '/foo/bar?baz=quux#frag',
- hash: '#frag',
- search: '?baz=quux',
- query: 'baz=quux',
- pathname: '/foo/bar',
- path: '/foo/bar?baz=quux'
- },
-
- 'http:/foo/bar?baz=quux#frag': {
- href: 'http:/foo/bar?baz=quux#frag',
- protocol: 'http:',
- hash: '#frag',
- search: '?baz=quux',
- query: 'baz=quux',
- pathname: '/foo/bar',
- path: '/foo/bar?baz=quux'
- },
-
- 'mailto:foo@bar.com?subject=hello': {
- href: 'mailto:foo@bar.com?subject=hello',
- protocol: 'mailto:',
- host: 'bar.com',
- auth: 'foo',
- hostname: 'bar.com',
- search: '?subject=hello',
- query: 'subject=hello',
- path: '?subject=hello'
- },
-
- 'javascript:alert(\'hello\');': {
- href: 'javascript:alert(\'hello\');',
- protocol: 'javascript:',
- pathname: 'alert(\'hello\');',
- path: 'alert(\'hello\');'
- },
-
- 'xmpp:isaacschlueter@jabber.org': {
- href: 'xmpp:isaacschlueter@jabber.org',
- protocol: 'xmpp:',
- host: 'jabber.org',
- auth: 'isaacschlueter',
- hostname: 'jabber.org'
- },
-
- 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar': {
- href: 'http://atpass:foo%40bar@127.0.0.1:8080/path?search=foo#bar',
- protocol: 'http:',
- slashes: true,
- host: '127.0.0.1:8080',
- auth: 'atpass:foo@bar',
- hostname: '127.0.0.1',
- port: '8080',
- pathname: '/path',
- search: '?search=foo',
- query: 'search=foo',
- hash: '#bar',
- path: '/path?search=foo'
- },
-
- 'svn+ssh://foo/bar': {
- href: 'svn+ssh://foo/bar',
- host: 'foo',
- hostname: 'foo',
- protocol: 'svn+ssh:',
- pathname: '/bar',
- path: '/bar',
- slashes: true
- },
-
- 'dash-test://foo/bar': {
- href: 'dash-test://foo/bar',
- host: 'foo',
- hostname: 'foo',
- protocol: 'dash-test:',
- pathname: '/bar',
- path: '/bar',
- slashes: true
- },
-
- 'dash-test:foo/bar': {
- href: 'dash-test:foo/bar',
- host: 'foo',
- hostname: 'foo',
- protocol: 'dash-test:',
- pathname: '/bar',
- path: '/bar'
- },
-
- 'dot.test://foo/bar': {
- href: 'dot.test://foo/bar',
- host: 'foo',
- hostname: 'foo',
- protocol: 'dot.test:',
- pathname: '/bar',
- path: '/bar',
- slashes: true
- },
-
- 'dot.test:foo/bar': {
- href: 'dot.test:foo/bar',
- host: 'foo',
- hostname: 'foo',
- protocol: 'dot.test:',
- pathname: '/bar',
- path: '/bar'
- },
-
- // IDNA tests
- 'http://www.日本語.com/': {
- href: 'http://www.xn--wgv71a119e.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.xn--wgv71a119e.com',
- hostname: 'www.xn--wgv71a119e.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://example.Bücher.com/': {
- href: 'http://example.xn--bcher-kva.com/',
- protocol: 'http:',
- slashes: true,
- host: 'example.xn--bcher-kva.com',
- hostname: 'example.xn--bcher-kva.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://www.Äffchen.com/': {
- href: 'http://www.xn--ffchen-9ta.com/',
- protocol: 'http:',
- slashes: true,
- host: 'www.xn--ffchen-9ta.com',
- hostname: 'www.xn--ffchen-9ta.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://www.Äffchen.cOm;A/b/c?d=e#f g<h>i': {
- href: 'http://www.xn--ffchen-9ta.com/;A/b/c?d=e#f%20g%3Ch%3Ei',
- protocol: 'http:',
- slashes: true,
- host: 'www.xn--ffchen-9ta.com',
- hostname: 'www.xn--ffchen-9ta.com',
- pathname: ';A/b/c',
- search: '?d=e',
- query: 'd=e',
- hash: '#f%20g%3Ch%3Ei',
- path: ';A/b/c?d=e'
- },
-
- 'http://SÉLIER.COM/': {
- href: 'http://xn--slier-bsa.com/',
- protocol: 'http:',
- slashes: true,
- host: 'xn--slier-bsa.com',
- hostname: 'xn--slier-bsa.com',
- pathname: '/',
- path: '/'
- },
-
- 'http://ليهمابتكلموشعربي؟.ي؟/': {
- href: 'http://xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f/',
- protocol: 'http:',
- slashes: true,
- host: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
- hostname: 'xn--egbpdaj6bu4bxfgehfvwxn.xn--egb9f',
- pathname: '/',
- path: '/'
- },
-
- 'http://➡.ws/➡': {
- href: 'http://xn--hgi.ws/➡',
- protocol: 'http:',
- slashes: true,
- host: 'xn--hgi.ws',
- hostname: 'xn--hgi.ws',
- pathname: '/➡',
- path: '/➡'
- },
-
- 'http://bucket_name.s3.amazonaws.com/image.jpg': {
- protocol: 'http:',
- slashes: true,
- host: 'bucket_name.s3.amazonaws.com',
- hostname: 'bucket_name.s3.amazonaws.com',
- pathname: '/image.jpg',
- href: 'http://bucket_name.s3.amazonaws.com/image.jpg',
- path: '/image.jpg'
- },
-
- 'git+http://github.com/joyent/node.git': {
- protocol: 'git+http:',
- slashes: true,
- host: 'github.com',
- hostname: 'github.com',
- pathname: '/joyent/node.git',
- path: '/joyent/node.git',
- href: 'git+http://github.com/joyent/node.git'
- },
-
- //if local1@domain1 is uses as a relative URL it may
- //be parse into auth@hostname, but here there is no
- //way to make it work in url.parse, I add the test to be explicit
- 'local1@domain1': {
- pathname: 'local1@domain1',
- path: 'local1@domain1',
- href: 'local1@domain1'
- },
-
- //While this may seem counter-intuitive, a browser will parse
- //<a href='www.google.com'> as a path.
- 'www.example.com': {
- href: 'www.example.com',
- pathname: 'www.example.com',
- path: 'www.example.com'
- },
-
- // ipv6 support
- '[fe80::1]': {
- href: '[fe80::1]',
- pathname: '[fe80::1]',
- path: '[fe80::1]'
- },
-
- 'coap://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]': {
- protocol: 'coap:',
- slashes: true,
- host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]',
- hostname: 'fedc:ba98:7654:3210:fedc:ba98:7654:3210',
- href: 'coap://[fedc:ba98:7654:3210:fedc:ba98:7654:3210]/',
- pathname: '/',
- path: '/'
- },
-
- 'coap://[1080:0:0:0:8:800:200C:417A]:61616/': {
- protocol: 'coap:',
- slashes: true,
- host: '[1080:0:0:0:8:800:200c:417a]:61616',
- port: '61616',
- hostname: '1080:0:0:0:8:800:200c:417a',
- href: 'coap://[1080:0:0:0:8:800:200c:417a]:61616/',
- pathname: '/',
- path: '/'
- },
-
- 'http://user:password@[3ffe:2a00:100:7031::1]:8080': {
- protocol: 'http:',
- slashes: true,
- auth: 'user:password',
- host: '[3ffe:2a00:100:7031::1]:8080',
- port: '8080',
- hostname: '3ffe:2a00:100:7031::1',
- href: 'http://user:password@[3ffe:2a00:100:7031::1]:8080/',
- pathname: '/',
- path: '/'
- },
-
- 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature': {
- protocol: 'coap:',
- slashes: true,
- auth: 'u:p',
- host: '[::192.9.5.5]:61616',
- port: '61616',
- hostname: '::192.9.5.5',
- href: 'coap://u:p@[::192.9.5.5]:61616/.well-known/r?n=Temperature',
- search: '?n=Temperature',
- query: 'n=Temperature',
- pathname: '/.well-known/r',
- path: '/.well-known/r?n=Temperature'
- },
-
- // empty port
- 'http://example.com:': {
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- href: 'http://example.com/',
- pathname: '/',
- path: '/'
- },
-
- 'http://example.com:/a/b.html': {
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- href: 'http://example.com/a/b.html',
- pathname: '/a/b.html',
- path: '/a/b.html'
- },
-
- 'http://example.com:?a=b': {
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- href: 'http://example.com/?a=b',
- search: '?a=b',
- query: 'a=b',
- pathname: '/',
- path: '/?a=b'
- },
-
- 'http://example.com:#abc': {
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- href: 'http://example.com/#abc',
- hash: '#abc',
- pathname: '/',
- path: '/'
- },
-
- 'http://[fe80::1]:/a/b?a=b#abc': {
- protocol: 'http:',
- slashes: true,
- host: '[fe80::1]',
- hostname: 'fe80::1',
- href: 'http://[fe80::1]/a/b?a=b#abc',
- search: '?a=b',
- query: 'a=b',
- hash: '#abc',
- pathname: '/a/b',
- path: '/a/b?a=b'
- },
-
- 'http://-lovemonsterz.tumblr.com/rss': {
- protocol: 'http:',
- slashes: true,
- host: '-lovemonsterz.tumblr.com',
- hostname: '-lovemonsterz.tumblr.com',
- href: 'http://-lovemonsterz.tumblr.com/rss',
- pathname: '/rss',
- path: '/rss',
- },
-
- 'http://-lovemonsterz.tumblr.com:80/rss': {
- protocol: 'http:',
- slashes: true,
- port: '80',
- host: '-lovemonsterz.tumblr.com:80',
- hostname: '-lovemonsterz.tumblr.com',
- href: 'http://-lovemonsterz.tumblr.com:80/rss',
- pathname: '/rss',
- path: '/rss',
- },
-
- 'http://user:pass@-lovemonsterz.tumblr.com/rss': {
- protocol: 'http:',
- slashes: true,
- auth: 'user:pass',
- host: '-lovemonsterz.tumblr.com',
- hostname: '-lovemonsterz.tumblr.com',
- href: 'http://user:pass@-lovemonsterz.tumblr.com/rss',
- pathname: '/rss',
- path: '/rss',
- },
-
- 'http://user:pass@-lovemonsterz.tumblr.com:80/rss': {
- protocol: 'http:',
- slashes: true,
- auth: 'user:pass',
- port: '80',
- host: '-lovemonsterz.tumblr.com:80',
- hostname: '-lovemonsterz.tumblr.com',
- href: 'http://user:pass@-lovemonsterz.tumblr.com:80/rss',
- pathname: '/rss',
- path: '/rss',
- },
-
- 'http://_jabber._tcp.google.com/test': {
- protocol: 'http:',
- slashes: true,
- host: '_jabber._tcp.google.com',
- hostname: '_jabber._tcp.google.com',
- href: 'http://_jabber._tcp.google.com/test',
- pathname: '/test',
- path: '/test',
- },
-
- 'http://user:pass@_jabber._tcp.google.com/test': {
- protocol: 'http:',
- slashes: true,
- auth: 'user:pass',
- host: '_jabber._tcp.google.com',
- hostname: '_jabber._tcp.google.com',
- href: 'http://user:pass@_jabber._tcp.google.com/test',
- pathname: '/test',
- path: '/test',
- },
-
- 'http://_jabber._tcp.google.com:80/test': {
- protocol: 'http:',
- slashes: true,
- port: '80',
- host: '_jabber._tcp.google.com:80',
- hostname: '_jabber._tcp.google.com',
- href: 'http://_jabber._tcp.google.com:80/test',
- pathname: '/test',
- path: '/test',
- },
-
- 'http://user:pass@_jabber._tcp.google.com:80/test': {
- protocol: 'http:',
- slashes: true,
- auth: 'user:pass',
- port: '80',
- host: '_jabber._tcp.google.com:80',
- hostname: '_jabber._tcp.google.com',
- href: 'http://user:pass@_jabber._tcp.google.com:80/test',
- pathname: '/test',
- path: '/test',
- },
-
- 'http://x:1/\' <>"`/{}|\\^~`/': {
- protocol: 'http:',
- slashes: true,
- host: 'x:1',
- port: '1',
- hostname: 'x',
- pathname: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
- path: '/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/',
- href: 'http://x:1/%27%20%3C%3E%22%60/%7B%7D%7C/%5E~%60/'
- },
-
- 'http://a@b@c/': {
- protocol: 'http:',
- slashes: true,
- auth: 'a@b',
- host: 'c',
- hostname: 'c',
- href: 'http://a%40b@c/',
- path: '/',
- pathname: '/'
- },
-
- 'http://a@b?@c': {
- protocol: 'http:',
- slashes: true,
- auth: 'a',
- host: 'b',
- hostname: 'b',
- href: 'http://a@b/?@c',
- path: '/?@c',
- pathname: '/',
- search: '?@c',
- query: '@c'
- },
-
- 'http://a.b/\tbc\ndr\ref g"hq\'j<kl>?mn\\op^q=r`99{st|uv}wz': {
- protocol: 'http:',
- slashes: true,
- host: 'a.b',
- port: null,
- hostname: 'a.b',
- hash: null,
- pathname: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E',
- path: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
- search: '?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
- query: 'mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
- href: 'http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz'
- },
-
- 'http://a\r" \t\n<\'b:b@c\r\nd/e?f': {
- protocol: 'http:',
- slashes: true,
- auth: 'a\r" \t\n<\'b:b',
- host: 'c',
- port: null,
- hostname: 'c',
- hash: null,
- search: '?f',
- query: 'f',
- pathname: '%0D%0Ad/e',
- path: '%0D%0Ad/e?f',
- href: 'http://a%0D%22%20%09%0A%3C\'b:b@c/%0D%0Ad/e?f'
- },
-
- // git urls used by npm
- 'git+ssh://git@github.com:npm/npm': {
- protocol: 'git+ssh:',
- slashes: true,
- auth: 'git',
- host: 'github.com',
- port: null,
- hostname: 'github.com',
- hash: null,
- search: null,
- query: null,
- pathname: '/:npm/npm',
- path: '/:npm/npm',
- href: 'git+ssh://git@github.com/:npm/npm'
- },
-
- 'https://*': {
- protocol: 'https:',
- slashes: true,
- auth: null,
- host: '',
- port: null,
- hostname: '',
- hash: null,
- search: null,
- query: null,
- pathname: '/*',
- path: '/*',
- href: 'https:///*'
- }
-
-};
-
-for (const u in parseTests) {
- let actual = url.parse(u);
- const spaced = url.parse(` \t ${u}\n\t`);
- let expected = Object.assign(new url.Url(), parseTests[u]);
-
- Object.keys(actual).forEach(function(i) {
- if (expected[i] === undefined && actual[i] === null) {
- expected[i] = null;
- }
- });
-
- assert.deepStrictEqual(
- actual,
- expected,
- `expected ${inspect(expected)}, got ${inspect(actual)}`
- );
- assert.deepStrictEqual(
- spaced,
- expected,
- `expected ${inspect(expected)}, got ${inspect(spaced)}`
- );
-
- expected = parseTests[u].href;
- actual = url.format(parseTests[u]);
-
- assert.strictEqual(actual, expected,
- 'format(' + u + ') == ' + u + '\nactual:' + actual);
-}
-
-function createWithNoPrototype(properties = []) {
- const noProto = Object.create(null);
- properties.forEach((property) => {
- noProto[property.key] = property.value;
- });
- return noProto;
-}
-
-function check(actual, expected) {
- assert.notStrictEqual(Object.getPrototypeOf(actual), Object.prototype);
- assert.deepStrictEqual(Object.keys(actual).sort(),
- Object.keys(expected).sort());
- Object.keys(expected).forEach(function(key) {
- assert.deepStrictEqual(actual[key], expected[key]);
- });
-}
-
-const parseTestsWithQueryString = {
- '/foo/bar?baz=quux#frag': {
- href: '/foo/bar?baz=quux#frag',
- hash: '#frag',
- search: '?baz=quux',
- query: createWithNoPrototype([{key: 'baz', value: 'quux'}]),
- pathname: '/foo/bar',
- path: '/foo/bar?baz=quux'
- },
- 'http://example.com': {
- href: 'http://example.com/',
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- query: createWithNoPrototype(),
- search: '',
- pathname: '/',
- path: '/'
- },
- '/example': {
- protocol: null,
- slashes: null,
- auth: undefined,
- host: null,
- port: null,
- hostname: null,
- hash: null,
- search: '',
- query: createWithNoPrototype(),
- pathname: '/example',
- path: '/example',
- href: '/example'
- },
- '/example?query=value': {
- protocol: null,
- slashes: null,
- auth: undefined,
- host: null,
- port: null,
- hostname: null,
- hash: null,
- search: '?query=value',
- query: createWithNoPrototype([{ key: 'query', value: 'value' }]),
- pathname: '/example',
- path: '/example?query=value',
- href: '/example?query=value'
- }
-};
-for (const u in parseTestsWithQueryString) {
- const actual = url.parse(u, true);
- const expected = Object.assign(new url.Url(), parseTestsWithQueryString[u]);
- for (const i in actual) {
- if (actual[i] === null && expected[i] === undefined) {
- expected[i] = null;
- }
- }
-
- const properties = Object.keys(actual).sort();
- assert.deepStrictEqual(properties, Object.keys(expected).sort());
- properties.forEach((property) => {
- if (property === 'query') {
- check(actual[property], expected[property]);
- } else {
- assert.deepStrictEqual(actual[property], expected[property]);
- }
- });
-}
-
-// some extra formatting tests, just to verify
-// that it'll format slightly wonky content to a valid url.
-const formatTests = {
- 'http://example.com?': {
- href: 'http://example.com/?',
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- search: '?',
- query: {},
- pathname: '/'
- },
- 'http://example.com?foo=bar#frag': {
- href: 'http://example.com/?foo=bar#frag',
- protocol: 'http:',
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag',
- search: '?foo=bar',
- query: 'foo=bar',
- pathname: '/'
- },
- 'http://example.com?foo=@bar#frag': {
- href: 'http://example.com/?foo=@bar#frag',
- protocol: 'http:',
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag',
- search: '?foo=@bar',
- query: 'foo=@bar',
- pathname: '/'
- },
- 'http://example.com?foo=/bar/#frag': {
- href: 'http://example.com/?foo=/bar/#frag',
- protocol: 'http:',
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag',
- search: '?foo=/bar/',
- query: 'foo=/bar/',
- pathname: '/'
- },
- 'http://example.com?foo=?bar/#frag': {
- href: 'http://example.com/?foo=?bar/#frag',
- protocol: 'http:',
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag',
- search: '?foo=?bar/',
- query: 'foo=?bar/',
- pathname: '/'
- },
- 'http://example.com#frag=?bar/#frag': {
- href: 'http://example.com/#frag=?bar/#frag',
- protocol: 'http:',
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag=?bar/#frag',
- pathname: '/'
- },
- 'http://google.com" onload="alert(42)/': {
- href: 'http://google.com/%22%20onload=%22alert(42)/',
- protocol: 'http:',
- host: 'google.com',
- pathname: '/%22%20onload=%22alert(42)/'
- },
- 'http://a.com/a/b/c?s#h': {
- href: 'http://a.com/a/b/c?s#h',
- protocol: 'http',
- host: 'a.com',
- pathname: 'a/b/c',
- hash: 'h',
- search: 's'
- },
- 'xmpp:isaacschlueter@jabber.org': {
- href: 'xmpp:isaacschlueter@jabber.org',
- protocol: 'xmpp:',
- host: 'jabber.org',
- auth: 'isaacschlueter',
- hostname: 'jabber.org'
- },
- 'http://atpass:foo%40bar@127.0.0.1/': {
- href: 'http://atpass:foo%40bar@127.0.0.1/',
- auth: 'atpass:foo@bar',
- hostname: '127.0.0.1',
- protocol: 'http:',
- pathname: '/'
- },
- 'http://atslash%2F%40:%2F%40@foo/': {
- href: 'http://atslash%2F%40:%2F%40@foo/',
- auth: 'atslash/@:/@',
- hostname: 'foo',
- protocol: 'http:',
- pathname: '/'
- },
- 'svn+ssh://foo/bar': {
- href: 'svn+ssh://foo/bar',
- hostname: 'foo',
- protocol: 'svn+ssh:',
- pathname: '/bar',
- slashes: true
- },
- 'dash-test://foo/bar': {
- href: 'dash-test://foo/bar',
- hostname: 'foo',
- protocol: 'dash-test:',
- pathname: '/bar',
- slashes: true
- },
- 'dash-test:foo/bar': {
- href: 'dash-test:foo/bar',
- hostname: 'foo',
- protocol: 'dash-test:',
- pathname: '/bar'
- },
- 'dot.test://foo/bar': {
- href: 'dot.test://foo/bar',
- hostname: 'foo',
- protocol: 'dot.test:',
- pathname: '/bar',
- slashes: true
- },
- 'dot.test:foo/bar': {
- href: 'dot.test:foo/bar',
- hostname: 'foo',
- protocol: 'dot.test:',
- pathname: '/bar'
- },
- // ipv6 support
- 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature': {
- href: 'coap:u:p@[::1]:61616/.well-known/r?n=Temperature',
- protocol: 'coap:',
- auth: 'u:p',
- hostname: '::1',
- port: '61616',
- pathname: '/.well-known/r',
- search: 'n=Temperature'
- },
- 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton': {
- href: 'coap:[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616/s/stopButton',
- protocol: 'coap',
- host: '[fedc:ba98:7654:3210:fedc:ba98:7654:3210]:61616',
- pathname: '/s/stopButton'
- },
-
- // encode context-specific delimiters in path and query, but do not touch
- // other non-delimiter chars like `%`.
- // <https://github.com/joyent/node/issues/4082>
-
- // `#`,`?` in path
- '/path/to/%%23%3F+=&.txt?foo=theA1#bar': {
- href: '/path/to/%%23%3F+=&.txt?foo=theA1#bar',
- pathname: '/path/to/%#?+=&.txt',
- query: {
- foo: 'theA1'
- },
- hash: '#bar'
- },
-
- // `#`,`?` in path + `#` in query
- '/path/to/%%23%3F+=&.txt?foo=the%231#bar': {
- href: '/path/to/%%23%3F+=&.txt?foo=the%231#bar',
- pathname: '/path/to/%#?+=&.txt',
- query: {
- foo: 'the#1'
- },
- hash: '#bar'
- },
-
- // `?` and `#` in path and search
- 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag': {
- href: 'http://ex.com/foo%3F100%m%23r?abc=the%231?&foo=bar#frag',
- protocol: 'http:',
- hostname: 'ex.com',
- hash: '#frag',
- search: '?abc=the#1?&foo=bar',
- pathname: '/foo?100%m#r',
- },
-
- // `?` and `#` in search only
- 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag': {
- href: 'http://ex.com/fooA100%mBr?abc=the%231?&foo=bar#frag',
- protocol: 'http:',
- hostname: 'ex.com',
- hash: '#frag',
- search: '?abc=the#1?&foo=bar',
- pathname: '/fooA100%mBr',
- },
-
- // multiple `#` in search
- 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag': {
- href: 'http://example.com/?foo=bar%231%232%233&abc=%234%23%235#frag',
- protocol: 'http:',
- slashes: true,
- host: 'example.com',
- hostname: 'example.com',
- hash: '#frag',
- search: '?foo=bar#1#2#3&abc=#4##5',
- query: {},
- pathname: '/'
- },
-
- // more than 255 characters in hostname which exceeds the limit
- [`http://${'a'.repeat(255)}.com/node`]: {
- href: 'http:///node',
- protocol: 'http:',
- slashes: true,
- host: '',
- hostname: '',
- pathname: '/node',
- path: '/node'
- },
-
- // greater than or equal to 63 characters after `.` in hostname
- [`http://www.${'z'.repeat(63)}example.com/node`]: {
- href: `http://www.${'z'.repeat(63)}example.com/node`,
- protocol: 'http:',
- slashes: true,
- host: `www.${'z'.repeat(63)}example.com`,
- hostname: `www.${'z'.repeat(63)}example.com`,
- pathname: '/node',
- path: '/node'
- },
-
- // https://github.com/nodejs/node/issues/3361
- 'file:///home/user': {
- href: 'file:///home/user',
- protocol: 'file',
- pathname: '/home/user',
- path: '/home/user'
- }
-};
-for (const u in formatTests) {
- const expect = formatTests[u].href;
- delete formatTests[u].href;
- const actual = url.format(u);
- const actualObj = url.format(formatTests[u]);
- assert.strictEqual(actual, expect,
- 'wonky format(' + u + ') == ' + expect +
- '\nactual:' + actual);
- assert.strictEqual(actualObj, expect,
- 'wonky format(' + JSON.stringify(formatTests[u]) +
- ') == ' + expect +
- '\nactual: ' + actualObj);
-}
-
-/*
- [from, path, expected]
-*/
-const relativeTests = [
- ['/foo/bar/baz', 'quux', '/foo/bar/quux'],
- ['/foo/bar/baz', 'quux/asdf', '/foo/bar/quux/asdf'],
- ['/foo/bar/baz', 'quux/baz', '/foo/bar/quux/baz'],
- ['/foo/bar/baz', '../quux/baz', '/foo/quux/baz'],
- ['/foo/bar/baz', '/bar', '/bar'],
- ['/foo/bar/baz/', 'quux', '/foo/bar/baz/quux'],
- ['/foo/bar/baz/', 'quux/baz', '/foo/bar/baz/quux/baz'],
- ['/foo/bar/baz', '../../../../../../../../quux/baz', '/quux/baz'],
- ['/foo/bar/baz', '../../../../../../../quux/baz', '/quux/baz'],
- ['/foo', '.', '/'],
- ['/foo', '..', '/'],
- ['/foo/', '.', '/foo/'],
- ['/foo/', '..', '/'],
- ['/foo/bar', '.', '/foo/'],
- ['/foo/bar', '..', '/'],
- ['/foo/bar/', '.', '/foo/bar/'],
- ['/foo/bar/', '..', '/foo/'],
- ['foo/bar', '../../../baz', '../../baz'],
- ['foo/bar/', '../../../baz', '../baz'],
- ['http://example.com/b//c//d;p?q#blarg', 'https:#hash2', 'https:///#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'https:/p/a/t/h?s#hash2',
- 'https://p/a/t/h?s#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'https://u:p@h.com/p/a/t/h?s#hash2',
- 'https://u:p@h.com/p/a/t/h?s#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'https:/a/b/c/d',
- 'https://a/b/c/d'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'http:#hash2',
- 'http://example.com/b//c//d;p?q#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'http:/p/a/t/h?s#hash2',
- 'http://example.com/p/a/t/h?s#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'http://u:p@h.com/p/a/t/h?s#hash2',
- 'http://u:p@h.com/p/a/t/h?s#hash2'],
- ['http://example.com/b//c//d;p?q#blarg',
- 'http:/a/b/c/d',
- 'http://example.com/a/b/c/d'],
- ['/foo/bar/baz', '/../etc/passwd', '/etc/passwd'],
- ['http://localhost', 'file:///Users/foo', 'file:///Users/foo'],
- ['http://localhost', 'file://foo/Users', 'file://foo/Users']
-];
-relativeTests.forEach(function(relativeTest) {
- const a = url.resolve(relativeTest[0], relativeTest[1]);
- const e = relativeTest[2];
- assert.strictEqual(a, e,
- 'resolve(' + [relativeTest[0], relativeTest[1]] + ') == ' + e +
- '\n actual=' + a);
-});
-
-
-// https://github.com/joyent/node/issues/568
-[
- undefined,
- null,
- true,
- false,
- 0.0,
- 0,
- [],
- {}
-].forEach(function(val) {
- assert.throws(function() { url.parse(val); }, TypeError);
-});
-
-
-//
-// Tests below taken from Chiron
-// http://code.google.com/p/chironjs/source/browse/trunk/src/test/http/url.js
-//
-// Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
-// used with permission under MIT License
-//
-// Changes marked with @isaacs
-
-const bases = [
- 'http://a/b/c/d;p?q',
- 'http://a/b/c/d;p?q=1/2',
- 'http://a/b/c/d;p=1/2?q',
- 'fred:///s//a/b/c',
- 'http:///s//a/b/c'
-];
-
-//[to, from, result]
-const relativeTests2 = [
- // http://lists.w3.org/Archives/Public/uri/2004Feb/0114.html
- ['../c', 'foo:a/b', 'foo:c'],
- ['foo:.', 'foo:a', 'foo:'],
- ['/foo/../../../bar', 'zz:abc', 'zz:/bar'],
- ['/foo/../bar', 'zz:abc', 'zz:/bar'],
- // @isaacs Disagree. Not how web browsers resolve this.
- ['foo/../../../bar', 'zz:abc', 'zz:bar'],
- // ['foo/../../../bar', 'zz:abc', 'zz:../../bar'], // @isaacs Added
- ['foo/../bar', 'zz:abc', 'zz:bar'],
- ['zz:.', 'zz:abc', 'zz:'],
- ['/.', bases[0], 'http://a/'],
- ['/.foo', bases[0], 'http://a/.foo'],
- ['.foo', bases[0], 'http://a/b/c/.foo'],
-
- // http://gbiv.com/protocols/uri/test/rel_examples1.html
- // examples from RFC 2396
- ['g:h', bases[0], 'g:h'],
- ['g', bases[0], 'http://a/b/c/g'],
- ['./g', bases[0], 'http://a/b/c/g'],
- ['g/', bases[0], 'http://a/b/c/g/'],
- ['/g', bases[0], 'http://a/g'],
- ['//g', bases[0], 'http://g/'],
- // changed with RFC 2396bis
- //('?y', bases[0], 'http://a/b/c/d;p?y'],
- ['?y', bases[0], 'http://a/b/c/d;p?y'],
- ['g?y', bases[0], 'http://a/b/c/g?y'],
- // changed with RFC 2396bis
- //('#s', bases[0], CURRENT_DOC_URI + '#s'],
- ['#s', bases[0], 'http://a/b/c/d;p?q#s'],
- ['g#s', bases[0], 'http://a/b/c/g#s'],
- ['g?y#s', bases[0], 'http://a/b/c/g?y#s'],
- [';x', bases[0], 'http://a/b/c/;x'],
- ['g;x', bases[0], 'http://a/b/c/g;x'],
- ['g;x?y#s', bases[0], 'http://a/b/c/g;x?y#s'],
- // changed with RFC 2396bis
- //('', bases[0], CURRENT_DOC_URI],
- ['', bases[0], 'http://a/b/c/d;p?q'],
- ['.', bases[0], 'http://a/b/c/'],
- ['./', bases[0], 'http://a/b/c/'],
- ['..', bases[0], 'http://a/b/'],
- ['../', bases[0], 'http://a/b/'],
- ['../g', bases[0], 'http://a/b/g'],
- ['../..', bases[0], 'http://a/'],
- ['../../', bases[0], 'http://a/'],
- ['../../g', bases[0], 'http://a/g'],
- ['../../../g', bases[0], ('http://a/../g', 'http://a/g')],
- ['../../../../g', bases[0], ('http://a/../../g', 'http://a/g')],
- // changed with RFC 2396bis
- //('/./g', bases[0], 'http://a/./g'],
- ['/./g', bases[0], 'http://a/g'],
- // changed with RFC 2396bis
- //('/../g', bases[0], 'http://a/../g'],
- ['/../g', bases[0], 'http://a/g'],
- ['g.', bases[0], 'http://a/b/c/g.'],
- ['.g', bases[0], 'http://a/b/c/.g'],
- ['g..', bases[0], 'http://a/b/c/g..'],
- ['..g', bases[0], 'http://a/b/c/..g'],
- ['./../g', bases[0], 'http://a/b/g'],
- ['./g/.', bases[0], 'http://a/b/c/g/'],
- ['g/./h', bases[0], 'http://a/b/c/g/h'],
- ['g/../h', bases[0], 'http://a/b/c/h'],
- ['g;x=1/./y', bases[0], 'http://a/b/c/g;x=1/y'],
- ['g;x=1/../y', bases[0], 'http://a/b/c/y'],
- ['g?y/./x', bases[0], 'http://a/b/c/g?y/./x'],
- ['g?y/../x', bases[0], 'http://a/b/c/g?y/../x'],
- ['g#s/./x', bases[0], 'http://a/b/c/g#s/./x'],
- ['g#s/../x', bases[0], 'http://a/b/c/g#s/../x'],
- ['http:g', bases[0], ('http:g', 'http://a/b/c/g')],
- ['http:', bases[0], ('http:', bases[0])],
- // not sure where this one originated
- ['/a/b/c/./../../g', bases[0], 'http://a/a/g'],
-
- // http://gbiv.com/protocols/uri/test/rel_examples2.html
- // slashes in base URI's query args
- ['g', bases[1], 'http://a/b/c/g'],
- ['./g', bases[1], 'http://a/b/c/g'],
- ['g/', bases[1], 'http://a/b/c/g/'],
- ['/g', bases[1], 'http://a/g'],
- ['//g', bases[1], 'http://g/'],
- // changed in RFC 2396bis
- //('?y', bases[1], 'http://a/b/c/?y'],
- ['?y', bases[1], 'http://a/b/c/d;p?y'],
- ['g?y', bases[1], 'http://a/b/c/g?y'],
- ['g?y/./x', bases[1], 'http://a/b/c/g?y/./x'],
- ['g?y/../x', bases[1], 'http://a/b/c/g?y/../x'],
- ['g#s', bases[1], 'http://a/b/c/g#s'],
- ['g#s/./x', bases[1], 'http://a/b/c/g#s/./x'],
- ['g#s/../x', bases[1], 'http://a/b/c/g#s/../x'],
- ['./', bases[1], 'http://a/b/c/'],
- ['../', bases[1], 'http://a/b/'],
- ['../g', bases[1], 'http://a/b/g'],
- ['../../', bases[1], 'http://a/'],
- ['../../g', bases[1], 'http://a/g'],
-
- // http://gbiv.com/protocols/uri/test/rel_examples3.html
- // slashes in path params
- // all of these changed in RFC 2396bis
- ['g', bases[2], 'http://a/b/c/d;p=1/g'],
- ['./g', bases[2], 'http://a/b/c/d;p=1/g'],
- ['g/', bases[2], 'http://a/b/c/d;p=1/g/'],
- ['g?y', bases[2], 'http://a/b/c/d;p=1/g?y'],
- [';x', bases[2], 'http://a/b/c/d;p=1/;x'],
- ['g;x', bases[2], 'http://a/b/c/d;p=1/g;x'],
- ['g;x=1/./y', bases[2], 'http://a/b/c/d;p=1/g;x=1/y'],
- ['g;x=1/../y', bases[2], 'http://a/b/c/d;p=1/y'],
- ['./', bases[2], 'http://a/b/c/d;p=1/'],
- ['../', bases[2], 'http://a/b/c/'],
- ['../g', bases[2], 'http://a/b/c/g'],
- ['../../', bases[2], 'http://a/b/'],
- ['../../g', bases[2], 'http://a/b/g'],
-
- // http://gbiv.com/protocols/uri/test/rel_examples4.html
- // double and triple slash, unknown scheme
- ['g:h', bases[3], 'g:h'],
- ['g', bases[3], 'fred:///s//a/b/g'],
- ['./g', bases[3], 'fred:///s//a/b/g'],
- ['g/', bases[3], 'fred:///s//a/b/g/'],
- ['/g', bases[3], 'fred:///g'], // may change to fred:///s//a/g
- ['//g', bases[3], 'fred://g'], // may change to fred:///s//g
- ['//g/x', bases[3], 'fred://g/x'], // may change to fred:///s//g/x
- ['///g', bases[3], 'fred:///g'],
- ['./', bases[3], 'fred:///s//a/b/'],
- ['../', bases[3], 'fred:///s//a/'],
- ['../g', bases[3], 'fred:///s//a/g'],
-
- ['../../', bases[3], 'fred:///s//'],
- ['../../g', bases[3], 'fred:///s//g'],
- ['../../../g', bases[3], 'fred:///s/g'],
- // may change to fred:///s//a/../../../g
- ['../../../../g', bases[3], 'fred:///g'],
-
- // http://gbiv.com/protocols/uri/test/rel_examples5.html
- // double and triple slash, well-known scheme
- ['g:h', bases[4], 'g:h'],
- ['g', bases[4], 'http:///s//a/b/g'],
- ['./g', bases[4], 'http:///s//a/b/g'],
- ['g/', bases[4], 'http:///s//a/b/g/'],
- ['/g', bases[4], 'http:///g'], // may change to http:///s//a/g
- ['//g', bases[4], 'http://g/'], // may change to http:///s//g
- ['//g/x', bases[4], 'http://g/x'], // may change to http:///s//g/x
- ['///g', bases[4], 'http:///g'],
- ['./', bases[4], 'http:///s//a/b/'],
- ['../', bases[4], 'http:///s//a/'],
- ['../g', bases[4], 'http:///s//a/g'],
- ['../../', bases[4], 'http:///s//'],
- ['../../g', bases[4], 'http:///s//g'],
- // may change to http:///s//a/../../g
- ['../../../g', bases[4], 'http:///s/g'],
- // may change to http:///s//a/../../../g
- ['../../../../g', bases[4], 'http:///g'],
-
- // from Dan Connelly's tests in http://www.w3.org/2000/10/swap/uripath.py
- ['bar:abc', 'foo:xyz', 'bar:abc'],
- ['../abc', 'http://example/x/y/z', 'http://example/x/abc'],
- ['http://example/x/abc', 'http://example2/x/y/z', 'http://example/x/abc'],
- ['../r', 'http://ex/x/y/z', 'http://ex/x/r'],
- ['q/r', 'http://ex/x/y', 'http://ex/x/q/r'],
- ['q/r#s', 'http://ex/x/y', 'http://ex/x/q/r#s'],
- ['q/r#s/t', 'http://ex/x/y', 'http://ex/x/q/r#s/t'],
- ['ftp://ex/x/q/r', 'http://ex/x/y', 'ftp://ex/x/q/r'],
- ['', 'http://ex/x/y', 'http://ex/x/y'],
- ['', 'http://ex/x/y/', 'http://ex/x/y/'],
- ['', 'http://ex/x/y/pdq', 'http://ex/x/y/pdq'],
- ['z/', 'http://ex/x/y/', 'http://ex/x/y/z/'],
- ['#Animal',
- 'file:/swap/test/animal.rdf',
- 'file:/swap/test/animal.rdf#Animal'],
- ['../abc', 'file:/e/x/y/z', 'file:/e/x/abc'],
- ['/example/x/abc', 'file:/example2/x/y/z', 'file:/example/x/abc'],
- ['../r', 'file:/ex/x/y/z', 'file:/ex/x/r'],
- ['/r', 'file:/ex/x/y/z', 'file:/r'],
- ['q/r', 'file:/ex/x/y', 'file:/ex/x/q/r'],
- ['q/r#s', 'file:/ex/x/y', 'file:/ex/x/q/r#s'],
- ['q/r#', 'file:/ex/x/y', 'file:/ex/x/q/r#'],
- ['q/r#s/t', 'file:/ex/x/y', 'file:/ex/x/q/r#s/t'],
- ['ftp://ex/x/q/r', 'file:/ex/x/y', 'ftp://ex/x/q/r'],
- ['', 'file:/ex/x/y', 'file:/ex/x/y'],
- ['', 'file:/ex/x/y/', 'file:/ex/x/y/'],
- ['', 'file:/ex/x/y/pdq', 'file:/ex/x/y/pdq'],
- ['z/', 'file:/ex/x/y/', 'file:/ex/x/y/z/'],
- ['file://meetings.example.com/cal#m1',
- 'file:/devel/WWW/2000/10/swap/test/reluri-1.n3',
- 'file://meetings.example.com/cal#m1'],
- ['file://meetings.example.com/cal#m1',
- 'file:/home/connolly/w3ccvs/WWW/2000/10/swap/test/reluri-1.n3',
- 'file://meetings.example.com/cal#m1'],
- ['./#blort', 'file:/some/dir/foo', 'file:/some/dir/#blort'],
- ['./#', 'file:/some/dir/foo', 'file:/some/dir/#'],
- // Ryan Lee
- ['./', 'http://example/x/abc.efg', 'http://example/x/'],
-
-
- // Graham Klyne's tests
- // http://www.ninebynine.org/Software/HaskellUtils/Network/UriTest.xls
- // 01-31 are from Connelly's cases
-
- // 32-49
- ['./q:r', 'http://ex/x/y', 'http://ex/x/q:r'],
- ['./p=q:r', 'http://ex/x/y', 'http://ex/x/p=q:r'],
- ['?pp/rr', 'http://ex/x/y?pp/qq', 'http://ex/x/y?pp/rr'],
- ['y/z', 'http://ex/x/y?pp/qq', 'http://ex/x/y/z'],
- ['local/qual@domain.org#frag',
- 'mailto:local',
- 'mailto:local/qual@domain.org#frag'],
- ['more/qual2@domain2.org#frag',
- 'mailto:local/qual1@domain1.org',
- 'mailto:local/more/qual2@domain2.org#frag'],
- ['y?q', 'http://ex/x/y?q', 'http://ex/x/y?q'],
- ['/x/y?q', 'http://ex?p', 'http://ex/x/y?q'],
- ['c/d', 'foo:a/b', 'foo:a/c/d'],
- ['/c/d', 'foo:a/b', 'foo:/c/d'],
- ['', 'foo:a/b?c#d', 'foo:a/b?c'],
- ['b/c', 'foo:a', 'foo:b/c'],
- ['../b/c', 'foo:/a/y/z', 'foo:/a/b/c'],
- ['./b/c', 'foo:a', 'foo:b/c'],
- ['/./b/c', 'foo:a', 'foo:/b/c'],
- ['../../d', 'foo://a//b/c', 'foo://a/d'],
- ['.', 'foo:a', 'foo:'],
- ['..', 'foo:a', 'foo:'],
-
- // 50-57[cf. TimBL comments --
- // http://lists.w3.org/Archives/Public/uri/2003Feb/0028.html,
- // http://lists.w3.org/Archives/Public/uri/2003Jan/0008.html)
- ['abc', 'http://example/x/y%2Fz', 'http://example/x/abc'],
- ['../../x%2Fabc', 'http://example/a/x/y/z', 'http://example/a/x%2Fabc'],
- ['../x%2Fabc', 'http://example/a/x/y%2Fz', 'http://example/a/x%2Fabc'],
- ['abc', 'http://example/x%2Fy/z', 'http://example/x%2Fy/abc'],
- ['q%3Ar', 'http://ex/x/y', 'http://ex/x/q%3Ar'],
- ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
- ['/x%2Fabc', 'http://example/x/y/z', 'http://example/x%2Fabc'],
- ['/x%2Fabc', 'http://example/x/y%2Fz', 'http://example/x%2Fabc'],
-
- // 70-77
- ['local2@domain2', 'mailto:local1@domain1?query1', 'mailto:local2@domain2'],
- ['local2@domain2?query2',
- 'mailto:local1@domain1',
- 'mailto:local2@domain2?query2'],
- ['local2@domain2?query2',
- 'mailto:local1@domain1?query1',
- 'mailto:local2@domain2?query2'],
- ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
- ['local@domain?query2', 'mailto:?query1', 'mailto:local@domain?query2'],
- ['?query2', 'mailto:local@domain?query1', 'mailto:local@domain?query2'],
- ['http://example/a/b?c/../d', 'foo:bar', 'http://example/a/b?c/../d'],
- ['http://example/a/b#c/../d', 'foo:bar', 'http://example/a/b#c/../d'],
-
- // 82-88
- // @isaacs Disagree. Not how browsers do it.
- // ['http:this', 'http://example.org/base/uri', 'http:this'],
- // @isaacs Added
- ['http:this', 'http://example.org/base/uri', 'http://example.org/base/this'],
- ['http:this', 'http:base', 'http:this'],
- ['.//g', 'f:/a', 'f://g'],
- ['b/c//d/e', 'f://example.org/base/a', 'f://example.org/base/b/c//d/e'],
- ['m2@example.ord/c2@example.org',
- 'mid:m@example.ord/c@example.org',
- 'mid:m@example.ord/m2@example.ord/c2@example.org'],
- ['mini1.xml',
- 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/',
- 'file:///C:/DEV/Haskell/lib/HXmlToolbox-3.01/examples/mini1.xml'],
- ['../b/c', 'foo:a/y/z', 'foo:a/b/c'],
-
- //changeing auth
- ['http://diff:auth@www.example.com',
- 'http://asdf:qwer@www.example.com',
- 'http://diff:auth@www.example.com/'],
-
- // changing port
- ['https://example.com:81/',
- 'https://example.com:82/',
- 'https://example.com:81/'],
-
- // https://github.com/nodejs/node/issues/1435
- ['https://another.host.com/',
- 'https://user:password@example.org/',
- 'https://another.host.com/'],
- ['//another.host.com/',
- 'https://user:password@example.org/',
- 'https://another.host.com/'],
- ['http://another.host.com/',
- 'https://user:password@example.org/',
- 'http://another.host.com/'],
- ['mailto:another.host.com',
- 'mailto:user@example.org',
- 'mailto:another.host.com'],
- ['https://example.com/foo',
- 'https://user:password@example.com',
- 'https://user:password@example.com/foo'],
-];
-relativeTests2.forEach(function(relativeTest) {
- const a = url.resolve(relativeTest[1], relativeTest[0]);
- const e = url.format(relativeTest[2]);
- assert.strictEqual(a, e,
- 'resolve(' + [relativeTest[1], relativeTest[0]] + ') == ' + e +
- '\n actual=' + a);
-});
-
-//if format and parse are inverse operations then
-//resolveObject(parse(x), y) == parse(resolve(x, y))
-
-//format: [from, path, expected]
-relativeTests.forEach(function(relativeTest) {
- let actual = url.resolveObject(url.parse(relativeTest[0]), relativeTest[1]);
- let expected = url.parse(relativeTest[2]);
-
-
- assert.deepStrictEqual(actual, expected);
-
- expected = relativeTest[2];
- actual = url.format(actual);
-
- assert.strictEqual(actual, expected,
- 'format(' + actual + ') == ' + expected + '\nactual:' + actual);
-});
-
-//format: [to, from, result]
-// the test: ['.//g', 'f:/a', 'f://g'] is a fundamental problem
-// url.parse('f:/a') does not have a host
-// url.resolve('f:/a', './/g') does not have a host because you have moved
-// down to the g directory. i.e. f: //g, however when this url is parsed
-// f:// will indicate that the host is g which is not the case.
-// it is unclear to me how to keep this information from being lost
-// it may be that a pathname of ////g should collapse to /g but this seems
-// to be a lot of work for an edge case. Right now I remove the test
-if (relativeTests2[181][0] === './/g' &&
- relativeTests2[181][1] === 'f:/a' &&
- relativeTests2[181][2] === 'f://g') {
- relativeTests2.splice(181, 1);
-}
-relativeTests2.forEach(function(relativeTest) {
- let actual = url.resolveObject(url.parse(relativeTest[1]), relativeTest[0]);
- let expected = url.parse(relativeTest[2]);
-
- assert.deepStrictEqual(
- actual,
- expected,
- `expected ${inspect(expected)} but got ${inspect(actual)}`
- );
-
- expected = url.format(relativeTest[2]);
- actual = url.format(actual);
-
- assert.strictEqual(actual, expected,
- 'format(' + relativeTest[1] + ') == ' + expected +
- '\nactual:' + actual);
-});
-
-
-// https://github.com/nodejs/node/pull/1036
-const throws = [
- undefined,
- null,
- true,
- false,
- 0,
- function() {}
-];
-for (let i = 0; i < throws.length; i++) {
- assert.throws(function() { url.format(throws[i]); }, TypeError);
-}
-assert.strictEqual(url.format(''), '');
-assert.strictEqual(url.format({}), '');