Skip to content

Instantly share code, notes, and snippets.

@disintegrator
Created June 7, 2024 11:12
Show Gist options
  • Save disintegrator/4374039e7b44c6e4a7f6168eb7f55eba to your computer and use it in GitHub Desktop.
Save disintegrator/4374039e7b44c6e4a7f6168eb7f55eba to your computer and use it in GitHub Desktop.
URL helpers
export function tryParseURL(input: unknown): URL | null {
if (input instanceof URL) {
return input;
}
if (typeof input !== "string") {
return null;
}
try {
return new URL(input);
} catch (err) {
return null;
}
}
export function compareURLs(a: URL, b: URL): boolean {
if (
a.origin !== b.origin ||
a.username !== b.username ||
a.password !== b.password ||
a.pathname !== b.pathname ||
a.hash !== b.hash ||
a.searchParams.size !== b.searchParams.size
) {
return false;
}
for (const [key, value] of a.searchParams) {
const avals = a.searchParams.getAll(key);
const bvals = b.searchParams.getAll(key);
if (avals.length !== bvals.length) {
return false;
}
if (!bvals.includes(value)) {
return false;
}
}
return true;
}
import { expect } from "vitest";
import { compareURLs, tryParseURL } from "./url_helpers";
expect.extend({
toMatchURL(actual: unknown, expected: unknown) {
const got = tryParseURL(actual);
const want = tryParseURL(expected);
if (got == null) {
return {
pass: false,
message: () => `expected ${actual} to be a string or URL`,
actual: typeof actual,
expected: "string | URL",
};
}
if (want == null) {
return {
pass: false,
message: () => `expected ${expected} to be a string or URL`,
actual: typeof expected,
expected: "string | URL",
};
}
const { isNot } = this;
return {
pass: compareURLs(got, want),
message: () => `urls ${isNot ? "" : "did not "}match`,
actual,
expected,
};
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment