From 259b4dcf128aba909e1108b269c96dca6d5be9b9 Mon Sep 17 00:00:00 2001 From: Alex Johansson Date: Sun, 15 May 2022 10:49:01 +0200 Subject: [PATCH] fix(zod): add ability to skip zod's parsing (#401) * skip zod parsing * align coding style --- zod/src/__tests__/__fixtures__/data.ts | 9 +++- zod/src/__tests__/__snapshots__/zod.ts.snap | 53 +++++++++++++++++++++ zod/src/__tests__/zod.ts | 11 +++-- zod/src/types.ts | 12 ++++- zod/src/zod.ts | 2 +- 5 files changed, 80 insertions(+), 7 deletions(-) diff --git a/zod/src/__tests__/__fixtures__/data.ts b/zod/src/__tests__/__fixtures__/data.ts index 5009fcdd..01923b40 100644 --- a/zod/src/__tests__/__fixtures__/data.ts +++ b/zod/src/__tests__/__fixtures__/data.ts @@ -29,13 +29,19 @@ export const schema = z }), ) .optional(), + dateStr: z + .string() + .transform((value) => new Date(value)) + .refine((value) => !isNaN(value.getTime()), { + message: 'Invalid date', + }), }) .refine((obj) => obj.password === obj.repeatPassword, { message: 'Passwords do not match', path: ['confirm'], }); -export const validData: z.infer = { +export const validData: z.input = { username: 'Doe', password: 'Password123_', repeatPassword: 'Password123_', @@ -51,6 +57,7 @@ export const validData: z.infer = { name: 'name', }, ], + dateStr: '2020-01-01', }; export const invalidData = { diff --git a/zod/src/__tests__/__snapshots__/zod.ts.snap b/zod/src/__tests__/__snapshots__/zod.ts.snap index f5ad22ab..4c56c6bd 100644 --- a/zod/src/__tests__/__snapshots__/zod.ts.snap +++ b/zod/src/__tests__/__snapshots__/zod.ts.snap @@ -13,6 +13,11 @@ Object { "ref": undefined, "type": "invalid_type", }, + "dateStr": Object { + "message": "Required", + "ref": undefined, + "type": "invalid_type", + }, "email": Object { "message": "Invalid email", "ref": Object { @@ -86,6 +91,11 @@ Object { "ref": undefined, "type": "invalid_type", }, + "dateStr": Object { + "message": "Required", + "ref": undefined, + "type": "invalid_type", + }, "email": Object { "message": "Invalid email", "ref": Object { @@ -169,6 +179,14 @@ Object { "invalid_type": "Expected number, received string", }, }, + "dateStr": Object { + "message": "Required", + "ref": undefined, + "type": "invalid_type", + "types": Object { + "invalid_type": "Required", + }, + }, "email": Object { "message": "Invalid email", "ref": Object { @@ -284,6 +302,14 @@ Object { "invalid_type": "Expected number, received string", }, }, + "dateStr": Object { + "message": "Required", + "ref": undefined, + "type": "invalid_type", + "types": Object { + "invalid_type": "Required", + }, + }, "email": Object { "message": "Invalid email", "ref": Object { @@ -375,3 +401,30 @@ Object { "values": Object {}, } `; + +exports[`zodResolver should return parsed values from zodResolver with \`mode: sync\` when validation pass 1`] = ` +Object { + "errors": Object {}, + "values": Object { + "accessToken": "accessToken", + "birthYear": 2000, + "dateStr": 2020-01-01T00:00:00.000Z, + "email": "john@doe.com", + "enabled": true, + "like": Array [ + Object { + "id": 1, + "name": "name", + }, + ], + "password": "Password123_", + "repeatPassword": "Password123_", + "tags": Array [ + "tag1", + "tag2", + ], + "url": "https://react-hook-form.com/", + "username": "Doe", + }, +} +`; diff --git a/zod/src/__tests__/zod.ts b/zod/src/__tests__/zod.ts index 3ee2fa5d..a932fedf 100644 --- a/zod/src/__tests__/zod.ts +++ b/zod/src/__tests__/zod.ts @@ -4,10 +4,12 @@ import { schema, validData, invalidData, fields } from './__fixtures__/data'; const shouldUseNativeValidation = false; describe('zodResolver', () => { - it('should return values from zodResolver when validation pass', async () => { + it('should return values from zodResolver when validation pass & rawValues=true', async () => { const parseAsyncSpy = jest.spyOn(schema, 'parseAsync'); - const result = await zodResolver(schema)(validData, undefined, { + const result = await zodResolver(schema, undefined, { + rawValues: true, + })(validData, undefined, { fields, shouldUseNativeValidation, }); @@ -16,7 +18,7 @@ describe('zodResolver', () => { expect(result).toEqual({ errors: {}, values: validData }); }); - it('should return values from zodResolver with `mode: sync` when validation pass', async () => { + it('should return parsed values from zodResolver with `mode: sync` when validation pass', async () => { const parseSpy = jest.spyOn(schema, 'parse'); const parseAsyncSpy = jest.spyOn(schema, 'parseAsync'); @@ -26,7 +28,8 @@ describe('zodResolver', () => { expect(parseSpy).toHaveBeenCalledTimes(1); expect(parseAsyncSpy).not.toHaveBeenCalled(); - expect(result).toEqual({ errors: {}, values: validData }); + expect(result.errors).toEqual({}); + expect(result).toMatchSnapshot(); }); it('should return a single error from zodResolver when validation fails', async () => { diff --git a/zod/src/types.ts b/zod/src/types.ts index 58c7b54c..4f053916 100644 --- a/zod/src/types.ts +++ b/zod/src/types.ts @@ -9,7 +9,17 @@ import { z } from 'zod'; export type Resolver = >( schema: T, schemaOptions?: Partial, - factoryOptions?: { mode?: 'async' | 'sync' }, + factoryOptions?: { + /** + * @default async + */ + mode?: 'async' | 'sync'; + /** + * Return the raw input values rather than the parsed values. + * @default false + */ + rawValues?: boolean; + }, ) => ( values: UnpackNestedValue, context: TContext | undefined, diff --git a/zod/src/zod.ts b/zod/src/zod.ts index 847afa01..4b6ab72e 100644 --- a/zod/src/zod.ts +++ b/zod/src/zod.ts @@ -69,7 +69,7 @@ export const zodResolver: Resolver = return { errors: {} as FieldErrors, - values: data, + values: resolverOptions.rawValues ? values : data, }; } catch (error: any) { return {