mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
282 lines
8.4 KiB
JavaScript
282 lines
8.4 KiB
JavaScript
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}`,
|
|
);
|
|
}
|
|
});
|
|
});
|