mirror of
https://github.com/oven-sh/bun
synced 2026-02-16 05:42:43 +00:00
Merge branch 'main' into jarred/process-change
This commit is contained in:
@@ -1310,6 +1310,14 @@ describe("fs.exists", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
it("should work with util.promisify when path exists", async () => {
|
||||
const fsexists = promisify(fs.exists);
|
||||
expect(await fsexists(import.meta.path)).toBe(true);
|
||||
});
|
||||
it("should work with util.promisify when path doesn't exist", async () => {
|
||||
const fsexists = promisify(fs.exists);
|
||||
expect(await fsexists(`${tmpdir()}/test-fs-exists-${Date.now()}`)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("rm", () => {
|
||||
|
||||
26
test/js/node/url/url-canParse-whatwg.test.js
Normal file
26
test/js/node/url/url-canParse-whatwg.test.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import { URL } from "node:url";
|
||||
|
||||
describe("URL.canParse", () => {
|
||||
// TODO: Support error code.
|
||||
test.todo("invalid input", () => {
|
||||
// One argument is required
|
||||
assert.throws(
|
||||
() => {
|
||||
URL.canParse();
|
||||
},
|
||||
{
|
||||
code: "ERR_MISSING_ARGS",
|
||||
name: "TypeError",
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
test("repeatedly called produces same result", () => {
|
||||
// This test is to ensure that the v8 fast api works.
|
||||
for (let i = 0; i < 1e5; i++) {
|
||||
assert(URL.canParse("https://www.example.com/path/?query=param#hash"));
|
||||
}
|
||||
});
|
||||
});
|
||||
31
test/js/node/url/url-domain-ascii-unicode.test.js
Normal file
31
test/js/node/url/url-domain-ascii-unicode.test.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
const domainToASCII = url.domainToASCII;
|
||||
const domainToUnicode = url.domainToUnicode;
|
||||
|
||||
// TODO: Support url.domainToASCII and url.domainToUnicode.
|
||||
describe.todo("url.domainToASCII and url.domainToUnicode", () => {
|
||||
test("convert from unicode to ascii and back", () => {
|
||||
const domainWithASCII = [
|
||||
["ıíd", "xn--d-iga7r"],
|
||||
["يٴ", "xn--mhb8f"],
|
||||
["www.ϧƽəʐ.com", "www.xn--cja62apfr6c.com"],
|
||||
["новини.com", "xn--b1amarcd.com"],
|
||||
["名がドメイン.com", "xn--v8jxj3d1dzdz08w.com"],
|
||||
["افغانستا.icom.museum", "xn--mgbaal8b0b9b2b.icom.museum"],
|
||||
["الجزائر.icom.fake", "xn--lgbbat1ad8j.icom.fake"],
|
||||
["भारत.org", "xn--h2brj9c.org"],
|
||||
];
|
||||
|
||||
domainWithASCII.forEach(pair => {
|
||||
const domain = pair[0];
|
||||
const ascii = pair[1];
|
||||
const domainConvertedToASCII = domainToASCII(domain);
|
||||
assert.strictEqual(domainConvertedToASCII, ascii);
|
||||
const asciiConvertedToUnicode = domainToUnicode(ascii);
|
||||
assert.strictEqual(asciiConvertedToUnicode, domain);
|
||||
});
|
||||
});
|
||||
});
|
||||
156
test/js/node/url/url-fileurltopath.test.js
Normal file
156
test/js/node/url/url-fileurltopath.test.js
Normal file
@@ -0,0 +1,156 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url, { URL } from "node:url";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
|
||||
describe("url.fileURLToPath", () => {
|
||||
function testInvalidArgs(...args) {
|
||||
for (const arg of args) {
|
||||
assert.throws(() => url.fileURLToPath(arg), {
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Support error code.
|
||||
test.todo("invalid input", () => {
|
||||
// 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",
|
||||
});
|
||||
|
||||
const withHost = new URL("file://host/a");
|
||||
|
||||
if (isWindows) {
|
||||
assert.strictEqual(url.fileURLToPath(withHost), "\\\\host\\a");
|
||||
} else {
|
||||
assert.throws(() => url.fileURLToPath(withHost), {
|
||||
code: "ERR_INVALID_FILE_URL_HOST",
|
||||
});
|
||||
}
|
||||
|
||||
if (isWindows) {
|
||||
assert.throws(() => url.fileURLToPath("file:///C:/a%2F/"), {
|
||||
code: "ERR_INVALID_FILE_URL_PATH",
|
||||
});
|
||||
assert.throws(() => url.fileURLToPath("file:///C:/a%5C/"), {
|
||||
code: "ERR_INVALID_FILE_URL_PATH",
|
||||
});
|
||||
assert.throws(() => url.fileURLToPath("file:///?:/"), {
|
||||
code: "ERR_INVALID_FILE_URL_PATH",
|
||||
});
|
||||
} else {
|
||||
assert.throws(() => url.fileURLToPath("file:///a%2F/"), {
|
||||
code: "ERR_INVALID_FILE_URL_PATH",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test("general", () => {
|
||||
let testCases;
|
||||
if (isWindows) {
|
||||
testCases = [
|
||||
// Lowercase ascii alpha
|
||||
{ path: "C:\\foo", fileURL: "file:///C:/foo" },
|
||||
// Uppercase ascii alpha
|
||||
{ path: "C:\\FOO", fileURL: "file:///C:/FOO" },
|
||||
// dir
|
||||
{ path: "C:\\dir\\foo", fileURL: "file:///C:/dir/foo" },
|
||||
// trailing separator
|
||||
{ path: "C:\\dir\\", fileURL: "file:///C:/dir/" },
|
||||
// dot
|
||||
{ path: "C:\\foo.mjs", fileURL: "file:///C:/foo.mjs" },
|
||||
// space
|
||||
{ path: "C:\\foo bar", fileURL: "file:///C:/foo%20bar" },
|
||||
// question mark
|
||||
{ path: "C:\\foo?bar", fileURL: "file:///C:/foo%3Fbar" },
|
||||
// number sign
|
||||
{ path: "C:\\foo#bar", fileURL: "file:///C:/foo%23bar" },
|
||||
// ampersand
|
||||
{ path: "C:\\foo&bar", fileURL: "file:///C:/foo&bar" },
|
||||
// equals
|
||||
{ path: "C:\\foo=bar", fileURL: "file:///C:/foo=bar" },
|
||||
// colon
|
||||
{ path: "C:\\foo:bar", fileURL: "file:///C:/foo:bar" },
|
||||
// semicolon
|
||||
{ path: "C:\\foo;bar", fileURL: "file:///C:/foo;bar" },
|
||||
// percent
|
||||
{ path: "C:\\foo%bar", fileURL: "file:///C:/foo%25bar" },
|
||||
// backslash
|
||||
{ path: "C:\\foo\\bar", fileURL: "file:///C:/foo/bar" },
|
||||
// backspace
|
||||
{ path: "C:\\foo\bbar", fileURL: "file:///C:/foo%08bar" },
|
||||
// tab
|
||||
{ path: "C:\\foo\tbar", fileURL: "file:///C:/foo%09bar" },
|
||||
// newline
|
||||
{ path: "C:\\foo\nbar", fileURL: "file:///C:/foo%0Abar" },
|
||||
// carriage return
|
||||
{ path: "C:\\foo\rbar", fileURL: "file:///C:/foo%0Dbar" },
|
||||
// latin1
|
||||
{ path: "C:\\fóóbàr", fileURL: "file:///C:/f%C3%B3%C3%B3b%C3%A0r" },
|
||||
// Euro sign (BMP code point)
|
||||
{ path: "C:\\€", fileURL: "file:///C:/%E2%82%AC" },
|
||||
// Rocket emoji (non-BMP code point)
|
||||
{ path: "C:\\🚀", fileURL: "file:///C:/%F0%9F%9A%80" },
|
||||
// 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" },
|
||||
];
|
||||
} else {
|
||||
testCases = [
|
||||
// Lowercase ascii alpha
|
||||
{ path: "/foo", fileURL: "file:///foo" },
|
||||
// Uppercase ascii alpha
|
||||
{ path: "/FOO", fileURL: "file:///FOO" },
|
||||
// dir
|
||||
{ path: "/dir/foo", fileURL: "file:///dir/foo" },
|
||||
// trailing separator
|
||||
{ path: "/dir/", fileURL: "file:///dir/" },
|
||||
// dot
|
||||
{ path: "/foo.mjs", fileURL: "file:///foo.mjs" },
|
||||
// space
|
||||
{ path: "/foo bar", fileURL: "file:///foo%20bar" },
|
||||
// question mark
|
||||
{ path: "/foo?bar", fileURL: "file:///foo%3Fbar" },
|
||||
// number sign
|
||||
{ path: "/foo#bar", fileURL: "file:///foo%23bar" },
|
||||
// ampersand
|
||||
{ path: "/foo&bar", fileURL: "file:///foo&bar" },
|
||||
// equals
|
||||
{ path: "/foo=bar", fileURL: "file:///foo=bar" },
|
||||
// colon
|
||||
{ path: "/foo:bar", fileURL: "file:///foo:bar" },
|
||||
// semicolon
|
||||
{ path: "/foo;bar", fileURL: "file:///foo;bar" },
|
||||
// percent
|
||||
{ path: "/foo%bar", fileURL: "file:///foo%25bar" },
|
||||
// backslash
|
||||
{ path: "/foo\\bar", fileURL: "file:///foo%5Cbar" },
|
||||
// backspace
|
||||
{ path: "/foo\bbar", fileURL: "file:///foo%08bar" },
|
||||
// tab
|
||||
{ path: "/foo\tbar", fileURL: "file:///foo%09bar" },
|
||||
// newline
|
||||
{ path: "/foo\nbar", fileURL: "file:///foo%0Abar" },
|
||||
// carriage return
|
||||
{ path: "/foo\rbar", fileURL: "file:///foo%0Dbar" },
|
||||
// latin1
|
||||
{ path: "/fóóbàr", fileURL: "file:///f%C3%B3%C3%B3b%C3%A0r" },
|
||||
// Euro sign (BMP code point)
|
||||
{ path: "/€", fileURL: "file:///%E2%82%AC" },
|
||||
// Rocket emoji (non-BMP code point)
|
||||
{ path: "/🚀", fileURL: "file:///%F0%9F%9A%80" },
|
||||
];
|
||||
}
|
||||
|
||||
for (const { path, fileURL } of testCases) {
|
||||
const fromString = url.fileURLToPath(fileURL);
|
||||
assert.strictEqual(fromString, path);
|
||||
const fromURL = url.fileURLToPath(new URL(fileURL));
|
||||
assert.strictEqual(fromURL, path);
|
||||
}
|
||||
});
|
||||
});
|
||||
28
test/js/node/url/url-format-invalid-input.test.js
Normal file
28
test/js/node/url/url-format-invalid-input.test.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
describe("url.format", () => {
|
||||
// TODO: Support error code.
|
||||
test.todo("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",
|
||||
message: 'The "urlObject" argument must be one of type object or string.',
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
test("empty", () => {
|
||||
assert.strictEqual(url.format(""), "");
|
||||
assert.strictEqual(url.format({}), "");
|
||||
});
|
||||
});
|
||||
78
test/js/node/url/url-format-whatwg.test.js
Normal file
78
test/js/node/url/url-format-whatwg.test.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url, { URL } from "node:url";
|
||||
|
||||
describe("url.format", () => {
|
||||
test("WHATWG", () => {
|
||||
const myURL = new URL("http://user:pass@xn--lck1c3crb1723bpq4a.com/a?a=b#c");
|
||||
|
||||
// TODO: Support these.
|
||||
//
|
||||
// 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");
|
||||
|
||||
// TODO: Support this kind of assert.throws.
|
||||
// {
|
||||
// [true, 1, "test", Infinity].forEach(value => {
|
||||
// assert.throws(() => url.format(myURL, value), {
|
||||
// code: "ERR_INVALID_ARG_TYPE",
|
||||
// name: "TypeError",
|
||||
// message: 'The "options" argument must be of type object.',
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// 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");
|
||||
|
||||
// TODO: Support these.
|
||||
//
|
||||
// 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 }));
|
||||
});
|
||||
});
|
||||
281
test/js/node/url/url-format.test.js
Normal file
281
test/js/node/url/url-format.test.js
Normal file
@@ -0,0 +1,281 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
describe("url.format", () => {
|
||||
test("slightly wonky content", () => {
|
||||
// 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",
|
||||
},
|
||||
// TODO: Support this.
|
||||
//
|
||||
// "http://[::]/": {
|
||||
// href: "http://[::]/",
|
||||
// protocol: "http:",
|
||||
// hostname: "[::]",
|
||||
// pathname: "/",
|
||||
// },
|
||||
|
||||
// Encode context-specific delimiters in path and query, but do not touch
|
||||
// other non-delimiter chars like `%`.
|
||||
// <https://github.com/nodejs/node-v0.x-archive/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",
|
||||
},
|
||||
|
||||
// `#` 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",
|
||||
},
|
||||
|
||||
// `?` 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",
|
||||
},
|
||||
// TODO: Support these.
|
||||
//
|
||||
// // 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",
|
||||
// },
|
||||
|
||||
// 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}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
22
test/js/node/url/url-is-url.test.js
Normal file
22
test/js/node/url/url-is-url.test.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// Flags: --expose-internals
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import { URL, parse } from "node:url";
|
||||
|
||||
describe("internal/url", () => {
|
||||
test.skip("isURL", () => {
|
||||
const { isURL } = require("internal/url");
|
||||
|
||||
assert.strictEqual(isURL("https://www.nodejs.org"), true);
|
||||
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,
|
||||
);
|
||||
});
|
||||
});
|
||||
15
test/js/node/url/url-null-char.test.js
Normal file
15
test/js/node/url/url-null-char.test.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import { URL } from "node:url";
|
||||
|
||||
describe("URL", () => {
|
||||
// TODO: Fix error properties
|
||||
test.skip("null character", () => {
|
||||
assert.throws(
|
||||
() => {
|
||||
new URL("a\0b");
|
||||
},
|
||||
{ code: "ERR_INVALID_URL", input: "a\0b" },
|
||||
);
|
||||
});
|
||||
});
|
||||
1077
test/js/node/url/url-parse-format.test.js
Normal file
1077
test/js/node/url/url-parse-format.test.js
Normal file
File diff suppressed because it is too large
Load Diff
121
test/js/node/url/url-parse-invalid-input.test.js
Normal file
121
test/js/node/url/url-parse-invalid-input.test.js
Normal file
@@ -0,0 +1,121 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
describe("url.parse", () => {
|
||||
// TODO: Support error code.
|
||||
test.todo("invalid input", () => {
|
||||
// https://github.com/joyent/node/issues/568
|
||||
[
|
||||
[undefined, "undefined"],
|
||||
[null, "object"],
|
||||
[true, "boolean"],
|
||||
[false, "boolean"],
|
||||
[0.0, "number"],
|
||||
[0, "number"],
|
||||
[[], "object"],
|
||||
[{}, "object"],
|
||||
[() => {}, "function"],
|
||||
[Symbol("foo"), "symbol"],
|
||||
].forEach(([val, type]) => {
|
||||
assert.throws(
|
||||
() => {
|
||||
url.parse(val);
|
||||
},
|
||||
{
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
name: "TypeError",
|
||||
message: 'The "url" argument must be of type string.',
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
assert.throws(
|
||||
() => {
|
||||
url.parse("http://%E0%A4%A@fail");
|
||||
},
|
||||
e => {
|
||||
// The error should be a URIError.
|
||||
if (!(e instanceof URIError)) return false;
|
||||
|
||||
// The error should be from the JS engine and not from Node.js.
|
||||
// JS engine errors do not have the `code` property.
|
||||
return e.code === undefined;
|
||||
},
|
||||
);
|
||||
|
||||
assert.throws(
|
||||
() => {
|
||||
url.parse("http://[127.0.0.1\x00c8763]:8000/");
|
||||
},
|
||||
{ code: "ERR_INVALID_URL", input: "http://[127.0.0.1\x00c8763]:8000/" },
|
||||
);
|
||||
|
||||
if (common.hasIntl) {
|
||||
// An array of Unicode code points whose Unicode NFKD contains a "bad
|
||||
// character".
|
||||
const badIDNA = (() => {
|
||||
const BAD_CHARS = "#%/:?@[\\]^|";
|
||||
const out = [];
|
||||
for (let i = 0x80; i < 0x110000; i++) {
|
||||
const cp = String.fromCodePoint(i);
|
||||
for (const badChar of BAD_CHARS) {
|
||||
if (cp.normalize("NFKD").includes(badChar)) {
|
||||
out.push(cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
})();
|
||||
|
||||
// The generation logic above should at a minimum produce these two
|
||||
// characters.
|
||||
assert(badIDNA.includes("℀"));
|
||||
assert(badIDNA.includes("@"));
|
||||
|
||||
for (const badCodePoint of badIDNA) {
|
||||
const badURL = `http://fail${badCodePoint}fail.com/`;
|
||||
assert.throws(
|
||||
() => {
|
||||
url.parse(badURL);
|
||||
},
|
||||
e => e.code === "ERR_INVALID_URL",
|
||||
`parsing ${badURL}`,
|
||||
);
|
||||
}
|
||||
|
||||
assert.throws(
|
||||
() => {
|
||||
url.parse("http://\u00AD/bad.com/");
|
||||
},
|
||||
e => e.code === "ERR_INVALID_URL",
|
||||
"parsing http://\u00AD/bad.com/",
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
const badURLs = ["https://evil.com:.example.com", "git+ssh://git@github.com:npm/npm"];
|
||||
badURLs.forEach(badURL => {
|
||||
common.spawnPromisified(process.execPath, ["-e", `url.parse(${JSON.stringify(badURL)})`]).then(
|
||||
common.mustCall(({ code, stdout, stderr }) => {
|
||||
assert.strictEqual(code, 0);
|
||||
assert.strictEqual(stdout, "");
|
||||
assert.match(stderr, /\[DEP0170\] DeprecationWarning:/);
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
// Warning should only happen once per process.
|
||||
const expectedWarning = [
|
||||
`The URL ${badURLs[0]} is invalid. Future versions of Node.js will throw an error.`,
|
||||
"DEP0170",
|
||||
];
|
||||
common.expectWarning({
|
||||
DeprecationWarning: expectedWarning,
|
||||
});
|
||||
badURLs.forEach(badURL => {
|
||||
url.parse(badURL);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
93
test/js/node/url/url-parse-query.test.js
Normal file
93
test/js/node/url/url-parse-query.test.js
Normal file
@@ -0,0 +1,93 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
describe("url.parse", () => {
|
||||
// TODO: Support correct prototype and null values.
|
||||
test.todo("with query string", () => {
|
||||
function createWithNoPrototype(properties = []) {
|
||||
const noProto = { __proto__: 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: null,
|
||||
pathname: "/",
|
||||
path: "/",
|
||||
},
|
||||
"/example": {
|
||||
protocol: null,
|
||||
slashes: null,
|
||||
auth: undefined,
|
||||
host: null,
|
||||
port: null,
|
||||
hostname: null,
|
||||
hash: null,
|
||||
search: null,
|
||||
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]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
203
test/js/node/url/url-pathtofileurl.test.js
Normal file
203
test/js/node/url/url-pathtofileurl.test.js
Normal file
@@ -0,0 +1,203 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import url from "node:url";
|
||||
|
||||
const isWindows = process.platform === "win32";
|
||||
|
||||
describe("url.pathToFileURL", () => {
|
||||
// TODO: Fix these asserts on Windows.
|
||||
test.skipIf(isWindows)("dangling slashes and percent sign", () => {
|
||||
{
|
||||
const fileURL = url.pathToFileURL("test/").href;
|
||||
assert.ok(fileURL.startsWith("file:///"));
|
||||
assert.ok(fileURL.endsWith("/"));
|
||||
}
|
||||
|
||||
// TODO: Support these.
|
||||
//
|
||||
// {
|
||||
// const fileURL = url.pathToFileURL("test\\").href;
|
||||
// assert.ok(fileURL.startsWith("file:///"));
|
||||
// if (isWindows) assert.ok(fileURL.endsWith("/"));
|
||||
// else assert.ok(fileURL.endsWith("%5C"));
|
||||
// }
|
||||
|
||||
// {
|
||||
// const fileURL = url.pathToFileURL("test/%").href;
|
||||
// assert.ok(fileURL.includes("%25"));
|
||||
// }
|
||||
});
|
||||
|
||||
// TODO: Support UNC paths across platforms.
|
||||
test.todo("UNC paths", () => {
|
||||
if (isWindows) {
|
||||
// UNC path: \\server\share\resource
|
||||
|
||||
// Missing server:
|
||||
assert.throws(() => url.pathToFileURL("\\\\\\no-server"), {
|
||||
code: "ERR_INVALID_ARG_VALUE",
|
||||
});
|
||||
|
||||
// Missing share or resource:
|
||||
assert.throws(() => url.pathToFileURL("\\\\host"), {
|
||||
code: "ERR_INVALID_ARG_VALUE",
|
||||
});
|
||||
|
||||
// Regression test for direct String.prototype.startsWith call
|
||||
assert.throws(() => url.pathToFileURL(["\\\\", { [Symbol.toPrimitive]: () => "blep\\blop" }]), {
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
});
|
||||
assert.throws(() => url.pathToFileURL(["\\\\", "blep\\blop"]), {
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
});
|
||||
assert.throws(
|
||||
() =>
|
||||
url.pathToFileURL({
|
||||
[Symbol.toPrimitive]: () => "\\\\blep\\blop",
|
||||
}),
|
||||
{
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// UNC paths on posix are considered a single path that has backslashes:
|
||||
const fileURL = url.pathToFileURL("\\\\nas\\share\\path.txt").href;
|
||||
assert.match(fileURL, /file:\/\/.+%5C%5Cnas%5Cshare%5Cpath\.txt$/);
|
||||
}
|
||||
});
|
||||
|
||||
test("general", () => {
|
||||
let testCases;
|
||||
if (isWindows) {
|
||||
testCases = [
|
||||
// Lowercase ascii alpha
|
||||
{ path: "C:\\foo", expected: "file:///C:/foo" },
|
||||
// Uppercase ascii alpha
|
||||
{ path: "C:\\FOO", expected: "file:///C:/FOO" },
|
||||
// dir
|
||||
{ path: "C:\\dir\\foo", expected: "file:///C:/dir/foo" },
|
||||
// trailing separator
|
||||
{ path: "C:\\dir\\", expected: "file:///C:/dir/" },
|
||||
// dot
|
||||
{ path: "C:\\foo.mjs", expected: "file:///C:/foo.mjs" },
|
||||
// space
|
||||
{ path: "C:\\foo bar", expected: "file:///C:/foo%20bar" },
|
||||
// question mark
|
||||
{ path: "C:\\foo?bar", expected: "file:///C:/foo%3Fbar" },
|
||||
// number sign
|
||||
{ path: "C:\\foo#bar", expected: "file:///C:/foo%23bar" },
|
||||
// ampersand
|
||||
{ path: "C:\\foo&bar", expected: "file:///C:/foo&bar" },
|
||||
// equals
|
||||
{ path: "C:\\foo=bar", expected: "file:///C:/foo=bar" },
|
||||
// colon
|
||||
{ path: "C:\\foo:bar", expected: "file:///C:/foo:bar" },
|
||||
// semicolon
|
||||
{ path: "C:\\foo;bar", expected: "file:///C:/foo;bar" },
|
||||
// TODO: Support these.
|
||||
//
|
||||
// percent
|
||||
// { path: "C:\\foo%bar", expected: "file:///C:/foo%25bar" },
|
||||
// backslash
|
||||
// { path: "C:\\foo\\bar", expected: "file:///C:/foo/bar" },
|
||||
// backspace
|
||||
// { path: "C:\\foo\bbar", expected: "file:///C:/foo%08bar" },
|
||||
// tab
|
||||
// { path: "C:\\foo\tbar", expected: "file:///C:/foo%09bar" },
|
||||
// newline
|
||||
// { path: "C:\\foo\nbar", expected: "file:///C:/foo%0Abar" },
|
||||
// carriage return
|
||||
// { path: "C:\\foo\rbar", expected: "file:///C:/foo%0Dbar" },
|
||||
// latin1
|
||||
{ path: "C:\\fóóbàr", expected: "file:///C:/f%C3%B3%C3%B3b%C3%A0r" },
|
||||
// Euro sign (BMP code point)
|
||||
{ path: "C:\\€", expected: "file:///C:/%E2%82%AC" },
|
||||
// Rocket emoji (non-BMP code point)
|
||||
{ path: "C:\\🚀", expected: "file:///C:/%F0%9F%9A%80" },
|
||||
// UNC path (see https://docs.microsoft.com/en-us/archive/blogs/ie/file-uris-in-windows)
|
||||
{ path: "\\\\nas\\My Docs\\File.doc", expected: "file://nas/My%20Docs/File.doc" },
|
||||
];
|
||||
} else {
|
||||
testCases = [
|
||||
// Lowercase ascii alpha
|
||||
{ path: "/foo", expected: "file:///foo" },
|
||||
// Uppercase ascii alpha
|
||||
{ path: "/FOO", expected: "file:///FOO" },
|
||||
// dir
|
||||
{ path: "/dir/foo", expected: "file:///dir/foo" },
|
||||
// trailing separator
|
||||
{ path: "/dir/", expected: "file:///dir/" },
|
||||
// dot
|
||||
{ path: "/foo.mjs", expected: "file:///foo.mjs" },
|
||||
// space
|
||||
{ path: "/foo bar", expected: "file:///foo%20bar" },
|
||||
// question mark
|
||||
{ path: "/foo?bar", expected: "file:///foo%3Fbar" },
|
||||
// number sign
|
||||
{ path: "/foo#bar", expected: "file:///foo%23bar" },
|
||||
// ampersand
|
||||
{ path: "/foo&bar", expected: "file:///foo&bar" },
|
||||
// equals
|
||||
{ path: "/foo=bar", expected: "file:///foo=bar" },
|
||||
// colon
|
||||
{ path: "/foo:bar", expected: "file:///foo:bar" },
|
||||
// semicolon
|
||||
{ path: "/foo;bar", expected: "file:///foo;bar" },
|
||||
// TODO: Support these.
|
||||
//
|
||||
// percent
|
||||
// { path: "/foo%bar", expected: "file:///foo%25bar" },
|
||||
// backslash
|
||||
// { path: "/foo\\bar", expected: "file:///foo%5Cbar" },
|
||||
// backspace
|
||||
//{ path: "/foo\bbar", expected: "file:///foo%08bar" },
|
||||
// tab
|
||||
// { path: "/foo\tbar", expected: "file:///foo%09bar" },
|
||||
// newline
|
||||
// { path: "/foo\nbar", expected: "file:///foo%0Abar" },
|
||||
// carriage return
|
||||
// { path: "/foo\rbar", expected: "file:///foo%0Dbar" },
|
||||
// latin1
|
||||
{ path: "/fóóbàr", expected: "file:///f%C3%B3%C3%B3b%C3%A0r" },
|
||||
// Euro sign (BMP code point)
|
||||
{ path: "/€", expected: "file:///%E2%82%AC" },
|
||||
// Rocket emoji (non-BMP code point)
|
||||
{ path: "/🚀", expected: "file:///%F0%9F%9A%80" },
|
||||
];
|
||||
}
|
||||
|
||||
for (const { path, expected } of testCases) {
|
||||
const actual = url.pathToFileURL(path).href;
|
||||
assert.strictEqual(actual, expected);
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: Support throwing correct exception for non-string params.
|
||||
test.todo("non-string parameter", () => {
|
||||
for (const badPath of [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
42,
|
||||
42n,
|
||||
Symbol("42"),
|
||||
NaN,
|
||||
{},
|
||||
[],
|
||||
() => {},
|
||||
Promise.resolve("foo"),
|
||||
new Date(),
|
||||
new String("notPrimitive"),
|
||||
{
|
||||
toString() {
|
||||
return "amObject";
|
||||
},
|
||||
},
|
||||
{ [Symbol.toPrimitive]: hint => "amObject" },
|
||||
]) {
|
||||
assert.throws(() => url.pathToFileURL(badPath), {
|
||||
code: "ERR_INVALID_ARG_TYPE",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
420
test/js/node/url/url-relative.test.js
Normal file
420
test/js/node/url/url-relative.test.js
Normal file
@@ -0,0 +1,420 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import { inspect } from "node:util";
|
||||
import url from "node: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"],
|
||||
// TODO: Support this.
|
||||
//
|
||||
// ["http://localhost", "file:///Users/foo", "file:///Users/foo"],
|
||||
["http://localhost", "file://foo/Users", "file://foo/Users"],
|
||||
["https://registry.npmjs.org", "@foo/bar", "https://registry.npmjs.org/@foo/bar"],
|
||||
];
|
||||
|
||||
describe("url.resolveObject", () => {
|
||||
test("source is false", () => {
|
||||
// When source is false
|
||||
assert.strictEqual(url.resolveObject("", "foo"), "foo");
|
||||
});
|
||||
|
||||
test("url.resolveObject and url.parse are inverse operations", () => {
|
||||
// If format and parse are inverse operations then
|
||||
// resolveObject(parse(x), y) == parse(resolve(x, y))
|
||||
|
||||
// format: [from, path, expected]
|
||||
for (let i = 0; i < relativeTests.length; i++) {
|
||||
const relativeTest = relativeTests[i];
|
||||
|
||||
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}\n` + `actual: ${actual}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("url.resolve", () => {
|
||||
test("relative paths", () => {
|
||||
for (let i = 0; i < relativeTests.length; i++) {
|
||||
const relativeTest = relativeTests[i];
|
||||
|
||||
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}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("chiron url.resolve rests", () => {
|
||||
//
|
||||
// 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/"],
|
||||
|
||||
// TODO: Support this.
|
||||
//
|
||||
// changing port
|
||||
//["https://example.com:81/", "https://example.com:82/", "https://example.com:81/"],
|
||||
|
||||
// TODO: Support these.
|
||||
//
|
||||
// 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/"],
|
||||
// TODO: Support this.
|
||||
//
|
||||
// ["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"],
|
||||
|
||||
// No path at all
|
||||
["#hash1", "#hash2", "#hash1"],
|
||||
];
|
||||
|
||||
test("relative paths", () => {
|
||||
for (let i = 0; i < relativeTests2.length; i++) {
|
||||
const relativeTest = relativeTests2[i];
|
||||
|
||||
const a = url.resolve(relativeTest[1], relativeTest[0]);
|
||||
const e = url.format(relativeTest[2]);
|
||||
assert.strictEqual(a, e, `resolve(${relativeTest[0]}, ${relativeTest[1]})` + ` == ${e}\n actual=${a}`);
|
||||
}
|
||||
});
|
||||
|
||||
test("special case relative paths", () => {
|
||||
// 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);
|
||||
}
|
||||
for (let i = 0; i < relativeTests2.length; i++) {
|
||||
const relativeTest = relativeTests2[i];
|
||||
|
||||
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}\n` + `actual: ${actual}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
19
test/js/node/url/url-revokeobjecturl.test.js
Normal file
19
test/js/node/url/url-revokeobjecturl.test.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, test } from "bun:test";
|
||||
import assert from "node:assert";
|
||||
import { URL } from "node:url";
|
||||
|
||||
// TODO: Support throwing appropriate error.
|
||||
describe.todo("URL.revokeObjectURL", () => {
|
||||
test("invalid input", () => {
|
||||
// Test ensures that the function receives the url argument.
|
||||
assert.throws(
|
||||
() => {
|
||||
URL.revokeObjectURL();
|
||||
},
|
||||
{
|
||||
code: "ERR_MISSING_ARGS",
|
||||
name: "TypeError",
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user