Files
SnowLuma/.pnpm-store/v11/files/6d/2850ac9b7cd39317af5d5dfe1f7ad604198fcf2ff80873eeef473c512cace00741c3a0e2bb47f56d0d3783522a46b125bc49f904f574dc158665194f323242
TanTan 2a69b23b47
Dev Build / cleanup (push) Canceled after 0s
Dev Build / typecheck (push) Canceled after 0s
Dev Build / build (linux-arm64, ubuntu-24.04-arm, linux-arm64) (push) Canceled after 0s
Dev Build / build (linux-x64, ubuntu-latest, linux-x64) (push) Canceled after 0s
Dev Build / build (win-x64, windows-latest, win32-x64) (push) Canceled after 0s
Dev Build / dispatch-dev-docker (push) Skipped
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

85 lines
2.0 KiB
Plaintext

import { beforeEach, expect, test } from "vitest";
import * as z from "zod/mini";
// the config object lives on globalThis, so only file isolation protects it; pin the unset precondition explicitly
beforeEach(() => {
delete z.config().memoizer;
});
const cyclic = (): any => {
const input: any = { id: 1 };
input.self = input;
return input;
};
test("cyclic input needs the memoizer opt-in", () => {
const Before: any = z.object({
id: z.number(),
get self() {
return Before;
},
});
expect(() => Before.parse(cyclic())).toThrow(RangeError);
z.config({ memoizer: z.memoizer() });
const After: any = z.object({
id: z.number(),
get self() {
return After;
},
});
const out = After.parse(cyclic());
expect(out.self).toBe(out);
expect(out).not.toBe(cyclic());
// read at construction, so a schema built before the opt-in keeps none
expect(() => Before.parse(cyclic())).toThrow(RangeError);
});
test("the opt-in reaches every core container", () => {
z.config({ memoizer: z.memoizer() });
const Arr: any = z.array(z.lazy(() => Arr));
const input: any = [];
input.push(input);
const out = Arr.parse(input);
expect(out[0]).toBe(out);
});
test("rejects a cycle that closes through a transform", () => {
z.config({ memoizer: z.memoizer() });
const Inner: any = z.object({
name: z.string(),
get self() {
return Wrapped;
},
});
const Wrapped: any = z.pipe(
Inner,
z.transform((value: any) => ({ wrapped: value }))
);
const input: any = { name: "x" };
input.self = input;
expect(() => Wrapped.parse(input)).toThrow(/reference cycle/);
});
test("leaves a transform that is not on the cycle alone", () => {
z.config({ memoizer: z.memoizer() });
const Node: any = z.object({
n: z.pipe(
z.number(),
z.transform((value: number) => value * 2)
),
get self() {
return Node;
},
});
const input: any = { n: 21 };
input.self = input;
const result = Node.parse(input);
expect(result.n).toBe(42);
expect(result.self).toBe(result);
});