mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-27 13:39:44 -08:00
114 lines
2.6 KiB
TypeScript
114 lines
2.6 KiB
TypeScript
|
import { z } from 'zod';
|
||
|
|
||
|
import { parseSchema } from '../../src/parsers/parse-schema';
|
||
|
|
||
|
describe('parseSchema', () => {
|
||
|
test('should be usable without providing refs', () => {
|
||
|
expect(parseSchema({ type: 'string' })).toMatchZod(z.string());
|
||
|
});
|
||
|
|
||
|
test('should return a seen and processed ref', () => {
|
||
|
const seen = new Map();
|
||
|
const schema = {
|
||
|
type: 'object',
|
||
|
properties: {
|
||
|
prop: {
|
||
|
type: 'string',
|
||
|
},
|
||
|
},
|
||
|
};
|
||
|
expect(parseSchema(schema, { seen, path: [] }));
|
||
|
expect(parseSchema(schema, { seen, path: [] }));
|
||
|
});
|
||
|
|
||
|
test('should be possible to describe a readonly schema', () => {
|
||
|
expect(parseSchema({ type: 'string', readOnly: true })).toMatchZod(z.string().readonly());
|
||
|
});
|
||
|
|
||
|
test('should handle nullable', () => {
|
||
|
expect(
|
||
|
parseSchema(
|
||
|
{
|
||
|
type: 'string',
|
||
|
nullable: true,
|
||
|
},
|
||
|
{ path: [], seen: new Map() },
|
||
|
),
|
||
|
).toMatchZod(z.string().nullable());
|
||
|
});
|
||
|
|
||
|
test('should handle enum', () => {
|
||
|
expect(parseSchema({ enum: ['someValue', 57] })).toMatchZod(
|
||
|
z.union([z.literal('someValue'), z.literal(57)]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('should handle multiple type', () => {
|
||
|
expect(parseSchema({ type: ['string', 'number'] })).toMatchZod(
|
||
|
z.union([z.string(), z.number()]),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('should handle if-then-else type', () => {
|
||
|
expect(
|
||
|
parseSchema({
|
||
|
if: { type: 'string' },
|
||
|
then: { type: 'number' },
|
||
|
else: { type: 'boolean' },
|
||
|
}),
|
||
|
).toMatchZod(
|
||
|
z.union([z.number(), z.boolean()]).superRefine((value, ctx) => {
|
||
|
const result = z.string().safeParse(value).success
|
||
|
? z.number().safeParse(value)
|
||
|
: z.boolean().safeParse(value);
|
||
|
if (!result.success) {
|
||
|
result.error.errors.forEach((error) => ctx.addIssue(error));
|
||
|
}
|
||
|
}),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
test('should handle anyOf', () => {
|
||
|
expect(
|
||
|
parseSchema({
|
||
|
anyOf: [
|
||
|
{
|
||
|
type: 'string',
|
||
|
},
|
||
|
{ type: 'number' },
|
||
|
],
|
||
|
}),
|
||
|
).toMatchZod(z.union([z.string(), z.number()]));
|
||
|
});
|
||
|
|
||
|
test('should handle oneOf', () => {
|
||
|
expect(
|
||
|
parseSchema({
|
||
|
oneOf: [
|
||
|
{
|
||
|
type: 'string',
|
||
|
},
|
||
|
{ type: 'number' },
|
||
|
],
|
||
|
}),
|
||
|
).toMatchZod(
|
||
|
z.any().superRefine((x, ctx) => {
|
||
|
const schemas = [z.string(), z.number()];
|
||
|
const errors = schemas.reduce<z.ZodError[]>(
|
||
|
(errors, schema) =>
|
||
|
((result) => (result.error ? [...errors, result.error] : errors))(schema.safeParse(x)),
|
||
|
[],
|
||
|
);
|
||
|
if (schemas.length - errors.length !== 1) {
|
||
|
ctx.addIssue({
|
||
|
path: ctx.path,
|
||
|
code: 'invalid_union',
|
||
|
unionErrors: errors,
|
||
|
message: 'Invalid input: Should pass single schema',
|
||
|
});
|
||
|
}
|
||
|
}),
|
||
|
);
|
||
|
});
|
||
|
});
|