diff --git a/codegen.yml b/codegen.yml index 02311409..f3170225 100644 --- a/codegen.yml +++ b/codegen.yml @@ -13,7 +13,6 @@ generates: schema: yup importFrom: ../types withObjectType: true - withInterfaceType: true directives: required: msg: required @@ -50,7 +49,6 @@ generates: schema: zod importFrom: ../types withObjectType: true - withInterfaceType: true directives: # Write directives like # @@ -74,7 +72,6 @@ generates: schema: myzod importFrom: ../types withObjectType: true - withInterfaceType: true directives: constraint: minLength: min diff --git a/src/config.ts b/src/config.ts index a91c1652..6475f9fc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -194,24 +194,6 @@ export interface ValidationSchemaPluginConfig extends TypeScriptPluginConfig { * ``` */ withObjectType?: boolean - /** - * @description Generates validation schema with GraphQL type interfaces. - * - * @exampleMarkdown - * ```yml - * generates: - * path/to/types.ts: - * plugins: - * - typescript - * path/to/schemas.ts: - * plugins: - * - graphql-codegen-validation-schema - * config: - * schema: yup - * withInterfaceType: true - * ``` - */ - withInterfaceType?: boolean /** * @description Specify validation schema export type. * @default function diff --git a/src/myzod/index.ts b/src/myzod/index.ts index 319f41ad..ca44c10f 100644 --- a/src/myzod/index.ts +++ b/src/myzod/index.ts @@ -63,7 +63,7 @@ export class MyZodSchemaVisitor extends BaseSchemaVisitor { get InterfaceTypeDefinition() { return { - leave: InterfaceTypeDefinitionBuilder(this.config.withInterfaceType, (node: InterfaceTypeDefinitionNode) => { + leave: InterfaceTypeDefinitionBuilder(this.config.withObjectType, (node: InterfaceTypeDefinitionNode) => { const visitor = this.createVisitor('output'); const name = visitor.convertName(node.name.value); this.importTypes.push(name); diff --git a/src/yup/index.ts b/src/yup/index.ts index c10710b7..5998af5d 100644 --- a/src/yup/index.ts +++ b/src/yup/index.ts @@ -70,7 +70,7 @@ export class YupSchemaVisitor extends BaseSchemaVisitor { get InterfaceTypeDefinition() { return { - leave: InterfaceTypeDefinitionBuilder(this.config.withInterfaceType, (node: InterfaceTypeDefinitionNode) => { + leave: InterfaceTypeDefinitionBuilder(this.config.withObjectType, (node: InterfaceTypeDefinitionNode) => { const visitor = this.createVisitor('output'); const name = visitor.convertName(node.name.value); this.importTypes.push(name); diff --git a/src/zod/index.ts b/src/zod/index.ts index 85ecb09d..e5bd802f 100644 --- a/src/zod/index.ts +++ b/src/zod/index.ts @@ -79,7 +79,7 @@ export class ZodSchemaVisitor extends BaseSchemaVisitor { get InterfaceTypeDefinition() { return { - leave: InterfaceTypeDefinitionBuilder(this.config.withInterfaceType, (node: InterfaceTypeDefinitionNode) => { + leave: InterfaceTypeDefinitionBuilder(this.config.withObjectType, (node: InterfaceTypeDefinitionNode) => { const visitor = this.createVisitor('output'); const name = visitor.convertName(node.name.value); this.importTypes.push(name); diff --git a/tests/myzod.spec.ts b/tests/myzod.spec.ts index ac822e0e..1a53f782 100644 --- a/tests/myzod.spec.ts +++ b/tests/myzod.spec.ts @@ -486,168 +486,6 @@ describe('myzod', () => { }); }); - describe('with withInterfaceType', () => { - it('not generate if withObjectType false', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface User { - id: ID! - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'myzod', - }, - {}, - ); - expect(result.content).not.toContain('export function UserSchema(): myzod.Type {'); - }); - - it('generate if withInterfaceType true', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - title: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'myzod', - withInterfaceType: true, - }, - {}, - ); - const wantContains = [ - 'export function BookSchema(): myzod.Type {', - 'title: myzod.string().optional().nullable()', - ]; - const wantNotContains = ['__typename: myzod.literal(\'Book\')']; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); - - for (const wantNotContain of wantNotContains) - expect(result.content).not.toContain(wantNotContain); - }); - - it('generate interface type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - author: Author - title: String - } - - interface Author { - books: [Book] - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'myzod', - withInterfaceType: true, - }, - {}, - ); - const wantContains = [ - 'export function AuthorSchema(): myzod.Type {', - 'books: myzod.array(BookSchema().nullable()).optional().nullable(),', - 'name: myzod.string().optional().nullable()', - - 'export function BookSchema(): myzod.Type {', - 'author: AuthorSchema().optional().nullable(),', - 'title: myzod.string().optional().nullable()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); - }); - it('generate object type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - 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 - } - `); - const result = await plugin( - schema, - [], - { - schema: 'myzod', - withInterfaceType: true, - withObjectType: true, - }, - {}, - ); - const wantContains = [ - [ - 'export function BookSchema(): myzod.Type {', - 'return myzod.object({', - 'title: myzod.string(),', - 'author: AuthorSchema()', - '})', - '}', - ], - - [ - 'export function TextbookSchema(): myzod.Type {', - 'return myzod.object({', - '__typename: myzod.literal(\'Textbook\').optional(),', - 'title: myzod.string(),', - 'author: AuthorSchema(),', - 'courses: myzod.array(myzod.string())', - '})', - '}', - ], - - [ - 'export function ColoringBookSchema(): myzod.Type {', - 'return myzod.object({', - '__typename: myzod.literal(\'ColoringBook\').optional(),', - 'title: myzod.string(),', - 'author: AuthorSchema(),', - 'colors: myzod.array(myzod.string())', - '})', - '}', - ], - - [ - 'export function AuthorSchema(): myzod.Type {', - 'return myzod.object({', - '__typename: myzod.literal(\'Author\').optional()', - 'books: myzod.array(BookSchema()).optional().nullable()', - 'name: myzod.string().optional().nullable()', - '})', - '}', - ], - ]; - for (const wantContain of wantContains) { - for (const wantContainLine of wantContain) - expect(result.content).toContain(wantContainLine); - } - }); - }); - describe('with withObjectType', () => { it('not generate if withObjectType false', async () => { const schema = buildSchema(/* GraphQL */ ` @@ -982,6 +820,167 @@ describe('myzod', () => { }`; expect(result.content).toContain(wantContain); }); + + describe('with InterfaceType', () => { + it('not generate if withObjectType false', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface User { + id: ID! + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'myzod', + }, + {}, + ); + expect(result.content).not.toContain('export function UserSchema(): myzod.Type {'); + }); + + it('generate if withObjectType true', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + title: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'myzod', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + 'export function BookSchema(): myzod.Type {', + 'title: myzod.string().optional().nullable()', + ]; + const wantNotContains = ['__typename: myzod.literal(\'Book\')']; + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + + for (const wantNotContain of wantNotContains) + expect(result.content).not.toContain(wantNotContain); + }); + + it('generate interface type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + author: Author + title: String + } + + interface Author { + books: [Book] + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'myzod', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + 'export function AuthorSchema(): myzod.Type {', + 'books: myzod.array(BookSchema().nullable()).optional().nullable(),', + 'name: myzod.string().optional().nullable()', + + 'export function BookSchema(): myzod.Type {', + 'author: AuthorSchema().optional().nullable(),', + 'title: myzod.string().optional().nullable()', + ]; + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }); + it('generate object type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + 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 + } + `); + const result = await plugin( + schema, + [], + { + schema: 'myzod', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + [ + 'export function BookSchema(): myzod.Type {', + 'return myzod.object({', + 'title: myzod.string(),', + 'author: AuthorSchema()', + '})', + '}', + ], + + [ + 'export function TextbookSchema(): myzod.Type {', + 'return myzod.object({', + '__typename: myzod.literal(\'Textbook\').optional(),', + 'title: myzod.string(),', + 'author: AuthorSchema(),', + 'courses: myzod.array(myzod.string())', + '})', + '}', + ], + + [ + 'export function ColoringBookSchema(): myzod.Type {', + 'return myzod.object({', + '__typename: myzod.literal(\'ColoringBook\').optional(),', + 'title: myzod.string(),', + 'author: AuthorSchema(),', + 'colors: myzod.array(myzod.string())', + '})', + '}', + ], + + [ + 'export function AuthorSchema(): myzod.Type {', + 'return myzod.object({', + '__typename: myzod.literal(\'Author\').optional()', + 'books: myzod.array(BookSchema()).optional().nullable()', + 'name: myzod.string().optional().nullable()', + '})', + '}', + ], + ]; + for (const wantContain of wantContains) { + for (const wantContainLine of wantContain) + expect(result.content).toContain(wantContainLine); + } + }); + }); }); it('properly generates custom directive values', async () => { diff --git a/tests/yup.spec.ts b/tests/yup.spec.ts index 466492b3..2593fc03 100644 --- a/tests/yup.spec.ts +++ b/tests/yup.spec.ts @@ -393,181 +393,6 @@ describe('yup', () => { expect(result.content).toContain('export function SayISchema(): yup.ObjectSchema {'); }); - describe('with interfaceType', () => { - it('not generate if withInterfaceType false', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface User { - id: ID! - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'yup', - }, - {}, - ); - expect(result.content).not.toContain('export function UserSchema(): yup.ObjectSchema {'); - }); - - it('generate if withInterfaceType true', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - title: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'yup', - withInterfaceType: true, - }, - {}, - ); - const wantContains = [ - 'export function BookSchema(): yup.ObjectSchema {', - 'title: yup.string().defined().nullable().optional()', - ]; - const wantNotContains = ['__typename: yup.string<\'Book\'>().optional()']; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); - - for (const wantNotContain of wantNotContains) - expect(result.content).not.toContain(wantNotContain); - }); - - it('generate interface type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - author: Author - title: String - } - - interface Book2 { - author: Author! - title: String! - } - - interface Author { - books: [Book] - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'yup', - withInterfaceType: true, - }, - {}, - ); - const wantContains = [ - 'export function AuthorSchema(): yup.ObjectSchema {', - 'books: yup.array(BookSchema().nullable()).defined().nullable().optional(),', - 'name: yup.string().defined().nullable().optional()', - - 'export function BookSchema(): yup.ObjectSchema {', - 'author: AuthorSchema().nullable().optional(),', - 'title: yup.string().defined().nullable().optional()', - - 'export function Book2Schema(): yup.ObjectSchema {', - 'author: AuthorSchema().nonNullable(),', - 'title: yup.string().defined().nonNullable()', - ]; - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); - - for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) - expect(result.content).not.toContain(wantNotContain); - }); - it('generate object type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - 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 - } - `); - const result = await plugin( - schema, - [], - { - schema: 'yup', - withInterfaceType: true, - withObjectType: true, - }, - {}, - ); - const wantContains = [ - [ - 'export function BookSchema(): yup.ObjectSchema {', - 'return yup.object({', - 'title: yup.string().defined().nonNullable(),', - 'author: AuthorSchema().nonNullable()', - '})', - '}', - ], - - [ - 'export function TextbookSchema(): yup.ObjectSchema {', - 'return yup.object({', - '__typename: yup.string<\'Textbook\'>().optional(),', - 'title: yup.string().defined().nonNullable(),', - 'author: AuthorSchema().nonNullable(),', - 'courses: yup.array(yup.string().defined().nonNullable()).defined()', - '})', - '}', - ], - - [ - 'export function ColoringBookSchema(): yup.ObjectSchema {', - 'return yup.object({', - '__typename: yup.string<\'ColoringBook\'>().optional(),', - 'title: yup.string().defined().nonNullable(),', - 'author: AuthorSchema().nonNullable(),', - 'colors: yup.array(yup.string().defined().nonNullable()).defined()', - '})', - '}', - ], - - [ - 'export function AuthorSchema(): yup.ObjectSchema {', - 'return yup.object({', - '__typename: yup.string<\'Author\'>().optional(),', - 'books: yup.array(BookSchema().nonNullable()).defined().nullable().optional(),', - 'name: yup.string().defined().nullable().optional()', - '})', - '}', - ], - ]; - - for (const wantContain of wantContains) { - for (const wantContainLine of wantContain) - expect(result.content).toContain(wantContainLine); - } - }); - }); - describe('with withObjectType', () => { it('not generate if withObjectType false', async () => { const schema = buildSchema(/* GraphQL */ ` @@ -913,6 +738,181 @@ describe('yup', () => { }`; expect(result.content).toContain(wantContain); }); + + describe('with InterfaceType', () => { + it('not generate if withObjectType false', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface User { + id: ID! + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'yup', + withObjectType: false, + }, + {}, + ); + expect(result.content).not.toContain('export function UserSchema(): yup.ObjectSchema {'); + }); + + it('generate if withObjectType true', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + title: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'yup', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + 'export function BookSchema(): yup.ObjectSchema {', + 'title: yup.string().defined().nullable().optional()', + ]; + const wantNotContains = ['__typename: yup.string<\'Book\'>().optional()']; + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + + for (const wantNotContain of wantNotContains) + expect(result.content).not.toContain(wantNotContain); + }); + + it('generate interface type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + author: Author + title: String + } + + interface Book2 { + author: Author! + title: String! + } + + interface Author { + books: [Book] + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'yup', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + 'export function AuthorSchema(): yup.ObjectSchema {', + 'books: yup.array(BookSchema().nullable()).defined().nullable().optional(),', + 'name: yup.string().defined().nullable().optional()', + + 'export function BookSchema(): yup.ObjectSchema {', + 'author: AuthorSchema().nullable().optional(),', + 'title: yup.string().defined().nullable().optional()', + + 'export function Book2Schema(): yup.ObjectSchema {', + 'author: AuthorSchema().nonNullable(),', + 'title: yup.string().defined().nonNullable()', + ]; + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + + for (const wantNotContain of ['Query', 'Mutation', 'Subscription']) + expect(result.content).not.toContain(wantNotContain); + }); + it('generate object type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + 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 + } + `); + const result = await plugin( + schema, + [], + { + schema: 'yup', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + [ + 'export function BookSchema(): yup.ObjectSchema {', + 'return yup.object({', + 'title: yup.string().defined().nonNullable(),', + 'author: AuthorSchema().nonNullable()', + '})', + '}', + ], + + [ + 'export function TextbookSchema(): yup.ObjectSchema {', + 'return yup.object({', + '__typename: yup.string<\'Textbook\'>().optional(),', + 'title: yup.string().defined().nonNullable(),', + 'author: AuthorSchema().nonNullable(),', + 'courses: yup.array(yup.string().defined().nonNullable()).defined()', + '})', + '}', + ], + + [ + 'export function ColoringBookSchema(): yup.ObjectSchema {', + 'return yup.object({', + '__typename: yup.string<\'ColoringBook\'>().optional(),', + 'title: yup.string().defined().nonNullable(),', + 'author: AuthorSchema().nonNullable(),', + 'colors: yup.array(yup.string().defined().nonNullable()).defined()', + '})', + '}', + ], + + [ + 'export function AuthorSchema(): yup.ObjectSchema {', + 'return yup.object({', + '__typename: yup.string<\'Author\'>().optional(),', + 'books: yup.array(BookSchema().nonNullable()).defined().nullable().optional(),', + 'name: yup.string().defined().nullable().optional()', + '})', + '}', + ], + ]; + + for (const wantContain of wantContains) { + for (const wantContainLine of wantContain) + expect(result.content).toContain(wantContainLine); + } + }); + }); }); it('properly generates custom directive values', async () => { diff --git a/tests/zod.spec.ts b/tests/zod.spec.ts index 8527a5a5..e297351a 100644 --- a/tests/zod.spec.ts +++ b/tests/zod.spec.ts @@ -588,170 +588,6 @@ describe('zod', () => { }); }); - describe('with withInterfaceType', () => { - it('not generate if withObjectType false', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface User { - id: ID! - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'zod', - }, - {}, - ); - expect(result.content).not.toContain('export function UserSchema(): z.ZodObject>'); - }); - - it('generate if withInterfaceType true', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - title: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'zod', - withInterfaceType: true, - }, - {}, - ); - const wantContains = [ - 'export function BookSchema(): z.ZodObject> {', - '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); - }); - - it('generate interface type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - author: Author - title: String - } - - interface Author { - books: [Book] - name: String - } - `); - const result = await plugin( - schema, - [], - { - schema: 'zod', - withInterfaceType: true, - }, - {}, - ); - 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); - }); - - it('generate object type contains interface type', async () => { - const schema = buildSchema(/* GraphQL */ ` - interface Book { - 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 - } - `); - const result = await plugin( - schema, - [], - { - schema: 'zod', - withInterfaceType: true, - withObjectType: true, - }, - {}, - ); - 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); - } - }); - }); - describe('with withObjectType', () => { it('not generate if withObjectType false', async () => { const schema = buildSchema(/* GraphQL */ ` @@ -1083,6 +919,170 @@ describe('zod', () => { }`; expect(result.content).toContain(wantContain); }); + + describe('with InterfaceType', () => { + it('not generate if withObjectType false', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface User { + id: ID! + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'zod', + withObjectType: false, + }, + {}, + ); + expect(result.content).not.toContain('export function UserSchema(): z.ZodObject>'); + }); + + it('generate if withObjectType true', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + title: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'zod', + withObjectType: true, + }, + {}, + ); + const wantContains = [ + 'export function BookSchema(): z.ZodObject> {', + '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); + }); + + it('generate interface type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + author: Author + title: String + } + + interface Author { + books: [Book] + name: String + } + `); + const result = await plugin( + schema, + [], + { + schema: 'zod', + withObjectType: true, + }, + {}, + ); + 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); + }); + + it('generate object type contains interface type', async () => { + const schema = buildSchema(/* GraphQL */ ` + interface Book { + 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 + } + `); + const result = await plugin( + schema, + [], + { + schema: 'zod', + withObjectType: true, + }, + {}, + ); + 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); + } + }); + }); }); it('properly generates custom directive values', async () => {