From 668c47e9e0bc61d257da86b598311acf7714cb09 Mon Sep 17 00:00:00 2001 From: MH4GF Date: Sun, 26 May 2024 08:45:46 +0900 Subject: [PATCH 1/3] refactor: decompose it.each To facilitate unit testing. --- tests/zod.spec.ts | 284 ++++++++++++++++++++++++---------------------- 1 file changed, 151 insertions(+), 133 deletions(-) diff --git a/tests/zod.spec.ts b/tests/zod.spec.ts index e297351a..7c3ac643 100644 --- a/tests/zod.spec.ts +++ b/tests/zod.spec.ts @@ -4,63 +4,68 @@ import { dedent } from 'ts-dedent'; import { plugin } from '../src/index'; 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).toContain('import { z } from \'zod\''); + + const wantContains = [ + 'export function PrimitiveInputSchema(): z.ZodObject>', + 'a: z.string()', + 'b: z.string()', + 'c: z.boolean()', + 'd: z.number()', + 'e: z.number()', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + 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(result.prepend).toContain('import { z } from \'zod\''); + + const 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(),', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + it("array", async () => { + const schema = buildSchema(/* GraphQL */ ` input ArrayInput { a: [String] b: [String!] @@ -69,23 +74,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(result.prepend).toContain('import { z } from \'zod\''); + + const 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()))', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + it("ref input object", async () => { + const schema = buildSchema(/* GraphQL */ ` input AInput { b: BInput! } @@ -95,39 +104,47 @@ 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(result.prepend).toContain('import { z } from \'zod\''); + + const 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())', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + 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(result.prepend).toContain('import { z } from \'zod\''); + + const wantContains = [ + 'export function NestedInputSchema(): z.ZodObject>', + 'child: z.lazy(() => NestedInputSchema().nullish()),', + 'childrens: z.array(z.lazy(() => NestedInputSchema().nullable())).nullish()', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + it('enum', async () => { + const schema = buildSchema(/* GraphQL */ ` enum PageType { PUBLIC BASIC_AUTH @@ -135,19 +152,23 @@ 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(result.prepend).toContain('import { z } from \'zod\''); + + const wantContains = [ + 'export const PageTypeSchema = z.nativeEnum(PageType)', + 'export function PageInputSchema(): z.ZodObject>', + 'pageType: PageTypeSchema', + ] + + for (const wantContain of wantContains) + expect(result.content).toContain(wantContain); + }) + + it('camelcase', async () => { + const schema = buildSchema(/* GraphQL */ ` input HTTPInput { method: HTTPMethod url: URL! @@ -159,24 +180,21 @@ 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\''); + const wantContains = [ + 'export function HttpInputSchema(): z.ZodObject>', + 'export const HttpMethodSchema = z.nativeEnum(HttpMethod)', + 'method: HttpMethodSchema', + 'url: definedNonNullAnySchema', + ] + for (const wantContain of wantContains) expect(result.content).toContain(wantContain); - }); + }) it('with scalars', async () => { const schema = buildSchema(/* GraphQL */ ` @@ -973,7 +991,7 @@ describe('zod', () => { author: Author title: String } - + interface Author { books: [Book] name: String @@ -1007,19 +1025,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 From b820268a2e636f1dcbbea54c5107e203d416a200 Mon Sep 17 00:00:00 2001 From: MH4GF Date: Sun, 26 May 2024 09:10:32 +0900 Subject: [PATCH 2/3] refactor: Switch `wantContains` to `toMatchInlineSnapshot` --- tests/zod.spec.ts | 902 +++++++++++++++++++++++++++++----------------- 1 file changed, 565 insertions(+), 337 deletions(-) diff --git a/tests/zod.spec.ts b/tests/zod.spec.ts index 7c3ac643..c034d6a6 100644 --- a/tests/zod.spec.ts +++ b/tests/zod.spec.ts @@ -3,6 +3,24 @@ 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("non-null and defined", async () => { const schema = buildSchema(/* GraphQL */ ` @@ -18,19 +36,25 @@ describe('zod', () => { ID: 'string', } const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const wantContains = [ - 'export function PrimitiveInputSchema(): z.ZodObject>', - 'a: z.string()', - 'b: z.string()', - 'c: z.boolean()', - 'd: z.number()', - 'e: z.number()', - ] - - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + 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 () => { @@ -48,20 +72,21 @@ describe('zod', () => { ID: 'string', } const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const 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(),', - ] - - 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().nullish(), + b: z.string().nullish(), + c: z.boolean().nullish(), + d: z.number().nullish(), + e: z.number().nullish(), + z: z.string() + }) + } + " + `) }) it("array", async () => { @@ -77,20 +102,20 @@ describe('zod', () => { `); const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const 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()))', - ] - - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + 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 () => { @@ -107,19 +132,27 @@ describe('zod', () => { `); const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const 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())', - ] - - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + 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 () => { @@ -131,16 +164,16 @@ describe('zod', () => { `); const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const wantContains = [ - 'export function NestedInputSchema(): z.ZodObject>', - 'child: z.lazy(() => NestedInputSchema().nullish()),', - 'childrens: z.array(z.lazy(() => NestedInputSchema().nullable())).nullish()', - ] - - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + 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 () => { @@ -155,16 +188,17 @@ describe('zod', () => { `); const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const wantContains = [ - 'export const PageTypeSchema = z.nativeEnum(PageType)', - 'export function PageInputSchema(): z.ZodObject>', - 'pageType: PageTypeSchema', - ] + expect(removedInitialEmitValue(result.content)).toMatchInlineSnapshot(` + " + export const PageTypeSchema = z.nativeEnum(PageType); - for (const wantContain of wantContains) - expect(result.content).toContain(wantContain); + export function PageInputSchema(): z.ZodObject> { + return z.object({ + pageType: PageTypeSchema + }) + } + " + `) }) it('camelcase', async () => { @@ -183,17 +217,18 @@ describe('zod', () => { `); const scalars = undefined const result = await plugin(schema, [], { schema: 'zod', scalars }, {}); - expect(result.prepend).toContain('import { z } from \'zod\''); - - const wantContains = [ - 'export function HttpInputSchema(): z.ZodObject>', - 'export const HttpMethodSchema = z.nativeEnum(HttpMethod)', - 'method: HttpMethodSchema', - 'url: definedNonNullAnySchema', - ] + 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 () => { @@ -218,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 () => { @@ -237,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 () => { @@ -257,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 () => { @@ -277,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 () => { @@ -302,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 () => { @@ -336,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 () => { @@ -367,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 () => { @@ -393,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 () => { @@ -413,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 () => { @@ -441,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', () => { @@ -474,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 () => { @@ -504,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 () => { @@ -534,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() + }) + } + " + `) }); }); @@ -567,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 () => { @@ -597,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() + }) + } + " + `) }); }); @@ -646,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); @@ -717,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); @@ -765,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 () => { @@ -800,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 () => { @@ -827,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 () => { @@ -862,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 () => { @@ -897,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 () => { @@ -925,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', () => { @@ -973,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); @@ -1006,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 () => { @@ -1052,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() + }) + } + " + `) }); }); }); @@ -1126,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 () => { @@ -1151,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 () => { @@ -1195,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); @@ -1246,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() + }) + } + " + `) }); }); From bb63d90ed5d622362ba80c9b19da7605f5c1ae35 Mon Sep 17 00:00:00 2001 From: MH4GF Date: Mon, 10 Jun 2024 22:59:02 +0900 Subject: [PATCH 3/3] fix: fix format --- tests/zod.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/zod.spec.ts b/tests/zod.spec.ts index c034d6a6..75b93d1a 100644 --- a/tests/zod.spec.ts +++ b/tests/zod.spec.ts @@ -22,7 +22,7 @@ function removedInitialEmitValue(content: string) { } describe('zod', () => { - it("non-null and defined", async () => { + it('non-null and defined', async () => { const schema = buildSchema(/* GraphQL */ ` input PrimitiveInput { a: ID! @@ -57,7 +57,7 @@ describe('zod', () => { `); }) - it("nullish", async () => { + it('nullish', async () => { const schema = buildSchema(/* GraphQL */ ` input PrimitiveInput { a: ID @@ -89,7 +89,7 @@ describe('zod', () => { `) }) - it("array", async () => { + it('array', async () => { const schema = buildSchema(/* GraphQL */ ` input ArrayInput { a: [String] @@ -118,7 +118,7 @@ describe('zod', () => { `) }) - it("ref input object", async () => { + it('ref input object', async () => { const schema = buildSchema(/* GraphQL */ ` input AInput { b: BInput!