on master help sign in
diagonal/test/url.test.ts
95 lines 4.4 kB history raw
1import { describe, expect, it } from "vitest";
2import { isValidLabel, labelOf, repairLabel, safeEmoji, titleKey } from "../src/shared/label";
3import { colorFor, hostname, isInternalUrl, promptAddress, promptUrl, provisionalTitle, registrableDomain, trimText } from "../src/shared/url";
4import { withDefaults } from "../src/background/settings";
5import labelCases from "../host/tests/golden/labels.json";
7describe("url helpers", () => {
8 it("strips www.", () => {
9 expect(hostname("https://www.github.com/x")).toBe("github.com");
10 expect(provisionalTitle("https://www.github.com/rust-lang")).toBe("github.com");
11 });
13 it("keeps the query when the path is empty, drops tracking keys elsewhere, keeps content keys", () => {
14 expect(promptAddress("https://www.example.com/?q=rust")).toBe("example.com?q=rust");
15 expect(promptAddress("https://www.youtube.com/watch?v=abc123&utm_source=x&t=10#frag")).toBe("youtube.com/watch?v=abc123");
16 expect(promptAddress("https://blog.example.com/post/1?utm_medium=email&fbclid=zz")).toBe("blog.example.com/post/1");
17 });
19 it("cuts the address at 160 characters", () => {
20 expect(promptAddress(`https://example.com/${"a".repeat(400)}`)).toHaveLength(160);
21 });
23 it("hostname only when full URLs are off", () => {
24 expect(promptUrl("https://docs.rs/tokio/latest/tokio/", false)).toBe("https://docs.rs");
25 });
27 it("registrable domain handles common two-label suffixes", () => {
28 expect(registrableDomain("https://news.bbc.co.uk/x")).toBe("bbc.co.uk");
29 expect(registrableDomain("https://gist.github.com/")).toBe("github.com");
30 expect(registrableDomain("https://me.github.io/")).toBe("me.github.io");
31 });
33 it("the same site always gets the same colour, never grey", () => {
34 expect(colorFor("https://github.com/a")).toBe(colorFor("https://gist.github.com/b"));
35 for (const u of ["https://a.com", "https://b.org", "https://c.net", "https://d.io", "https://e.dev"]) expect(colorFor(u)).not.toBe("grey");
36 });
38 it("internal pages are recognised", () => {
39 for (const u of ["brave://newtab/", "chrome://settings", "chrome-extension://abc/x.html", "file:///tmp", "about:blank", ""]) expect(isInternalUrl(u)).toBe(true);
40 expect(isInternalUrl("https://a.com")).toBe(false);
41 });
43 it("trims text on a word boundary", () => {
44 expect(trimText("one two three four", 10)).toBe("one two");
45 expect(trimText(" a \n b ", 300)).toBe("a b");
46 });
47});
49// The same cases run against the host's validate.repair_label, so the two sides agree on every label.
50const LABEL_CASES = labelCases as [string, string | null][];
52describe("labels", () => {
53 it.each(LABEL_CASES)("repairs %s", (raw, fixed) => {
54 expect(repairLabel(raw) ?? null).toBe(fixed);
55 });
57 it("validates", () => {
58 expect(isValidLabel("Lisbon trip")).toBe(true);
59 expect(isValidLabel("Lisbon")).toBe(false);
60 expect(isValidLabel("日本旅行")).toBe(true);
61 expect(isValidLabel("京都の旅行計画")).toBe(true);
62 expect(isValidLabel("日")).toBe(false);
63 expect(repairLabel("日本旅行。")).toBe("日本旅行");
64 });
66 it("emoji outside the list fall back; FE0F is optional", () => {
67 expect(safeEmoji("✈")).toBe("✈️");
68 expect(safeEmoji("🦄")).toBe("🧭");
69 });
71 it("titleKey ignores the unread counts and bullets sites put in titles", () => {
72 expect(titleKey("(3) Inbox - Mail")).toBe(titleKey("(12) Inbox - Mail"));
73 expect(titleKey("Inbox (1,204) - me@example.com - Gmail")).toBe("Inbox - me@example.com - Gmail");
74 expect(titleKey("• Slack | general")).toBe("Slack | general");
75 expect(titleKey("[99+] Chat")).toBe("Chat");
76 expect(titleKey("Rust async")).toBe("Rust async");
77 expect(titleKey("Rust async")).not.toBe(titleKey("Rust sync"));
78 });
80 it("labelOf strips our emoji prefix", () => {
81 expect(labelOf("🦀 Rust async")).toBe("Rust async");
82 expect(labelOf("Plain title")).toBe("Plain title");
83 });
84});
86describe("settings", () => {
87 it("fills defaults and clamps", () => {
88 const s = withDefaults({ namingDebounceMs: 10, tidyMode: "weird", emoji: false, tidyExclusions: ["a", "", 3] });
89 expect(s.namingDebounceMs).toBe(1000);
90 expect(s.tidyMode).toBe("auto");
91 expect(s.emoji).toBe(false);
92 expect(s.tidyExclusions).toEqual(["a"]);
93 expect(withDefaults(undefined).parkAfterHours).toBe(24);
94 });
95});