Files
sendou.ink/app/modules/search-params/search-params-test-utils.ts
2026-09-02 21:02:01 +03:00

78 lines
2.1 KiB
TypeScript

import { expect } from "vitest";
import type {
ParamDef,
SearchParamsDefinition,
SearchParamsValues,
} from "./search-params";
import * as SearchParams from "./search-params";
type AnyShape = Record<string, ParamDef<any>>;
/** Asserts `decode(encode(x))` deep-equals `x` through plain and compressed forms and a full `href` → `parse` cycle. */
export function assertRoundTrips<Shape extends AnyShape>(
definition: SearchParamsDefinition<Shape>,
examples: {
[K in keyof Shape]: Array<SearchParamsValues<Shape>[K]>;
},
) {
for (const key of definition.keys) {
const def = definition.shape[key];
expect
.soft(SearchParams.decodeParam(def, []), `${key}: absent → default`)
.toEqual(def.default);
for (const value of examples[key]) {
const encoded = SearchParams.encodeParam(def, value);
expect
.soft(
SearchParams.decodeParam(def, encoded),
`${key}: plain round trip of ${JSON.stringify(value)}`,
)
.toEqual(value);
const compressed =
def.compress || encoded.length === 0
? encoded
: def
.encodePlain(value)
.map((plain) => SearchParams.compressTransportValue(plain));
expect
.soft(
SearchParams.decodeParam(def, compressed),
`${key}: compressed round trip of ${JSON.stringify(value)}`,
)
.toEqual(value);
const href = definition.href("/round-trip", {
[key]: value,
} as Partial<SearchParamsValues<Shape>>);
const parsed = definition.parse(new URL(href, "http://localhost"));
expect
.soft(
parsed[key],
`${key}: href → parse round trip of ${JSON.stringify(value)}`,
)
.toEqual(value);
}
}
}
/** Asserts that each given raw URL value list decodes to the param's default. */
export function assertDecodesToDefault<Shape extends AnyShape>(
definition: SearchParamsDefinition<Shape>,
key: keyof Shape & string,
rawValuesList: string[][],
) {
const def = definition.shape[key];
for (const rawValues of rawValuesList) {
expect
.soft(
SearchParams.decodeParam(def, rawValues),
`${key}: ${JSON.stringify(rawValues)} → default`,
)
.toEqual(def.default);
}
}