1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-26 09:10:40 -05:00
denoland-deno/cli/js/tests/url_test.ts
Marcos Casagrande 2fc5878668
Change URL.port implementation to match WHATWG specifications (#4954)
Changed `URL.port` implementation to match [WHATWG
specifications](https://url.spec.whatwg.org/#port-state).

This PR matches the behaviour of other browsers:

1.  a `TypeError` must be thrown when passing an URL with an invalid
port to the constructor.

2. When setting an invalid port, using property setter, I haven't found
what should happen in this case, so I mimic **Firefox** & **Node**
behaviour. If an invalid port is set, it will use the previous value.
**Chrome** sets the value to `'0'` if an invalid port is set. I prefer
to keep the previous valid value.  (I can use Chrome's behaviour if you
think it's better, it's a simple value change)

```
url.port = '3000'; // valid
url.port = 'deno'; // invalid
assertEquals(url.port, '3000');
```

3. If the port value equals the current protocol default port value,
`port` will be an empty string.
2020-04-28 01:23:06 -04:00

315 lines
9.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import { unitTest, assert, assertEquals, assertThrows } from "./test_util.ts";
unitTest(function urlParsing(): void {
const url = new URL(
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
assertEquals(url.hash, "#qat");
assertEquals(url.host, "baz.qat:8000");
assertEquals(url.hostname, "baz.qat");
assertEquals(
url.href,
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
assertEquals(url.origin, "https://baz.qat:8000");
assertEquals(url.password, "bar");
assertEquals(url.pathname, "/qux/quux");
assertEquals(url.port, "8000");
assertEquals(url.protocol, "https:");
assertEquals(url.search, "?foo=bar&baz=12");
assertEquals(url.searchParams.getAll("foo"), ["bar"]);
assertEquals(url.searchParams.getAll("baz"), ["12"]);
assertEquals(url.username, "foo");
assertEquals(
String(url),
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
assertEquals(
JSON.stringify({ key: url }),
`{"key":"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"}`
);
});
unitTest(function urlModifications(): void {
const url = new URL(
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
url.hash = "";
assertEquals(
url.href,
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12"
);
url.host = "qat.baz:8080";
assertEquals(
url.href,
"https://foo:bar@qat.baz:8080/qux/quux?foo=bar&baz=12"
);
url.hostname = "foo.bar";
assertEquals(
url.href,
"https://foo:bar@foo.bar:8080/qux/quux?foo=bar&baz=12"
);
url.password = "qux";
assertEquals(
url.href,
"https://foo:qux@foo.bar:8080/qux/quux?foo=bar&baz=12"
);
url.pathname = "/foo/bar%qat";
assertEquals(
url.href,
"https://foo:qux@foo.bar:8080/foo/bar%qat?foo=bar&baz=12"
);
url.port = "";
assertEquals(url.href, "https://foo:qux@foo.bar/foo/bar%qat?foo=bar&baz=12");
url.protocol = "http:";
assertEquals(url.href, "http://foo:qux@foo.bar/foo/bar%qat?foo=bar&baz=12");
url.search = "?foo=bar&foo=baz";
assertEquals(url.href, "http://foo:qux@foo.bar/foo/bar%qat?foo=bar&foo=baz");
assertEquals(url.searchParams.getAll("foo"), ["bar", "baz"]);
url.username = "foo@bar";
assertEquals(
url.href,
"http://foo%40bar:qux@foo.bar/foo/bar%qat?foo=bar&foo=baz"
);
url.searchParams.set("bar", "qat");
assertEquals(
url.href,
"http://foo%40bar:qux@foo.bar/foo/bar%qat?foo=bar&foo=baz&bar=qat"
);
url.searchParams.delete("foo");
assertEquals(url.href, "http://foo%40bar:qux@foo.bar/foo/bar%qat?bar=qat");
url.searchParams.append("foo", "bar");
assertEquals(
url.href,
"http://foo%40bar:qux@foo.bar/foo/bar%qat?bar=qat&foo=bar"
);
});
unitTest(function urlModifyHref(): void {
const url = new URL("http://example.com/");
url.href = "https://foo:bar@example.com:8080/baz/qat#qux";
assertEquals(url.protocol, "https:");
assertEquals(url.username, "foo");
assertEquals(url.password, "bar");
assertEquals(url.host, "example.com:8080");
assertEquals(url.hostname, "example.com");
assertEquals(url.pathname, "/baz/qat");
assertEquals(url.hash, "#qux");
});
unitTest(function urlNormalize(): void {
const url = new URL("http://example.com");
assertEquals(url.pathname, "/");
assertEquals(url.href, "http://example.com/");
});
unitTest(function urlModifyPathname(): void {
const url = new URL("http://foo.bar/baz%qat/qux%quux");
assertEquals(url.pathname, "/baz%qat/qux%quux");
url.pathname = url.pathname;
assertEquals(url.pathname, "/baz%qat/qux%quux");
url.pathname = "baz#qat qux";
assertEquals(url.pathname, "/baz%23qat%20qux");
url.pathname = url.pathname;
assertEquals(url.pathname, "/baz%23qat%20qux");
});
unitTest(function urlModifyHash(): void {
const url = new URL("http://foo.bar");
url.hash = "%foo bar/qat%qux#bar";
assertEquals(url.hash, "#%foo%20bar/qat%qux#bar");
url.hash = url.hash;
assertEquals(url.hash, "#%foo%20bar/qat%qux#bar");
});
unitTest(function urlSearchParamsReuse(): void {
const url = new URL(
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
const sp = url.searchParams;
url.host = "baz.qat";
assert(sp === url.searchParams, "Search params should be reused.");
});
unitTest(function urlBaseURL(): void {
const base = new URL(
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
const url = new URL("/foo/bar?baz=foo#qux", base);
assertEquals(url.href, "https://foo:bar@baz.qat:8000/foo/bar?baz=foo#qux");
});
unitTest(function urlBaseString(): void {
const url = new URL(
"/foo/bar?baz=foo#qux",
"https://foo:bar@baz.qat:8000/qux/quux?foo=bar&baz=12#qat"
);
assertEquals(url.href, "https://foo:bar@baz.qat:8000/foo/bar?baz=foo#qux");
});
unitTest(function urlRelativeWithBase(): void {
assertEquals(new URL("", "file:///a/a/a").href, "file:///a/a/a");
assertEquals(new URL(".", "file:///a/a/a").href, "file:///a/a/");
assertEquals(new URL("..", "file:///a/a/a").href, "file:///a/");
assertEquals(new URL("b", "file:///a/a/a").href, "file:///a/a/b");
assertEquals(new URL("b", "file:///a/a/a/").href, "file:///a/a/a/b");
assertEquals(new URL("b/", "file:///a/a/a").href, "file:///a/a/b/");
assertEquals(new URL("../b", "file:///a/a/a").href, "file:///a/b");
});
unitTest(function emptyBasePath(): void {
assertEquals(new URL("", "http://example.com").href, "http://example.com/");
});
unitTest(function deletingAllParamsRemovesQuestionMarkFromURL(): void {
const url = new URL("http://example.com/?param1&param2");
url.searchParams.delete("param1");
url.searchParams.delete("param2");
assertEquals(url.href, "http://example.com/");
assertEquals(url.search, "");
});
unitTest(function removingNonExistentParamRemovesQuestionMarkFromURL(): void {
const url = new URL("http://example.com/?");
assertEquals(url.href, "http://example.com/?");
url.searchParams.delete("param1");
assertEquals(url.href, "http://example.com/");
assertEquals(url.search, "");
});
unitTest(function sortingNonExistentParamRemovesQuestionMarkFromURL(): void {
const url = new URL("http://example.com/?");
assertEquals(url.href, "http://example.com/?");
url.searchParams.sort();
assertEquals(url.href, "http://example.com/");
assertEquals(url.search, "");
});
unitTest(
{
// FIXME(bartlomieju)
ignore: true,
},
function customInspectFunction(): void {
const url = new URL("http://example.com/?");
assertEquals(
Deno.inspect(url),
'URL { href: "http://example.com/?", origin: "http://example.com", protocol: "http:", username: "", password: "", host: "example.com", hostname: "example.com", port: "", pathname: "/", hash: "", search: "?" }'
);
}
);
unitTest(function protocolNotHttpOrFile() {
const url = new URL("about:blank");
assertEquals(url.href, "about:blank");
assertEquals(url.protocol, "about:");
assertEquals(url.origin, "null");
});
unitTest(function createBadUrl(): void {
assertThrows(() => {
new URL("0.0.0.0:8080");
});
});
unitTest(function throwForInvalidPortConstructor(): void {
const urls = [
// If port is greater than 2^16 1, validation error, return failure.
`https://baz.qat:${2 ** 16}`,
"https://baz.qat:-32",
"https://baz.qat:deno",
];
for (const url of urls) {
assertThrows(() => new URL(url));
}
});
unitTest(function doNotOverridePortIfInvalid(): void {
const initialPort = "3000";
const ports = [
// If port is greater than 2^16 1, validation error, return failure.
`${2 ** 16}`,
"-32",
"deno",
];
for (const port of ports) {
const url = new URL(`https://deno.land:${initialPort}`);
url.port = port;
assertEquals(url.port, initialPort);
}
});
unitTest(function doNotOverridePortIfInvalid(): void {
const initialPort = "3000";
const ports = [
// If port is greater than 2^16 1, validation error, return failure.
`${2 ** 16}`,
"-32",
"deno",
];
for (const port of ports) {
const url = new URL(`https://deno.land:${initialPort}`);
url.port = port;
assertEquals(url.port, initialPort);
}
});
unitTest(function emptyPortForSchemeDefaultPort(): void {
const nonDefaultPort = "3500";
const urls = [
{ url: "ftp://baz.qat:21", port: "21", protocol: "ftp:" },
{ url: "https://baz.qat:443", port: "443", protocol: "https:" },
{ url: "wss://baz.qat:443", port: "443", protocol: "wss:" },
{ url: "http://baz.qat:80", port: "80", protocol: "http:" },
{ url: "ws://baz.qat:80", port: "80", protocol: "ws:" },
{ url: "file://home/index.html", port: "", protocol: "file:" },
{ url: "/foo", baseUrl: "ftp://baz.qat:21", port: "21", protocol: "ftp:" },
{
url: "/foo",
baseUrl: "https://baz.qat:443",
port: "443",
protocol: "https:",
},
{
url: "/foo",
baseUrl: "wss://baz.qat:443",
port: "443",
protocol: "wss:",
},
{
url: "/foo",
baseUrl: "http://baz.qat:80",
port: "80",
protocol: "http:",
},
{ url: "/foo", baseUrl: "ws://baz.qat:80", port: "80", protocol: "ws:" },
{
url: "/foo",
baseUrl: "file://home/index.html",
port: "",
protocol: "file:",
},
];
for (const { url: urlString, baseUrl, port, protocol } of urls) {
const url = new URL(urlString, baseUrl);
assertEquals(url.port, "");
url.port = nonDefaultPort;
assertEquals(url.port, nonDefaultPort);
url.port = port;
assertEquals(url.port, "");
// change scheme
url.protocol = "sftp:";
assertEquals(url.port, port);
url.protocol = protocol;
assertEquals(url.port, "");
}
});