From 7a1d633d77ceda478227f26ac310481f604a1ec3 Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Thu, 12 Sep 2024 20:29:55 -0400 Subject: [PATCH] test: move more url tests to `node:test` PR-URL: https://github.com/nodejs/node/pull/54636 Reviewed-By: James M Snell Reviewed-By: Moshe Atlow Reviewed-By: Colin Ihrig --- .../parallel/test-url-domain-ascii-unicode.js | 26 +- test/parallel/test-url-fileurltopath.js | 81 +-- .../parallel/test-url-format-invalid-input.js | 51 +- test/parallel/test-url-format-whatwg.js | 266 ++++----- test/parallel/test-url-format.js | 519 +++++++++--------- test/parallel/test-url-is-url-internal.js | 19 + test/parallel/test-url-is-url.js | 16 - test/parallel/test-url-null-char.js | 8 - test/parallel/test-url-parse-format.js | 75 ++- 9 files changed, 533 insertions(+), 528 deletions(-) create mode 100644 test/parallel/test-url-is-url-internal.js delete mode 100644 test/parallel/test-url-is-url.js delete mode 100644 test/parallel/test-url-null-char.js diff --git a/test/parallel/test-url-domain-ascii-unicode.js b/test/parallel/test-url-domain-ascii-unicode.js index 737294c241fbfe..f0a2f3db13960f 100644 --- a/test/parallel/test-url-domain-ascii-unicode.js +++ b/test/parallel/test-url-domain-ascii-unicode.js @@ -1,14 +1,10 @@ 'use strict'; -const common = require('../common'); -if (!common.hasIntl) - common.skip('missing Intl'); +const { hasIntl } = require('../common'); -const strictEqual = require('assert').strictEqual; -const url = require('url'); - -const domainToASCII = url.domainToASCII; -const domainToUnicode = url.domainToUnicode; +const { strictEqual } = require('node:assert'); +const { domainToASCII, domainToUnicode } = require('node:url'); +const { test } = require('node:test'); const domainWithASCII = [ ['ıíd', 'xn--d-iga7r'], @@ -21,11 +17,11 @@ const domainWithASCII = [ ['भारत.org', 'xn--h2brj9c.org'], ]; -domainWithASCII.forEach((pair) => { - const domain = pair[0]; - const ascii = pair[1]; - const domainConvertedToASCII = domainToASCII(domain); - strictEqual(domainConvertedToASCII, ascii); - const asciiConvertedToUnicode = domainToUnicode(ascii); - strictEqual(asciiConvertedToUnicode, domain); +test('domainToASCII and domainToUnicode', { skip: !hasIntl }, () => { + for (const [domain, ascii] of domainWithASCII) { + const domainConvertedToASCII = domainToASCII(domain); + strictEqual(domainConvertedToASCII, ascii); + const asciiConvertedToUnicode = domainToUnicode(ascii); + strictEqual(asciiConvertedToUnicode, domain); + } }); diff --git a/test/parallel/test-url-fileurltopath.js b/test/parallel/test-url-fileurltopath.js index 6bd4e280483a19..338efacaa1a62c 100644 --- a/test/parallel/test-url-fileurltopath.js +++ b/test/parallel/test-url-fileurltopath.js @@ -1,25 +1,25 @@ 'use strict'; const { isWindows } = require('../common'); -const assert = require('assert'); -const url = require('url'); -function testInvalidArgs(...args) { - for (const arg of args) { +const { test } = require('node:test'); +const assert = require('node:assert'); +const url = require('node:url'); + +test('invalid arguments', () => { + for (const arg of [null, undefined, 1, {}, true]) { assert.throws(() => url.fileURLToPath(arg), { code: 'ERR_INVALID_ARG_TYPE' }); } -} - -// Input must be string or URL -testInvalidArgs(null, undefined, 1, {}, true); +}); -// Input must be a file URL -assert.throws(() => url.fileURLToPath('https://a/b/c'), { - code: 'ERR_INVALID_URL_SCHEME' +test('input must be a file URL', () => { + assert.throws(() => url.fileURLToPath('https://a/b/c'), { + code: 'ERR_INVALID_URL_SCHEME' + }); }); -{ +test('fileURLToPath with host', () => { const withHost = new URL('file://host/a'); if (isWindows) { @@ -29,9 +29,9 @@ assert.throws(() => url.fileURLToPath('https://a/b/c'), { code: 'ERR_INVALID_FILE_URL_HOST' }); } -} +}); -{ +test('fileURLToPath with invalid path', () => { if (isWindows) { assert.throws(() => url.fileURLToPath('file:///C:/a%2F/'), { code: 'ERR_INVALID_FILE_URL_PATH' @@ -47,7 +47,7 @@ assert.throws(() => url.fileURLToPath('https://a/b/c'), { code: 'ERR_INVALID_FILE_URL_PATH' }); } -} +}); const windowsTestCases = [ // Lowercase ascii alpha @@ -95,6 +95,7 @@ const windowsTestCases = [ // UNC path (see https://docs.microsoft.com/en-us/archive/blogs/ie/file-uris-in-windows) { path: '\\\\nas\\My Docs\\File.doc', fileURL: 'file://nas/My%20Docs/File.doc' }, ]; + const posixTestCases = [ // Lowercase ascii alpha { path: '/foo', fileURL: 'file:///foo' }, @@ -140,29 +141,37 @@ const posixTestCases = [ { path: '/🚀', fileURL: 'file:///%F0%9F%9A%80' }, ]; -for (const { path, fileURL } of windowsTestCases) { - const fromString = url.fileURLToPath(fileURL, { windows: true }); - assert.strictEqual(fromString, path); - const fromURL = url.fileURLToPath(new URL(fileURL), { windows: true }); - assert.strictEqual(fromURL, path); -} +test('fileURLToPath with windows path', { skip: !isWindows }, () => { + + for (const { path, fileURL } of windowsTestCases) { + const fromString = url.fileURLToPath(fileURL, { windows: true }); + assert.strictEqual(fromString, path); + const fromURL = url.fileURLToPath(new URL(fileURL), { windows: true }); + assert.strictEqual(fromURL, path); + } +}); -for (const { path, fileURL } of posixTestCases) { - const fromString = url.fileURLToPath(fileURL, { windows: false }); - assert.strictEqual(fromString, path); - const fromURL = url.fileURLToPath(new URL(fileURL), { windows: false }); - assert.strictEqual(fromURL, path); -} +test('fileURLToPath with posix path', { skip: isWindows }, () => { + for (const { path, fileURL } of posixTestCases) { + const fromString = url.fileURLToPath(fileURL, { windows: false }); + assert.strictEqual(fromString, path); + const fromURL = url.fileURLToPath(new URL(fileURL), { windows: false }); + assert.strictEqual(fromURL, path); + } +}); const defaultTestCases = isWindows ? windowsTestCases : posixTestCases; -// Test when `options` is null -const whenNullActual = url.fileURLToPath(new URL(defaultTestCases[0].fileURL), null); -assert.strictEqual(whenNullActual, defaultTestCases[0].path); +test('options is null', () => { + const whenNullActual = url.fileURLToPath(new URL(defaultTestCases[0].fileURL), null); + assert.strictEqual(whenNullActual, defaultTestCases[0].path); +}); -for (const { path, fileURL } of defaultTestCases) { - const fromString = url.fileURLToPath(fileURL); - assert.strictEqual(fromString, path); - const fromURL = url.fileURLToPath(new URL(fileURL)); - assert.strictEqual(fromURL, path); -} +test('defaultTestCases', () => { + for (const { path, fileURL } of defaultTestCases) { + const fromString = url.fileURLToPath(fileURL); + assert.strictEqual(fromString, path); + const fromURL = url.fileURLToPath(new URL(fileURL)); + assert.strictEqual(fromURL, path); + } +}); diff --git a/test/parallel/test-url-format-invalid-input.js b/test/parallel/test-url-format-invalid-input.js index efa1a9ba1df6bf..4395ececfe64bf 100644 --- a/test/parallel/test-url-format-invalid-input.js +++ b/test/parallel/test-url-format-invalid-input.js @@ -1,27 +1,30 @@ 'use strict'; -const common = require('../common'); -const assert = require('assert'); -const url = require('url'); -const throwsObjsAndReportTypes = [ - undefined, - null, - true, - false, - 0, - function() {}, - Symbol('foo'), -]; +require('../common'); -for (const urlObject of throwsObjsAndReportTypes) { - assert.throws(() => { - url.format(urlObject); - }, { - code: 'ERR_INVALID_ARG_TYPE', - name: 'TypeError', - message: 'The "urlObject" argument must be one of type object or string.' + - common.invalidArgTypeHelper(urlObject) - }); -} -assert.strictEqual(url.format(''), ''); -assert.strictEqual(url.format({}), ''); +const assert = require('node:assert'); +const url = require('node:url'); +const { test } = require('node:test'); + +test('format invalid input', () => { + const throwsObjsAndReportTypes = [ + undefined, + null, + true, + false, + 0, + function() {}, + Symbol('foo'), + ]; + + for (const urlObject of throwsObjsAndReportTypes) { + assert.throws(() => { + url.format(urlObject); + }, { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', + }); + } + assert.strictEqual(url.format(''), ''); + assert.strictEqual(url.format({}), ''); +}); diff --git a/test/parallel/test-url-format-whatwg.js b/test/parallel/test-url-format-whatwg.js index bf9f8eaac63246..f399e0faf1d16a 100644 --- a/test/parallel/test-url-format-whatwg.js +++ b/test/parallel/test-url-format-whatwg.js @@ -1,147 +1,149 @@ 'use strict'; -const common = require('../common'); -if (!common.hasIntl) - common.skip('missing Intl'); +const { hasIntl } = require('../common'); -const assert = require('assert'); -const url = require('url'); +const assert = require('node:assert'); +const url = require('node:url'); +const { test } = require('node:test'); const myURL = new URL('http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c'); -assert.strictEqual( - url.format(myURL), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); +test('should format', { skip: !hasIntl }, () => { + assert.strictEqual( + url.format(myURL), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); -assert.strictEqual( - url.format(myURL, {}), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); + assert.strictEqual( + url.format(myURL, {}), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); +}); -{ - [true, 1, 'test', Infinity].forEach((value) => { +test('handle invalid arguments', { skip: !hasIntl }, () => { + for (const value of [true, 1, 'test', Infinity]) { assert.throws( () => url.format(myURL, value), { code: 'ERR_INVALID_ARG_TYPE', name: 'TypeError', - message: 'The "options" argument must be of type object.' + - common.invalidArgTypeHelper(value) } ); - }); -} - -// Any falsy value other than undefined will be treated as false. -// Any truthy value will be treated as true. - -assert.strictEqual( - url.format(myURL, { auth: false }), - 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { auth: '' }), - 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { auth: 0 }), - 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { auth: 1 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { auth: {} }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { fragment: false }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' -); - -assert.strictEqual( - url.format(myURL, { fragment: '' }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' -); - -assert.strictEqual( - url.format(myURL, { fragment: 0 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' -); - -assert.strictEqual( - url.format(myURL, { fragment: 1 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { fragment: {} }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { search: false }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' -); - -assert.strictEqual( - url.format(myURL, { search: '' }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' -); - -assert.strictEqual( - url.format(myURL, { search: 0 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' -); - -assert.strictEqual( - url.format(myURL, { search: 1 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { search: {} }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { unicode: true }), - 'http://user:pass@理容ナカムラ.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { unicode: 1 }), - 'http://user:pass@理容ナカムラ.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { unicode: {} }), - 'http://user:pass@理容ナカムラ.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { unicode: false }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(myURL, { unicode: 0 }), - 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' -); - -assert.strictEqual( - url.format(new URL('http://user:pass@xn--0zwm56d.com:8080/path'), { unicode: true }), - 'http://user:pass@测试.com:8080/path' -); - -assert.strictEqual( - url.format(new URL('tel:123')), - url.format(new URL('tel:123'), { unicode: true }) -); + } +}); + +test('any falsy value other than undefined will be treated as false', { skip: !hasIntl }, () => { + assert.strictEqual( + url.format(myURL, { auth: false }), + 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { auth: '' }), + 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { auth: 0 }), + 'http://xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { auth: 1 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { auth: {} }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { fragment: false }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' + ); + + assert.strictEqual( + url.format(myURL, { fragment: '' }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' + ); + + assert.strictEqual( + url.format(myURL, { fragment: 0 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b' + ); + + assert.strictEqual( + url.format(myURL, { fragment: 1 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { fragment: {} }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { search: false }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' + ); + + assert.strictEqual( + url.format(myURL, { search: '' }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' + ); + + assert.strictEqual( + url.format(myURL, { search: 0 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a#c' + ); + + assert.strictEqual( + url.format(myURL, { search: 1 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { search: {} }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { unicode: true }), + 'http://user:pass@理容ナカムラ.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { unicode: 1 }), + 'http://user:pass@理容ナカムラ.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { unicode: {} }), + 'http://user:pass@理容ナカムラ.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { unicode: false }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); + + assert.strictEqual( + url.format(myURL, { unicode: 0 }), + 'http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c' + ); +}); + +test('should format with unicode: true', { skip: !hasIntl }, () => { + assert.strictEqual( + url.format(new URL('http://user:pass@xn--0zwm56d.com:8080/path'), { unicode: true }), + 'http://user:pass@测试.com:8080/path' + ); +}); + +test('should format tel: prefix', { skip: !hasIntl }, () => { + assert.strictEqual( + url.format(new URL('tel:123')), + url.format(new URL('tel:123'), { unicode: true }) + ); +}); diff --git a/test/parallel/test-url-format.js b/test/parallel/test-url-format.js index 883d060ac2a152..4de8f51ef27e48 100644 --- a/test/parallel/test-url-format.js +++ b/test/parallel/test-url-format.js @@ -1,277 +1,278 @@ 'use strict'; -const common = require('../common'); -const assert = require('assert'); -const url = require('url'); -if (!common.hasIntl) - common.skip('missing Intl'); +const { hasIntl } = require('../common'); -// Formatting tests 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' - }, - 'http://[::]/': { - href: 'http://[::]/', - protocol: 'http:', - hostname: '[::]', - pathname: '/' - }, +const assert = require('node:assert'); +const url = require('node:url'); +const { test } = require('node:test'); - // Encode context-specific delimiters in path and query, but do not touch - // other non-delimiter chars like `%`. - // +test('format slightly wonky content to a valid URL', { skip: !hasIntl }, () => { + 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' + }, + 'http://[::]/': { + href: 'http://[::]/', + protocol: 'http:', + hostname: '[::]', + pathname: '/' + }, + + // Encode context-specific delimiters in path and query, but do not touch + // other non-delimiter chars like `%`. + // - // `#`,`?` 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' + // `#`,`?` 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' }, - 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' + // `#`,`?` 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' }, - hash: '#bar' - }, - // `#` in path end + `#` in query - '/path/to/%%23?foo=the%231#bar': { - href: '/path/to/%%23?foo=the%231#bar', - pathname: '/path/to/%#', - query: { - foo: 'the#1' + // `#` in path end + `#` in query + '/path/to/%%23?foo=the%231#bar': { + href: '/path/to/%%23?foo=the%231#bar', + pathname: '/path/to/%#', + query: { + foo: 'the#1' + }, + hash: '#bar' }, - 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 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', - }, + // `?` 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: '/' + }, - // 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' + }, - // 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' + }, - // 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' + }, - // https://github.com/nodejs/node/issues/3361 - 'file:///home/user': { - href: 'file:///home/user', - protocol: 'file', - pathname: '/home/user', - path: '/home/user' - }, + // surrogate in auth + 'http://%F0%9F%98%80@www.example.com/': { + href: 'http://%F0%9F%98%80@www.example.com/', + protocol: 'http:', + auth: '\uD83D\uDE00', + hostname: 'www.example.com', + pathname: '/' + } + }; - // surrogate in auth - 'http://%F0%9F%98%80@www.example.com/': { - href: 'http://%F0%9F%98%80@www.example.com/', - protocol: 'http:', - auth: '\uD83D\uDE00', - hostname: 'www.example.com', - pathname: '/' + 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}`); } -}; -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-is-url-internal.js b/test/parallel/test-url-is-url-internal.js new file mode 100644 index 00000000000000..b7b67b637f3a1b --- /dev/null +++ b/test/parallel/test-url-is-url-internal.js @@ -0,0 +1,19 @@ +// Flags: --expose-internals +'use strict'; + +require('../common'); + +const { URL, parse } = require('node:url'); +const assert = require('node:assert'); +const { isURL } = require('internal/url'); +const { test } = require('node:test'); + +test('isURL', () => { + assert.strictEqual(isURL(new URL('https://www.nodejs.org')), true); + assert.strictEqual(isURL(parse('https://www.nodejs.org')), false); + assert.strictEqual(isURL({ + href: 'https://www.nodejs.org', + protocol: 'https:', + path: '/', + }), false); +}); diff --git a/test/parallel/test-url-is-url.js b/test/parallel/test-url-is-url.js deleted file mode 100644 index 6bb8a1595df2a0..00000000000000 --- a/test/parallel/test-url-is-url.js +++ /dev/null @@ -1,16 +0,0 @@ -// Flags: --expose-internals -'use strict'; - -require('../common'); - -const { URL, parse } = require('url'); -const assert = require('assert'); -const { isURL } = require('internal/url'); - -assert.strictEqual(isURL(new URL('https://www.nodejs.org')), true); -assert.strictEqual(isURL(parse('https://www.nodejs.org')), false); -assert.strictEqual(isURL({ - href: 'https://www.nodejs.org', - protocol: 'https:', - path: '/', -}), false); diff --git a/test/parallel/test-url-null-char.js b/test/parallel/test-url-null-char.js deleted file mode 100644 index d81cbcfb6648d8..00000000000000 --- a/test/parallel/test-url-null-char.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; -require('../common'); -const assert = require('assert'); - -assert.throws( - () => { new URL('a\0b'); }, - { code: 'ERR_INVALID_URL', input: 'a\0b' } -); diff --git a/test/parallel/test-url-parse-format.js b/test/parallel/test-url-parse-format.js index f8761514a30b72..4e36e1306d3f51 100644 --- a/test/parallel/test-url-parse-format.js +++ b/test/parallel/test-url-parse-format.js @@ -1,13 +1,10 @@ 'use strict'; -const common = require('../common'); +const { hasIntl } = require('../common'); -if (!common.hasIntl) - common.skip('missing Intl'); - -const assert = require('assert'); -const inspect = require('util').inspect; - -const url = require('url'); +const assert = require('node:assert'); +const { inspect } = require('node:util'); +const url = require('node:url'); +const { test } = require('node:test'); // URLs to parse, and expected data // { url : parsed } @@ -1025,36 +1022,38 @@ const parseTests = { } }; -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; - } - }); +test('should parse and format', { skip: !hasIntl }, () => { + 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, + `parsing ${u} and expected ${inspect(expected)} but 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}`); + } +}); - assert.deepStrictEqual( - actual, - expected, - `parsing ${u} and expected ${inspect(expected)} but 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}`); -} - -{ +test('parse result should equal new url.Url()', { skip: !hasIntl }, () => { const parsed = url.parse('http://nodejs.org/') .resolveObject('jAvascript:alert(1);a=\x27@white-listed.com\x27'); @@ -1074,4 +1073,4 @@ for (const u in parseTests) { }); assert.deepStrictEqual(parsed, expected); -} +});