1import { assert, describe, it } from "@effect/vitest"
2import { assertNone, assertSome, deepStrictEqual } from "@effect/vitest/utils"
3import { Schema } from "effect"
4import { UrlParams } from "effect/http"
5import { assertSuccess } from "../utils/assert.ts"
6
7describe("UrlParams", () => {
8 describe("fromInput", () => {
9 it("coerces null to a string", () => {
10 deepStrictEqual(UrlParams.fromInput({ filter: null }).params, [["filter", "null"]])
11 })
12 })
13
14 describe("setAll", () => {
15 it("does not retain parameters when reusing UrlParams overrides", () => {
16 const overrides = UrlParams.fromInput({ sort: "name" })
17
18 UrlParams.setAll(UrlParams.fromInput({ page: 1 }), overrides)
19 assert.strictEqual(
20 UrlParams.toString(UrlParams.setAll(UrlParams.fromInput({ page: 2 }), overrides)),
21 "sort=name&page=2"
22 )
23 })
24 })
25
26 describe("Schema.UrlParams", () => {
27 it("round-trips ordered pairs with the serializer annotation", () => {
28 const iso = Schema.toIso(Schema.UrlParams)
29 const params = UrlParams.make([["a", "1"], ["b", "2"]])
30 assertSuccess(iso.getResult(params), [["a", "1"], ["b", "2"]])
31 assertSuccess(iso.replaceResult([["a", "1"], ["b", "3"]], params), UrlParams.make([["a", "1"], ["b", "3"]]))
32 })
33 })
34
35 it("getFirst and getLast return Option", () => {
36 const params = UrlParams.fromInput([[
37 "foo",
38 "a"
39 ], [
40 "foo",
41 "b"
42 ]])
43 assertSome(UrlParams.getFirst(params, "foo"), "a")
44 assertSome(UrlParams.getLast(params, "foo"), "b")
45 assertNone(UrlParams.getFirst(params, "bar"))
46 assertNone(UrlParams.getLast(params, "bar"))
47 })
48
49 it("JsonFromUrlParamsField applies a JSON reviver", () => {
50 const schema = Schema.JsonFromUrlParamsField("json", {
51 reviver: (key, value) => key === "value" ? "revived" : value
52 }).pipe(Schema.decodeTo(Schema.Struct({ value: Schema.String })))
53
54 deepStrictEqual(
55 Schema.decodeSync(schema)(UrlParams.fromInput({ json: "{\"value\":\"original\"}" })),
56 { value: "revived" }
57 )
58 })
59
60 it("RecordFromUrlParams preserves single and repeated values", () => {
61 const params = UrlParams.make([["a", "1"], ["a", "2"], ["b", "3"]])
62
63 deepStrictEqual(Schema.decodeSync(Schema.RecordFromUrlParams)(params), {
64 a: ["1", "2"],
65 b: "3"
66 })
67 deepStrictEqual(
68 Schema.encodeSync(Schema.RecordFromUrlParams)({ a: ["1", "2"], b: "3" }),
69 params
70 )
71 })
72})