1import { assert, it } from "@effect/vitest"
2import { FindMyWay as Router } from "effect/http"
3
4it("should setup parametric and regexp node", () => {
5 const router = Router.make<number>()
6
7 router.on("GET", "/foo/:bar", 1)
8 router.on("GET", "/foo/:bar(123)", 2)
9
10 assert.strictEqual(router.find("GET", "/foo/value")?.handler, 1)
11 assert.strictEqual(router.find("GET", "/foo/123")?.handler, 2)
12})
13
14it("should setup parametric and multi-parametric node", () => {
15 const router = Router.make<number>()
16
17 router.on("GET", "/foo/:bar", 1)
18 router.on("GET", "/foo/:bar.png", 2)
19
20 assert.strictEqual(router.find("GET", "/foo/value")?.handler, 1)
21 assert.strictEqual(router.find("GET", "/foo/value.png")?.handler, 2)
22})
23
24it("should throw when set upping two parametric nodes", () => {
25 const router = Router.make<number>()
26 router.on("GET", "/foo/:bar", 1)
27 assert.throws(() => router.on("GET", "/foo/:baz", 2))
28})
29
30it("should throw when set upping two regexp nodes", () => {
31 const router = Router.make<number>()
32 router.on("GET", "/foo/:bar(123)", 1)
33 assert.throws(() => router.on("GET", "/foo/:bar(456)", 2))
34})
35
36it("should set up two parametric nodes with static ending", () => {
37 const router = Router.make<number>()
38
39 router.on("GET", "/foo/:bar.png", 1)
40 router.on("GET", "/foo/:bar.jpeg", 2)
41
42 assert.strictEqual(router.find("GET", "/foo/value.png")?.handler, 1)
43 assert.strictEqual(router.find("GET", "/foo/value.jpeg")?.handler, 2)
44})
45
46it("should set up two regexp nodes with static ending", () => {
47 const router = Router.make<number>()
48
49 router.on("GET", "/foo/:bar(123).png", 1)
50 router.on("GET", "/foo/:bar(456).jpeg", 2)
51
52 assert.strictEqual(router.find("GET", "/foo/123.png")?.handler, 1)
53 assert.strictEqual(router.find("GET", "/foo/456.jpeg")?.handler, 2)
54})
55
56it("node with longer static suffix should have higher priority", () => {
57 const router = Router.make<number>()
58
59 router.on("GET", "/foo/:bar.png", 1)
60 router.on("GET", "/foo/:bar.png.png", 2)
61
62 assert.strictEqual(router.find("GET", "/foo/value.png")?.handler, 1)
63 assert.strictEqual(router.find("GET", "/foo/value.png.png")?.handler, 2)
64})
65
66it("node with longer static suffix should have higher priority", () => {
67 const router = Router.make<number>()
68
69 router.on("GET", "/foo/:bar.png.png", 2)
70 router.on("GET", "/foo/:bar.png", 1)
71
72 assert.strictEqual(router.find("GET", "/foo/value.png")?.handler, 1)
73 assert.strictEqual(router.find("GET", "/foo/value.png.png")?.handler, 2)
74})
75
76it("should set up regexp node and node with static ending", () => {
77 const router = Router.make<number>()
78
79 router.on("GET", "/foo/:bar(123)", 1)
80 router.on("GET", "/foo/:bar(123).jpeg", 2)
81
82 assert.strictEqual(router.find("GET", "/foo/123")?.handler, 1)
83 assert.strictEqual(router.find("GET", "/foo/123.jpeg")?.handler, 2)
84})
85
86it("distinguishes routes with different static parts between parameters", () => {
87 const router = Router.make<string>()
88
89 router.on("GET", "/foo/:a-:b", "dash")
90 router.on("GET", "/foo/:a.:b", "dot")
91
92 assert.strictEqual(router.find("GET", "/foo/x-y")?.handler, "dash")
93 assert.strictEqual(router.find("GET", "/foo/x.y")?.handler, "dot")
94})
95
96it("preserves prototype-sensitive parameter names as own properties", () => {
97 const router = Router.make<boolean>()
98 router.on("GET", "/foo/:__proto__/:constructor/:toString", true)
99
100 const params = router.find("GET", "/foo/a/b/c")!.params
101 assert.strictEqual(Object.getPrototypeOf(params), null)
102 assert.deepStrictEqual(Object.entries(params), [["__proto__", "a"], ["constructor", "b"], ["toString", "c"]])
103})