diff --git a/tests/zod.spec.ts b/tests/zod.spec.ts index e297351a..75b93d1a 100644 --- a/tests/zod.spec.ts +++ b/tests/zod.spec.ts @@ -3,64 +3,94 @@ import { dedent } from 'ts-dedent'; import { plugin } from '../src/index'; +const initialEmitValue = dedent(` + type Properties = Required<{ + [K in keyof T]: z.ZodType; + }>; + + type definedNonNullAny = {}; + + export const isDefinedNonNullAny = (v: any): v is definedNonNullAny => v !== undefined && v !== null; + + export const definedNonNullAnySchema = z.any().refine((v) => isDefinedNonNullAny(v)); + + + `) + +function removedInitialEmitValue(content: string) { + return content.replace(initialEmitValue, ''); +} + describe('zod', () => { - it.each([ - [ - 'non-null and defined', - { - textSchema: /* GraphQL */ ` - input PrimitiveInput { - a: ID! - b: String! - c: Boolean! - d: Int! - e: Float! - } - `, - wantContains: [ - 'export function PrimitiveInputSchema(): z.ZodObject>', - 'a: z.string()', - 'b: z.string()', - 'c: z.boolean()', - 'd: z.number()', - 'e: z.number()', - ], - scalars: { - ID: 'string', - }, - }, - ], - [ - 'nullish', - { - textSchema: /* GraphQL */ ` - input PrimitiveInput { - a: ID - b: String - c: Boolean - d: Int - e: Float - z: String! # no defined check - } - `, - wantContains: [ - 'export function PrimitiveInputSchema(): z.ZodObject>', - // alphabet order - 'a: z.string().nullish(),', - 'b: z.string().nullish(),', - 'c: z.boolean().nullish(),', - 'd: z.number().nullish(),', - 'e: z.number().nullish(),', - ], - scalars: { - ID: 'string', - }, - }, - ], - [ - 'array', - { - textSchema: /* GraphQL */ ` + it('non-null and defined', async () => { + const schema = buildSchema(/* GraphQL */ ` + input PrimitiveInput { + a: ID! + b: String! + c: Boolean! + d: Int! + e: Float! + } + `); + const scalars = { + ID: 'string', + } + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { z } from 'zod'", + ] + `); + + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function PrimitiveInputSchema(): z.ZodObject> { + return z.object({ + a: z.string(), + b: z.string(), + c: z.boolean(), + d: z.number(), + e: z.number() + }) + } + " + `); + }) + + it('nullish', async () => { + const schema = buildSchema(/* GraphQL */ ` + input PrimitiveInput { + a: ID + b: String + c: Boolean + d: Int + e: Float + z: String! # no defined check + } + `); + const scalars = { + ID: 'string', + } + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function PrimitiveInputSchema(): z.ZodObject> { + return z.object({ + a: z.string().nullish(), + b: z.string().nullish(), + c: z.boolean().nullish(), + d: z.number().nullish(), + e: z.number().nullish(), + z: z.string() + }) + } + " + `) + }) + + it('array', async () => { + const schema = buildSchema(/* GraphQL */ ` input ArrayInput { a: [String] b: [String!] @@ -69,23 +99,27 @@ describe('zod', () => { e: [[String]!] f: [[String]!]! } - `, - wantContains: [ - 'export function ArrayInputSchema(): z.ZodObject>', - 'a: z.array(z.string().nullable()).nullish(),', - 'b: z.array(z.string()).nullish(),', - 'c: z.array(z.string()),', - 'd: z.array(z.array(z.string().nullable()).nullish()).nullish(),', - 'e: z.array(z.array(z.string().nullable())).nullish(),', - 'f: z.array(z.array(z.string().nullable()))', - ], - scalars: undefined, - }, - ], - [ - 'ref input object', - { - textSchema: /* GraphQL */ ` + `); + const scalars = undefined + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function ArrayInputSchema(): z.ZodObject> { + return z.object({ + a: z.array(z.string().nullable()).nullish(), + b: z.array(z.string()).nullish(), + c: z.array(z.string()), + d: z.array(z.array(z.string().nullable()).nullish()).nullish(), + e: z.array(z.array(z.string().nullable())).nullish(), + f: z.array(z.array(z.string().nullable())) + }) + } + " + `) + }) + + it('ref input object', async () => { + const schema = buildSchema(/* GraphQL */ ` input AInput { b: BInput! } @@ -95,39 +129,55 @@ describe('zod', () => { input CInput { a: AInput! } - `, - wantContains: [ - 'export function AInputSchema(): z.ZodObject>', - 'b: z.lazy(() => BInputSchema())', - 'export function BInputSchema(): z.ZodObject>', - 'c: z.lazy(() => CInputSchema())', - 'export function CInputSchema(): z.ZodObject>', - 'a: z.lazy(() => AInputSchema())', - ], - scalars: undefined, - }, - ], - [ - 'nested input object', - { - textSchema: /* GraphQL */ ` + `); + const scalars = undefined + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function AInputSchema(): z.ZodObject> { + return z.object({ + b: z.lazy(() => BInputSchema()) + }) + } + + export function BInputSchema(): z.ZodObject> { + return z.object({ + c: z.lazy(() => CInputSchema()) + }) + } + + export function CInputSchema(): z.ZodObject> { + return z.object({ + a: z.lazy(() => AInputSchema()) + }) + } + " + `) + }) + + it('nested input object', async () => { + const schema = buildSchema(/* GraphQL */ ` input NestedInput { child: NestedInput childrens: [NestedInput] } - `, - wantContains: [ - 'export function NestedInputSchema(): z.ZodObject>', - 'child: z.lazy(() => NestedInputSchema().nullish()),', - 'childrens: z.array(z.lazy(() => NestedInputSchema().nullable())).nullish()', - ], - scalars: undefined, - }, - ], - [ - 'enum', - { - textSchema: /* GraphQL */ ` + `); + const scalars = undefined + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function NestedInputSchema(): z.ZodObject> { + return z.object({ + child: z.lazy(() => NestedInputSchema().nullish()), + childrens: z.array(z.lazy(() => NestedInputSchema().nullable())).nullish() + }) + } + " + `) + }) + + it('enum', async () => { + const schema = buildSchema(/* GraphQL */ ` enum PageType { PUBLIC BASIC_AUTH @@ -135,19 +185,24 @@ describe('zod', () => { input PageInput { pageType: PageType! } - `, - wantContains: [ - 'export const PageTypeSchema = z.nativeEnum(PageType)', - 'export function PageInputSchema(): z.ZodObject>', - 'pageType: PageTypeSchema', - ], - scalars: undefined, - }, - ], - [ - 'camelcase', - { - textSchema: /* GraphQL */ ` + `); + const scalars = undefined + const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const PageTypeSchema = z.nativeEnum(PageType); + + export function PageInputSchema(): z.ZodObject> { + return z.object({ + pageType: PageTypeSchema + }) + } + " + `) + }) + + it('camelcase', async () => { + const schema = buildSchema(/* GraphQL */ ` input HTTPInput { method: HTTPMethod url: URL! @@ -159,24 +214,22 @@ describe('zod', () => { } scalar URL # unknown scalar, should be any (definedNonNullAnySchema) - `, - wantContains: [ - 'export function HttpInputSchema(): z.ZodObject>', - 'export const HttpMethodSchema = z.nativeEnum(HttpMethod)', - 'method: HttpMethodSchema', - 'url: definedNonNullAnySchema', - ], - scalars: undefined, - }, - ], - ])('%s', async (_, { textSchema, wantContains, scalars }) => { - const schema = buildSchema(textSchema); + `); + const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const HttpMethodSchema = z.nativeEnum(HttpMethod); - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); - }); + export function HttpInputSchema(): z.ZodObject> { + return z.object({ + method: HttpMethodSchema.nullish(), + url: definedNonNullAnySchema + }) + } + " + `) + }) it('with scalars', async () => { const schema = buildSchema(/* GraphQL */ ` @@ -200,8 +253,16 @@ describe('zod', () => { }, {}, ); - expect(result.content).toContain('phrase: z.string()'); - expect(result.content).toContain('times: z.number()'); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SaySchema(): z.ZodObject> { + return z.object({ + phrase: z.string(), + times: z.number() + }) + } + " + `) }); it('with importFrom', async () => { @@ -219,8 +280,21 @@ describe('zod', () => { }, {}, ); - expect(result.prepend).toContain('import { Say } from \'./types\''); - expect(result.content).toContain('phrase: z.string()'); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { z } from 'zod'", + "import { Say } from './types'", + ] + `); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SaySchema(): z.ZodObject> { + return z.object({ + phrase: z.string() + }) + } + " + `) }); it('with importFrom & useTypeImports', async () => { @@ -239,8 +313,21 @@ describe('zod', () => { }, {}, ); - expect(result.prepend).toContain('import type { Say } from \'./types\''); - expect(result.content).toContain('phrase: z.string()'); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { z } from 'zod'", + "import type { Say } from './types'", + ] + `); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SaySchema(): z.ZodObject> { + return z.object({ + phrase: z.string() + }) + } + " + `) }); it('with enumsAsTypes', async () => { @@ -259,7 +346,11 @@ describe('zod', () => { }, {}, ); - expect(result.content).toContain('export const PageTypeSchema = z.enum([\'PUBLIC\', \'BASIC_AUTH\'])'); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const PageTypeSchema = z.enum(['PUBLIC', 'BASIC_AUTH']); + " + `) }); it('with notAllowEmptyString', async () => { @@ -284,16 +375,19 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function PrimitiveInputSchema(): z.ZodObject>', - 'a: z.string().min(1),', - 'b: z.string().min(1),', - 'c: z.boolean(),', - 'd: z.number(),', - 'e: z.number()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function PrimitiveInputSchema(): z.ZodObject> { + return z.object({ + a: z.string().min(1), + b: z.string().min(1), + c: z.boolean(), + d: z.number(), + e: z.number() + }) + } + " + `) }); it('with notAllowEmptyString issue #386', async () => { @@ -318,13 +412,21 @@ describe('zod', () => { }, {}, ); - const wantContain = dedent` - export function InputNestedSchema(): z.ZodObject> { - return z.object({ - field: z.string().min(1) - }) - }`; - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function InputOneSchema(): z.ZodObject> { + return z.object({ + field: z.lazy(() => InputNestedSchema()) + }) + } + + export function InputNestedSchema(): z.ZodObject> { + return z.object({ + field: z.string().min(1) + }) + } + " + `) }); it('with scalarSchemas', async () => { @@ -349,14 +451,17 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function ScalarsInputSchema(): z.ZodObject>', - 'date: z.date(),', - 'email: z.string().email().nullish(),', - 'str: z.string()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function ScalarsInputSchema(): z.ZodObject> { + return z.object({ + date: z.date(), + email: z.string().email().nullish(), + str: z.string() + }) + } + " + `) }); it('with typesPrefix', async () => { @@ -375,8 +480,21 @@ describe('zod', () => { }, {}, ); - expect(result.prepend).toContain('import { ISay } from \'./types\''); - expect(result.content).toContain('export function ISaySchema(): z.ZodObject> {'); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { z } from 'zod'", + "import { ISay } from './types'", + ] + `); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function ISaySchema(): z.ZodObject> { + return z.object({ + phrase: z.string() + }) + } + " + `) }); it('with typesSuffix', async () => { @@ -395,8 +513,21 @@ describe('zod', () => { }, {}, ); - expect(result.prepend).toContain('import { SayI } from \'./types\''); - expect(result.content).toContain('export function SayISchema(): z.ZodObject> {'); + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { z } from 'zod'", + "import { SayI } from './types'", + ] + `); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SayISchema(): z.ZodObject> { + return z.object({ + phrase: z.string() + }) + } + " + `) }); it('with default input values', async () => { @@ -423,14 +554,21 @@ describe('zod', () => { {}, ); - expect(result.content).toContain('export const PageTypeSchema = z.nativeEnum(PageType)'); - expect(result.content).toContain('export function PageInputSchema(): z.ZodObject>'); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const PageTypeSchema = z.nativeEnum(PageType); - expect(result.content).toContain('pageType: PageTypeSchema.default("PUBLIC")'); - expect(result.content).toContain('greeting: z.string().default("Hello").nullish()'); - expect(result.content).toContain('score: z.number().default(100).nullish()'); - expect(result.content).toContain('ratio: z.number().default(0.5).nullish()'); - expect(result.content).toContain('isMember: z.boolean().default(true).nullish()'); + export function PageInputSchema(): z.ZodObject> { + return z.object({ + pageType: PageTypeSchema.default("PUBLIC"), + greeting: z.string().default("Hello").nullish(), + score: z.number().default(100).nullish(), + ratio: z.number().default(0.5).nullish(), + isMember: z.boolean().default(true).nullish() + }) + } + " + `) }); describe('issues #19', () => { @@ -456,12 +594,15 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function UserCreateInputSchema(): z.ZodObject>', - 'profile: z.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000").nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + profile: z.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000").nullish() + }) + } + " + `) }); it('not null field', async () => { @@ -486,12 +627,15 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function UserCreateInputSchema(): z.ZodObject>', - 'profile: z.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000")', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + profile: z.string().min(1, "Please input more than 1").max(5000, "Please input less than 5000") + }) + } + " + `) }); it('list field', async () => { @@ -516,12 +660,15 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function UserCreateInputSchema(): z.ZodObject>', - 'profile: z.array(z.string().nullable()).min(1, "Please input more than 1").max(5000, "Please input less than 5000").nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + profile: z.array(z.string().nullable()).min(1, "Please input more than 1").max(5000, "Please input less than 5000").nullish() + }) + } + " + `) }); }); @@ -549,12 +696,16 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function UserCreateInputSchema(): z.ZodObject>', - 'profile: z.string().max(5000, "Please input less than 5000").min(1),', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + profile: z.string().max(5000, "Please input less than 5000").min(1), + age: z.number() + }) + } + " + `) }); it('without notAllowEmptyString', async () => { @@ -579,12 +730,16 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function UserCreateInputSchema(): z.ZodObject>', - 'profile: z.string().max(5000, "Please input less than 5000"),', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + profile: z.string().max(5000, "Please input less than 5000"), + age: z.number() + }) + } + " + `) }); }); @@ -628,19 +783,25 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function AuthorSchema(): z.ZodObject> {', - '__typename: z.literal(\'Author\').optional(),', - 'books: z.array(BookSchema().nullable()).nullish(),', - 'name: z.string().nullish()', - - 'export function BookSchema(): z.ZodObject> {', - '__typename: z.literal(\'Book\').optional(),', - 'author: AuthorSchema().nullish(),', - 'title: z.string().nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function BookSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Book').optional(), + author: AuthorSchema().nullish(), + title: z.string().nullish() + }) + } + + export function AuthorSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Author').optional(), + books: z.array(BookSchema().nullable()).nullish(), + name: z.string().nullish() + }) + } + " + `) for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) expect(result.content).not.toContain(wantNotContain); @@ -699,28 +860,36 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - // User Create Input - 'export function UserCreateInputSchema(): z.ZodObject> {', - 'name: z.string(),', - 'date: z.date(),', - 'email: z.string().email()', - // Username Update Input - 'export function UsernameUpdateInputSchema(): z.ZodObject> {', - 'updateInputId: z.number(),', - 'updateName: z.string()', - // User - 'export function UserSchema(): z.ZodObject> {', - '__typename: z.literal(\'User\').optional()', - 'id: z.string(),', - 'name: z.string().nullish(),', - 'age: z.number().nullish(),', - 'isMember: z.boolean().nullish(),', - 'email: z.string().email().nullish(),', - 'createdAt: z.date()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + name: z.string(), + date: z.date(), + email: z.string().email() + }) + } + + export function UsernameUpdateInputSchema(): z.ZodObject> { + return z.object({ + updateInputId: z.number(), + updateName: z.string() + }) + } + + export function UserSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('User').optional(), + id: z.string(), + name: z.string().nullish(), + age: z.number().nullish(), + email: z.string().email().nullish(), + isMember: z.boolean().nullish(), + createdAt: z.date() + }) + } + " + `) for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) expect(result.content).not.toContain(wantNotContain); @@ -747,14 +916,27 @@ describe('zod', () => { {}, ); - const wantContains = [ - // Shape Schema - 'export function ShapeSchema() {', - 'return z.union([CircleSchema(), SquareSchema()])', - '}', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SquareSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Square').optional(), + size: z.number().nullish() + }) + } + + export function CircleSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Circle').optional(), + radius: z.number().nullish() + }) + } + + export function ShapeSchema() { + return z.union([CircleSchema(), SquareSchema()]) + } + " + `) }); it('generate union types with single element', async () => { @@ -782,13 +964,34 @@ describe('zod', () => { {}, ); - const wantContains = [ - 'export function GeometrySchema(): z.ZodObject> {', - '__typename: z.literal(\'Geometry\').optional(),', - 'shape: ShapeSchema().nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function SquareSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Square').optional(), + size: z.number().nullish() + }) + } + + export function CircleSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Circle').optional(), + radius: z.number().nullish() + }) + } + + export function ShapeSchema() { + return z.union([CircleSchema(), SquareSchema()]) + } + + export function GeometrySchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Geometry').optional(), + shape: ShapeSchema().nullish() + }) + } + " + `) }); it('correctly reference generated union types', async () => { @@ -809,14 +1012,20 @@ describe('zod', () => { {}, ); - const wantContains = [ - // Shape Schema - 'export function ShapeSchema() {', - 'return CircleSchema()', - '}', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function CircleSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Circle').optional(), + radius: z.number().nullish() + }) + } + + export function ShapeSchema() { + return CircleSchema() + } + " + `) }); it('generate enum union types', async () => { @@ -844,13 +1053,17 @@ describe('zod', () => { {}, ); - const wantContains = [ - 'export function AnyTypeSchema() {', - 'return z.union([PageTypeSchema, MethodTypeSchema])', - '}', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const PageTypeSchema = z.nativeEnum(PageType); + + export const MethodTypeSchema = z.nativeEnum(MethodType); + + export function AnyTypeSchema() { + return z.union([PageTypeSchema, MethodTypeSchema]) + } + " + `) }); it('generate union types with single element, export as const', async () => { @@ -879,13 +1092,26 @@ describe('zod', () => { {}, ); - const wantContains = [ - 'export const GeometrySchema: z.ZodObject> = z.object({', - '__typename: z.literal(\'Geometry\').optional(),', - 'shape: ShapeSchema.nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const CircleSchema: z.ZodObject> = z.object({ + __typename: z.literal('Circle').optional(), + radius: z.number().nullish() + }); + + export const SquareSchema: z.ZodObject> = z.object({ + __typename: z.literal('Square').optional(), + size: z.number().nullish() + }); + + export const ShapeSchema = z.union([CircleSchema, SquareSchema]); + + export const GeometrySchema: z.ZodObject> = z.object({ + __typename: z.literal('Geometry').optional(), + shape: ShapeSchema.nullish() + }); + " + `) }); it('with object arguments', async () => { @@ -907,17 +1133,26 @@ describe('zod', () => { }, {}, ); - const wantContain = dedent` - export function MyTypeFooArgsSchema(): z.ZodObject> { - return z.object({ - a: z.string().nullish(), - b: z.number(), - c: z.boolean().nullish(), - d: z.number(), - e: z.string().nullish() - }) - }`; - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function MyTypeSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('MyType').optional(), + foo: z.string().nullish() + }) + } + + export function MyTypeFooArgsSchema(): z.ZodObject> { + return z.object({ + a: z.string().nullish(), + b: z.number(), + c: z.boolean().nullish(), + d: z.number(), + e: z.string().nullish() + }) + } + " + `) }); describe('with InterfaceType', () => { @@ -955,13 +1190,16 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function BookSchema(): z.ZodObject> {', - 'title: z.string().nullish()', - ]; + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function BookSchema(): z.ZodObject> { + return z.object({ + title: z.string().nullish() + }) + } + " + `) const wantNotContains = ['__typename: z.literal(\'Book\')']; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); for (const wantNotContain of wantNotContains) expect(result.content).not.toContain(wantNotContain); @@ -973,7 +1211,7 @@ describe('zod', () => { author: Author title: String } - + interface Author { books: [Book] name: String @@ -988,17 +1226,23 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - 'export function AuthorSchema(): z.ZodObject> {', - 'books: z.array(BookSchema().nullable()).nullish(),', - 'name: z.string().nullish()', - - 'export function BookSchema(): z.ZodObject> {', - 'author: AuthorSchema().nullish(),', - 'title: z.string().nullish()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function BookSchema(): z.ZodObject> { + return z.object({ + author: AuthorSchema().nullish(), + title: z.string().nullish() + }) + } + + export function AuthorSchema(): z.ZodObject> { + return z.object({ + books: z.array(BookSchema().nullable()).nullish(), + name: z.string().nullish() + }) + } + " + `) }); it('generate object type contains interface type', async () => { @@ -1007,19 +1251,19 @@ describe('zod', () => { title: String! author: Author! } - + type Textbook implements Book { title: String! author: Author! courses: [String!]! } - + type ColoringBook implements Book { title: String! author: Author! colors: [String!]! } - + type Author { books: [Book!] name: String @@ -1034,53 +1278,42 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - [ - 'export function BookSchema(): z.ZodObject> {', - 'return z.object({', - 'title: z.string(),', - 'author: AuthorSchema()', - '})', - '}', - ], - - [ - 'export function TextbookSchema(): z.ZodObject> {', - 'return z.object({', - '__typename: z.literal(\'Textbook\').optional(),', - 'title: z.string(),', - 'author: AuthorSchema(),', - 'courses: z.array(z.string())', - '})', - '}', - ], - - [ - 'export function ColoringBookSchema(): z.ZodObject> {', - 'return z.object({', - '__typename: z.literal(\'ColoringBook\').optional(),', - 'title: z.string(),', - 'author: AuthorSchema(),', - 'colors: z.array(z.string())', - '})', - '}', - ], - - [ - 'export function AuthorSchema(): z.ZodObject> {', - 'return z.object({', - '__typename: z.literal(\'Author\').optional()', - 'books: z.array(BookSchema()).nullish()', - 'name: z.string().nullish()', - '})', - '}', - ], - ]; - - for (const wantContain of wantContains) { - for (const wantContainLine of wantContain) - expect(result.content).toContain(wantContainLine); - } + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function BookSchema(): z.ZodObject> { + return z.object({ + title: z.string(), + author: AuthorSchema() + }) + } + + export function TextbookSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Textbook').optional(), + title: z.string(), + author: AuthorSchema(), + courses: z.array(z.string()) + }) + } + + export function ColoringBookSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('ColoringBook').optional(), + title: z.string(), + author: AuthorSchema(), + colors: z.array(z.string()) + }) + } + + export function AuthorSchema(): z.ZodObject> { + return z.object({ + __typename: z.literal('Author').optional(), + books: z.array(BookSchema()).nullish(), + name: z.string().nullish() + }) + } + " + `) }); }); }); @@ -1108,14 +1341,16 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - // User Create Input - 'export function UserCreateInputSchema(): z.ZodObject> {', - 'name: z.string().regex(/^Sir/),', - 'age: z.number().min(0).max(100)', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export function UserCreateInputSchema(): z.ZodObject> { + return z.object({ + name: z.string().regex(/^Sir/), + age: z.number().min(0).max(100) + }) + } + " + `) }); it('exports as const instead of func', async () => { @@ -1133,7 +1368,13 @@ describe('zod', () => { }, {}, ); - expect(result.content).toContain('export const SaySchema: z.ZodObject> = z.object({'); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const SaySchema: z.ZodObject> = z.object({ + phrase: z.string() + }); + " + `) }); it('generate both input & type, export as const', async () => { @@ -1177,24 +1418,25 @@ describe('zod', () => { }, {}, ); - const wantContains = [ - // User Create Input - 'export const UserCreateInputSchema: z.ZodObject> = z.object({', - 'name: z.string(),', - 'date: z.date(),', - 'email: z.string().email()', - // User - 'export const UserSchema: z.ZodObject> = z.object({', - '__typename: z.literal(\'User\').optional()', - 'id: z.string(),', - 'name: z.string().nullish(),', - 'age: z.number().nullish(),', - 'isMember: z.boolean().nullish(),', - 'email: z.string().email().nullish(),', - 'createdAt: z.date()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const UserCreateInputSchema: z.ZodObject> = z.object({ + name: z.string(), + date: z.date(), + email: z.string().email() + }); + + export const UserSchema: z.ZodObject> = z.object({ + __typename: z.literal('User').optional(), + id: z.string(), + name: z.string().nullish(), + age: z.number().nullish(), + email: z.string().email().nullish(), + isMember: z.boolean().nullish(), + createdAt: z.date() + }); + " + `) for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) expect(result.content).not.toContain(wantNotContain); @@ -1228,12 +1470,16 @@ describe('zod', () => { }, {}, ); - const wantContain = dedent` - export function QueryInputSchema(): z.ZodObject> { - return z.object({ - _dummy: TestSchema.nullish() - }) - }`; - expect(result.content).toContain(wantContain); + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const TestSchema = z.nativeEnum(Test); + + export function QueryInputSchema(): z.ZodObject> { + return z.object({ + _dummy: TestSchema.nullish() + }) + } + " + `) }); });