markdown.test.ts
Raw
1import { describe, expect, test } from "bun:test";
2import { resolveMarkdownHref } from "../src/services/markdown.ts";
3
4describe("resolveMarkdownHref", () => {
5 describe("protocol-absolute URLs (returns null)", () => {
6 test("http", () => {
7 expect(resolveMarkdownHref("", "http://example.com/img.png")).toBeNull();
8 expect(resolveMarkdownHref("docs", "http://example.com/img.png")).toBeNull();
9 });
10 test("https", () => {
11 expect(resolveMarkdownHref("", "https://example.com/img.png")).toBeNull();
12 });
13 test("ftp", () => {
14 expect(resolveMarkdownHref("", "ftp://files.example.com/")).toBeNull();
15 });
16 test("mailto", () => {
17 expect(resolveMarkdownHref("", "mailto:foo@bar.com")).toBeNull();
18 });
19 test("data", () => {
20 expect(resolveMarkdownHref("", "data:image/png;base64,abc123")).toBeNull();
21 });
22 test("ssh", () => {
23 expect(resolveMarkdownHref("", "ssh://git@example.com/repo.git")).toBeNull();
24 });
25 test("custom protocol", () => {
26 expect(resolveMarkdownHref("", "myapp://open/something")).toBeNull();
27 });
28 });
29
30 describe("anchor links (returns null)", () => {
31 test("simple anchor", () => {
32 expect(resolveMarkdownHref("", "#section-heading")).toBeNull();
33 });
34 test("anchor with any dir", () => {
35 expect(resolveMarkdownHref("docs/guide", "#toc")).toBeNull();
36 });
37 test("bare hash", () => {
38 expect(resolveMarkdownHref("", "#")).toBeNull();
39 });
40 });
41
42 describe("root-relative URLs (strips leading /)", () => {
43 test("single file at root", () => {
44 expect(resolveMarkdownHref("", "/img.png")).toBe("img.png");
45 });
46 test("subdir file — dir is ignored", () => {
47 expect(resolveMarkdownHref("docs", "/subdir/img.png")).toBe("subdir/img.png");
48 });
49 test("deep path — any dir is ignored", () => {
50 expect(resolveMarkdownHref("x/y/z", "/a/b/c.png")).toBe("a/b/c.png");
51 });
52 test("root-relative with no filename (trailing slash)", () => {
53 expect(resolveMarkdownHref("docs", "/assets/")).toBe("assets/");
54 });
55 });
56
57 describe("path-relative from root dir (dir = '')", () => {
58 test("bare filename", () => {
59 expect(resolveMarkdownHref("", "img.png")).toBe("img.png");
60 });
61 test("./filename", () => {
62 expect(resolveMarkdownHref("", "./img.png")).toBe("img.png");
63 });
64 test("subdir/file", () => {
65 expect(resolveMarkdownHref("", "subdir/img.png")).toBe("subdir/img.png");
66 });
67 test("./subdir/file", () => {
68 expect(resolveMarkdownHref("", "./subdir/img.png")).toBe("subdir/img.png");
69 });
70 test("../ from root clamps to root", () => {
71 // URL API resolves http://x/../img.png → http://x/img.png
72 expect(resolveMarkdownHref("", "../img.png")).toBe("img.png");
73 });
74 });
75
76 describe("path-relative from one-level dir (dir = 'docs')", () => {
77 test("bare filename", () => {
78 expect(resolveMarkdownHref("docs", "img.png")).toBe("docs/img.png");
79 });
80 test("./filename", () => {
81 expect(resolveMarkdownHref("docs", "./img.png")).toBe("docs/img.png");
82 });
83 test("../ traversal to root", () => {
84 expect(resolveMarkdownHref("docs", "../img.png")).toBe("img.png");
85 });
86 test("subdir/file", () => {
87 expect(resolveMarkdownHref("docs", "subdir/img.png")).toBe("docs/subdir/img.png");
88 });
89 test("./subdir/file", () => {
90 expect(resolveMarkdownHref("docs", "./subdir/img.png")).toBe("docs/subdir/img.png");
91 });
92 });
93
94 describe("path-relative from nested dir (dir = 'docs/guide')", () => {
95 test("bare filename", () => {
96 expect(resolveMarkdownHref("docs/guide", "img.png")).toBe("docs/guide/img.png");
97 });
98 test("one level up", () => {
99 expect(resolveMarkdownHref("docs/guide", "../img.png")).toBe("docs/img.png");
100 });
101 test("two levels up", () => {
102 expect(resolveMarkdownHref("docs/guide", "../../img.png")).toBe("img.png");
103 });
104 test("sibling directory", () => {
105 expect(resolveMarkdownHref("docs/guide", "../assets/img.png")).toBe("docs/assets/img.png");
106 });
107 test("./filename", () => {
108 expect(resolveMarkdownHref("docs/guide", "./img.png")).toBe("docs/guide/img.png");
109 });
110 test("deeper subdir", () => {
111 expect(resolveMarkdownHref("docs/guide", "sub/img.png")).toBe("docs/guide/sub/img.png");
112 });
113 });
114});
115