项目文件夹

文件
wehub-resource-sync 70bf21e064
Prerelease / build (push) Has been skipped
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:11 +08:00

459 行
12 KiB
TypeScript

import assert from "node:assert";
import { _forceColour, formatZodError } from "miniflare";
import { describe, test } from "vitest";
import { z } from "zod";
function formatZodErrorForTest(
schema: z.ZodTypeAny,
input: unknown,
colour?: boolean
) {
const result = schema.safeParse(input);
assert(!result.success);
// Disable colours by default for easier-to-read snapshots
_forceColour(colour ?? false);
return formatZodError(result.error, input);
}
describe("formatZodError:", () => {
test("formats primitive schema with primitive input", ({ expect }) => {
const formatted = formatZodErrorForTest(z.number(), false);
expect(formatted).toMatchInlineSnapshot(`
"false
^ Expected number, received boolean"
`);
});
test("formats primitive schema with object input", ({ expect }) => {
const formatted = formatZodErrorForTest(z.string(), {
a: 1,
b: { c: 1 },
});
expect(formatted).toMatchInlineSnapshot(`
"{ a: 1, b: [Object] }
^ Expected string, received object"
`);
});
test("formats object schema with primitive input", ({ expect }) => {
const formatted = formatZodErrorForTest(z.object({ a: z.number() }), true);
expect(formatted).toMatchInlineSnapshot(`
"true
^ Expected object, received boolean"
`);
});
test("formats object schema with object input", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({
a: z.string(),
b: z.number(),
c: z.boolean(),
d: z.number(),
e: z.number(),
f: z.boolean(),
g: z.boolean(),
}),
{
a: "", // Check skips valid
b: "2",
c: true, // Check skips valid
d: 4, // Check doesn't duplicate `...` when skipping valid
e: 5,
/*f*/ // Check required options
g: "7",
}
);
expect(formatted).toMatchInlineSnapshot(`
"{
...,
b: '2',
^ Expected number, received string
...,
g: '7',
^ Expected boolean, received string
f: undefined,
^ Required
}"
`);
});
test("formats object schema with additional options", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({ a: z.number() }).strict(),
{ a: 1, b: 2 }
);
expect(formatted).toMatchInlineSnapshot(`
"{ a: 1, b: 2 }
^ Unrecognized key(s) in object: 'b'"
`);
});
test("formats array schema with primitive input", ({ expect }) => {
const formatted = formatZodErrorForTest(z.array(z.boolean()), 1);
expect(formatted).toMatchInlineSnapshot(`
"1
^ Expected array, received number"
`);
});
test("formats array schema with array input", ({ expect }) => {
const formatted = formatZodErrorForTest(z.array(z.number()), [
1, // Check skips valid
2, // Check doesn't duplicate `...` when skipping valid
"3",
4,
5,
false,
]);
expect(formatted).toMatchInlineSnapshot(`
"[
...,
/* [2] */ '3',
^ Expected number, received string
...,
/* [5] */ false,
^ Expected number, received boolean
]"
`);
});
test("formats array schema with additional options", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.array(z.number()).max(3),
[1, 2, 3, 4, 5]
);
expect(formatted).toMatchInlineSnapshot(`
"[ 1, 2, 3, 4, 5 ]
^ Array must contain at most 3 element(s)"
`);
});
test("formats deeply nested schema", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({
a: z.number(),
b: z.object({
c: z.string(),
d: z.array(z.object({ e: z.boolean() })),
f: z.array(z.number()),
}),
g: z.string(),
}),
{
a: "1",
b: {
c: 2,
d: [{ e: true }, { e: 42 }, false, {}],
f: () => {},
},
}
);
expect(formatted).toMatchInlineSnapshot(`
"{
a: '1',
^ Expected number, received string
b: {
c: 2,
^ Expected string, received number
d: [
...,
/* [1] */ {
e: 42,
^ Expected boolean, received number
},
/* [2] */ false,
^ Expected object, received boolean
/* [3] */ {
e: undefined,
^ Required
},
],
f: [Function: f],
^ Expected array, received function
},
g: undefined,
^ Required
}"
`);
});
test("formats large actual values", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({
a: z.object({
b: z.string(),
}),
}),
{
a: {
// Check indents inspected value at correct depth
b: Array.from({ length: 50 }).map((_, i) => i),
},
}
);
expect(formatted).toMatchInlineSnapshot(`
"{
a: {
b: [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49
],
^ Expected string, received array
},
}"
`);
});
test("formats union schema", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.union([z.boolean(), z.literal(1)]),
"a"
);
expect(formatted).toMatchInlineSnapshot(`
"'a'
^ Expected boolean, received string
Invalid literal value, expected 1"
`);
});
const discriminatedUnionSchema = z.discriminatedUnion("type", [
z.object({
type: z.literal("a"),
a: z.number(),
}),
z.object({
type: z.literal("b"),
b: z.boolean(),
}),
]);
test("formats discriminated union schema", ({ expect }) => {
const formatted = formatZodErrorForTest(discriminatedUnionSchema, {
type: "a",
a: false,
});
expect(formatted).toMatchInlineSnapshot(`
"{
...,
a: false,
^ Expected number, received boolean
}"
`);
});
test("formats discriminated union schema with invalid discriminator", ({
expect,
}) => {
const formatted = formatZodErrorForTest(discriminatedUnionSchema, {
type: "c",
});
expect(formatted).toMatchInlineSnapshot(`
"{
type: 'c',
^ Invalid discriminator value. Expected 'a' | 'b'
}"
`);
});
test("formats intersection schema", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.intersection(z.number(), z.literal(2)),
false
);
expect(formatted).toMatchInlineSnapshot(`
"false
^ Expected number, received boolean
Invalid literal value, expected 2"
`);
});
const objectUnionSchema = z.object({
key: z.string(),
objects: z.array(
z.union([
z.object({ a: z.number() }),
z.object({ b: z.boolean() }),
z.object({ c: z.string() }),
])
),
});
test("formats object union schema", ({ expect }) => {
const formatted = formatZodErrorForTest(objectUnionSchema, {
key: false,
objects: [false, { a: 1 }, {}, [], { d: "" }],
});
expect(formatted).toMatchInlineSnapshot(`
"{
key: false,
^ Expected string, received boolean
objects: [
/* [0] */ false,
^ Expected object, received boolean
...,
/* [2] */ {
a: undefined,
^1 Required *or*
b: undefined,
^1 Required *or*
c: undefined,
^1 Required
},
/* [3] */ [],
^ Expected object, received array
/* [4] */ {
...,
a: undefined,
^2 Required *or*
b: undefined,
^2 Required *or*
c: undefined,
^2 Required
},
],
}"
`);
});
test("formats object union schema in colour", ({ expect }) => {
const formatted = formatZodErrorForTest(
objectUnionSchema,
{
key: false,
objects: [false, {}, {}, {}, {}, {}, /* cycle */ {}, {}],
},
/* colour */ true
);
expect(formatted).toMatchInlineSnapshot(`
"{
key: false,
 ^ Expected string, received boolean
objects: [
/* [0] */ false,
 ^ Expected object, received boolean
/* [1] */ {
a: undefined,
 ^1 Required *or*
b: undefined,
 ^1 Required *or*
c: undefined,
 ^1 Required
},
/* [2] */ {
a: undefined,
 ^2 Required *or*
b: undefined,
 ^2 Required *or*
c: undefined,
 ^2 Required
},
/* [3] */ {
a: undefined,
 ^3 Required *or*
b: undefined,
 ^3 Required *or*
c: undefined,
 ^3 Required
},
/* [4] */ {
a: undefined,
 ^4 Required *or*
b: undefined,
 ^4 Required *or*
c: undefined,
 ^4 Required
},
/* [5] */ {
a: undefined,
 ^5 Required *or*
b: undefined,
 ^5 Required *or*
c: undefined,
 ^5 Required
},
/* [6] */ {
a: undefined,
 ^6 Required *or*
b: undefined,
 ^6 Required *or*
c: undefined,
 ^6 Required
},
/* [7] */ {
a: undefined,
 ^7 Required *or*
b: undefined,
 ^7 Required *or*
c: undefined,
 ^7 Required
},
],
}"
`);
});
test("formats tuple union schema", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({
tuples: z.array(
z.union([
z.tuple([z.string(), z.number()]),
z.tuple([z.boolean(), z.boolean(), z.boolean()]),
])
),
}),
{
tuples: [false, { a: 1 }, [], ["2", "3"], [4, 5, 6], [true, 7, false]],
}
);
expect(formatted).toMatchInlineSnapshot(`
"{
tuples: [
/* [0] */ false,
^ Expected array, received boolean
/* [1] */ { a: 1 },
^ Expected array, received object
/* [2] */ [],
^ Array must contain at least 2 element(s)
Array must contain at least 3 element(s)
/* [3] */ [
...,
/* [1] */ '3',
^ Expected number, received string
],
/* [4] */ [
/* [0] */ 4,
^1 Expected string, received number
Expected boolean, received number *or*
/* [1] */ 5,
^1 Expected boolean, received number *or*
/* [2] */ 6,
^1 Expected boolean, received number
],
/* [5] */ [
/* [0] */ true,
^2 Expected string, received boolean *or*
/* [1] */ 7,
^2 Expected boolean, received number
...,
],
],
}"
`);
});
test("formats custom message schema", ({ expect }) => {
const formatted = formatZodErrorForTest(
z.object({
a: z.custom<never>(() => false, {
message: "Custom message\nwith multiple\nlines",
}),
}),
{ a: Symbol("kOoh") }
);
expect(formatted).toMatchInlineSnapshot(`
"{
a: Symbol(kOoh),
^ Custom message
with multiple
lines
}"
`);
});
});