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); }); } }); });