|
| 1 | +import { describe, expect, it } from "vitest" |
| 2 | +import { createMisina } from "../src/index.ts" |
| 3 | + |
| 4 | +function recordingDriver() { |
| 5 | + const seen: string[] = [] |
| 6 | + return { |
| 7 | + seen, |
| 8 | + driver: { |
| 9 | + name: "rec", |
| 10 | + request: async (req: Request) => { |
| 11 | + seen.push(req.url) |
| 12 | + return new Response("{}", { headers: { "content-type": "application/json" } }) |
| 13 | + }, |
| 14 | + }, |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +describe("trailingSlash policy", () => { |
| 19 | + it("'preserve' (default) leaves the URL alone", async () => { |
| 20 | + const { seen, driver } = recordingDriver() |
| 21 | + const m = createMisina({ driver, retry: 0 }) |
| 22 | + |
| 23 | + await m.get("https://api.test/users/") |
| 24 | + await m.get("https://api.test/users") |
| 25 | + |
| 26 | + expect(seen).toEqual(["https://api.test/users/", "https://api.test/users"]) |
| 27 | + }) |
| 28 | + |
| 29 | + it("'strip' removes a single trailing slash", async () => { |
| 30 | + const { seen, driver } = recordingDriver() |
| 31 | + const m = createMisina({ driver, retry: 0, trailingSlash: "strip" }) |
| 32 | + |
| 33 | + await m.get("https://api.test/users/") |
| 34 | + expect(seen[0]).toBe("https://api.test/users") |
| 35 | + }) |
| 36 | + |
| 37 | + it("'strip' removes multiple trailing slashes", async () => { |
| 38 | + const { seen, driver } = recordingDriver() |
| 39 | + const m = createMisina({ driver, retry: 0, trailingSlash: "strip" }) |
| 40 | + |
| 41 | + await m.get("https://api.test/users///") |
| 42 | + expect(seen[0]).toBe("https://api.test/users") |
| 43 | + }) |
| 44 | + |
| 45 | + it("'strip' preserves the slash when path is just /", async () => { |
| 46 | + const { seen, driver } = recordingDriver() |
| 47 | + const m = createMisina({ driver, retry: 0, trailingSlash: "strip" }) |
| 48 | + |
| 49 | + // Bare origin URL — there's no path to strip. |
| 50 | + await m.get("https://api.test/") |
| 51 | + // Either form is acceptable depending on whether root counts as "no path". |
| 52 | + // The contract: don't break a bare URL. |
| 53 | + expect(seen[0] === "https://api.test/" || seen[0] === "https://api.test").toBe(true) |
| 54 | + }) |
| 55 | + |
| 56 | + it("'strip' keeps trailing slash before query string out of the path", async () => { |
| 57 | + const { seen, driver } = recordingDriver() |
| 58 | + const m = createMisina({ driver, retry: 0, trailingSlash: "strip" }) |
| 59 | + |
| 60 | + await m.get("https://api.test/users/?page=2") |
| 61 | + expect(seen[0]).toBe("https://api.test/users?page=2") |
| 62 | + }) |
| 63 | + |
| 64 | + it("'forbid' throws on a trailing slash", async () => { |
| 65 | + const m = createMisina({ |
| 66 | + driver: recordingDriver().driver, |
| 67 | + retry: 0, |
| 68 | + trailingSlash: "forbid", |
| 69 | + }) |
| 70 | + |
| 71 | + await expect(m.get("https://api.test/users/")).rejects.toThrow(/trailingSlash is "forbid"/) |
| 72 | + }) |
| 73 | + |
| 74 | + it("'forbid' allows URLs without a trailing slash", async () => { |
| 75 | + const { seen, driver } = recordingDriver() |
| 76 | + const m = createMisina({ driver, retry: 0, trailingSlash: "forbid" }) |
| 77 | + |
| 78 | + await m.get("https://api.test/users") |
| 79 | + expect(seen[0]).toBe("https://api.test/users") |
| 80 | + }) |
| 81 | + |
| 82 | + it("per-request override beats defaults", async () => { |
| 83 | + const { seen, driver } = recordingDriver() |
| 84 | + const m = createMisina({ driver, retry: 0, trailingSlash: "strip" }) |
| 85 | + |
| 86 | + await m.get("https://api.test/users/", { trailingSlash: "preserve" }) |
| 87 | + expect(seen[0]).toBe("https://api.test/users/") |
| 88 | + }) |
| 89 | + |
| 90 | + it("does not interfere with baseURL resolution", async () => { |
| 91 | + const { seen, driver } = recordingDriver() |
| 92 | + const m = createMisina({ |
| 93 | + driver, |
| 94 | + retry: 0, |
| 95 | + baseURL: "https://api.test/v1/", |
| 96 | + trailingSlash: "strip", |
| 97 | + }) |
| 98 | + |
| 99 | + await m.get("users/") |
| 100 | + expect(seen[0]).toBe("https://api.test/v1/users") |
| 101 | + }) |
| 102 | +}) |
0 commit comments