UNPKG

zod

Version:

TypeScript-first schema declaration and validation library with static type inference

164 lines (142 loc) • 4.7 kB
import { expect, expectTypeOf, test } from "vitest"; import * as z from "zod/v4"; test("successful validation", () => { const testTuple = z.tuple([z.string(), z.number()]); expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>(); const val = testTuple.parse(["asdf", 1234]); expect(val).toEqual(val); const r1 = testTuple.safeParse(["asdf", "asdf"]); expect(r1.success).toEqual(false); expect(r1.error!).toMatchInlineSnapshot(` [ZodError: [ { "expected": "number", "code": "invalid_type", "path": [ 1 ], "message": "Invalid input: expected number, received string" } ]] `); const r2 = testTuple.safeParse(["asdf", 1234, true]); expect(r2.success).toEqual(false); expect(r2.error!).toMatchInlineSnapshot(` [ZodError: [ { "origin": "array", "code": "too_big", "maximum": 2, "path": [], "message": "Too big: expected array to have <2 items" } ]] `); const r3 = testTuple.safeParse({}); expect(r3.success).toEqual(false); expect(r3.error!).toMatchInlineSnapshot(` [ZodError: [ { "expected": "tuple", "code": "invalid_type", "path": [], "message": "Invalid input: expected tuple, received object" } ]] `); }); test("async validation", async () => { const testTuple = z .tuple([z.string().refine(async () => true), z.number().refine(async () => true)]) .refine(async () => true); expectTypeOf<typeof testTuple._output>().toEqualTypeOf<[string, number]>(); const val = await testTuple.parseAsync(["asdf", 1234]); expect(val).toEqual(val); const r1 = await testTuple.safeParseAsync(["asdf", "asdf"]); expect(r1.success).toEqual(false); expect(r1.error!).toMatchInlineSnapshot(` [ZodError: [ { "expected": "number", "code": "invalid_type", "path": [ 1 ], "message": "Invalid input: expected number, received string" } ]] `); const r2 = await testTuple.safeParseAsync(["asdf", 1234, true]); expect(r2.success).toEqual(false); expect(r2.error!).toMatchInlineSnapshot(` [ZodError: [ { "origin": "array", "code": "too_big", "maximum": 2, "path": [], "message": "Too big: expected array to have <2 items" } ]] `); const r3 = await testTuple.safeParseAsync({}); expect(r3.success).toEqual(false); expect(r3.error!).toMatchInlineSnapshot(` [ZodError: [ { "expected": "tuple", "code": "invalid_type", "path": [], "message": "Invalid input: expected tuple, received object" } ]] `); }); test("tuple with optional elements", () => { const myTuple = z.tuple([z.string(), z.number().optional(), z.string().optional()]).rest(z.boolean()); expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number?, string?, ...boolean[]]>(); const goodData = [["asdf"], ["asdf", 1234], ["asdf", 1234, "asdf"], ["asdf", 1234, "asdf", true, false, true]]; for (const data of goodData) { expect(myTuple.parse(data)).toEqual(data); } const badData = [ ["asdf", "asdf"], ["asdf", 1234, "asdf", "asdf"], ["asdf", 1234, "asdf", true, false, "asdf"], ]; for (const data of badData) { expect(() => myTuple.parse(data)).toThrow(); } }); test("tuple with optional elements followed by required", () => { const myTuple = z.tuple([z.string(), z.number().optional(), z.string()]).rest(z.boolean()); expectTypeOf<typeof myTuple._output>().toEqualTypeOf<[string, number | undefined, string, ...boolean[]]>(); const goodData = [ ["asdf", 1234, "asdf"], ["asdf", 1234, "asdf", true, false, true], ]; for (const data of goodData) { expect(myTuple.parse(data)).toEqual(data); } const badData = [ ["asdf"], ["asdf", 1234], ["asdf", 1234, "asdf", "asdf"], ["asdf", 1234, "asdf", true, false, "asdf"], ]; for (const data of badData) { expect(() => myTuple.parse(data)).toThrow(); } }); test("tuple with rest schema", () => { const myTuple = z.tuple([z.string(), z.number()]).rest(z.boolean()); expect(myTuple.parse(["asdf", 1234, true, false, true])).toEqual(["asdf", 1234, true, false, true]); expect(myTuple.parse(["asdf", 1234])).toEqual(["asdf", 1234]); expect(() => myTuple.parse(["asdf", 1234, "asdf"])).toThrow(); type t1 = z.output<typeof myTuple>; expectTypeOf<t1>().toEqualTypeOf<[string, number, ...boolean[]]>(); }); test("sparse array input", () => { const schema = z.tuple([z.string(), z.number()]); expect(() => schema.parse(new Array(2))).toThrow(); });