diff --git a/packages/plugins/typescript/resolvers/tests/federation.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts similarity index 100% rename from packages/plugins/typescript/resolvers/tests/federation.spec.ts rename to packages/plugins/typescript/resolvers/tests/ts-resolvers.federation.spec.ts diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts new file mode 100644 index 00000000000..af71b4bc6ca --- /dev/null +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.interface.spec.ts @@ -0,0 +1,169 @@ +import { resolversTestingSchema } from '@graphql-codegen/testing'; +import { buildSchema } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Resolvers Plugin - Interfaces', () => { + it('should generate ResolversInterfaceTypes', async () => { + const content = await plugin(resolversTestingSchema, [], {}, { outputFile: 'graphql.ts' }); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversInterfaceTypes<_RefType extends Record> = { + Node: ( SomeNode ); + AnotherNode: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + WithChild: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + WithChildren: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversTypes = { + MyType: ResolverTypeWrapper & { unionChild?: Maybe }>; + String: ResolverTypeWrapper; + Child: ResolverTypeWrapper; + MyOtherType: ResolverTypeWrapper; + ChildUnion: ResolverTypeWrapper['ChildUnion']>; + Query: ResolverTypeWrapper<{}>; + Subscription: ResolverTypeWrapper<{}>; + Node: ResolverTypeWrapper['Node']>; + ID: ResolverTypeWrapper; + SomeNode: ResolverTypeWrapper; + AnotherNode: ResolverTypeWrapper['AnotherNode']>; + WithChild: ResolverTypeWrapper['WithChild']>; + WithChildren: ResolverTypeWrapper['WithChildren']>; + AnotherNodeWithChild: ResolverTypeWrapper & { unionChild?: Maybe, interfaceChild?: Maybe }>; + AnotherNodeWithAll: ResolverTypeWrapper & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }>; + MyUnion: ResolverTypeWrapper['MyUnion']>; + MyScalar: ResolverTypeWrapper; + Int: ResolverTypeWrapper; + Boolean: ResolverTypeWrapper; + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversParentTypes = { + MyType: Omit & { unionChild?: Maybe }; + String: Scalars['String']['output']; + Child: Child; + MyOtherType: MyOtherType; + ChildUnion: ResolversUnionTypes['ChildUnion']; + Query: {}; + Subscription: {}; + Node: ResolversInterfaceTypes['Node']; + ID: Scalars['ID']['output']; + SomeNode: SomeNode; + AnotherNode: ResolversInterfaceTypes['AnotherNode']; + WithChild: ResolversInterfaceTypes['WithChild']; + WithChildren: ResolversInterfaceTypes['WithChildren']; + AnotherNodeWithChild: Omit & { unionChild?: Maybe, interfaceChild?: Maybe }; + AnotherNodeWithAll: Omit & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }; + MyUnion: ResolversUnionTypes['MyUnion']; + MyScalar: Scalars['MyScalar']['output']; + Int: Scalars['Int']['output']; + Boolean: Scalars['Boolean']['output']; + }; + `); + }); + + it('should generate ResolversInterfaceTypes with transformed type names correctly', async () => { + const content = await plugin( + resolversTestingSchema, + [], + { typesPrefix: 'I_', typesSuffix: '_Types' }, + { outputFile: 'graphql.ts' } + ); + + expect(content.content).toBeSimilarStringTo(` + export type I_ResolversInterfaceTypes_Types<_RefType extends Record> = { + Node: ( I_SomeNode_Types ); + AnotherNode: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + WithChild: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + WithChildren: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type I_ResolversTypes_Types = { + MyType: ResolverTypeWrapper & { unionChild?: Maybe }>; + String: ResolverTypeWrapper; + Child: ResolverTypeWrapper; + MyOtherType: ResolverTypeWrapper; + ChildUnion: ResolverTypeWrapper['ChildUnion']>; + Query: ResolverTypeWrapper<{}>; + Subscription: ResolverTypeWrapper<{}>; + Node: ResolverTypeWrapper['Node']>; + ID: ResolverTypeWrapper; + SomeNode: ResolverTypeWrapper; + AnotherNode: ResolverTypeWrapper['AnotherNode']>; + WithChild: ResolverTypeWrapper['WithChild']>; + WithChildren: ResolverTypeWrapper['WithChildren']>; + AnotherNodeWithChild: ResolverTypeWrapper & { unionChild?: Maybe, interfaceChild?: Maybe }>; + AnotherNodeWithAll: ResolverTypeWrapper & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }>; + MyUnion: ResolverTypeWrapper['MyUnion']>; + MyScalar: ResolverTypeWrapper; + Int: ResolverTypeWrapper; + Boolean: ResolverTypeWrapper; + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type I_ResolversParentTypes_Types = { + MyType: Omit & { unionChild?: Maybe }; + String: Scalars['String']['output']; + Child: I_Child_Types; + MyOtherType: I_MyOtherType_Types; + ChildUnion: I_ResolversUnionTypes_Types['ChildUnion']; + Query: {}; + Subscription: {}; + Node: I_ResolversInterfaceTypes_Types['Node']; + ID: Scalars['ID']['output']; + SomeNode: I_SomeNode_Types; + AnotherNode: I_ResolversInterfaceTypes_Types['AnotherNode']; + WithChild: I_ResolversInterfaceTypes_Types['WithChild']; + WithChildren: I_ResolversInterfaceTypes_Types['WithChildren']; + AnotherNodeWithChild: Omit & { unionChild?: Maybe, interfaceChild?: Maybe }; + AnotherNodeWithAll: Omit & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }; + MyUnion: I_ResolversUnionTypes_Types['MyUnion']; + MyScalar: Scalars['MyScalar']['output']; + Int: Scalars['Int']['output']; + Boolean: Scalars['Boolean']['output']; + }; + `); + }); + + it('should NOT generate ResolversInterfaceTypes if there is no Interface', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + fullName: String! + } + `); + const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); + + expect(content.content).not.toBeSimilarStringTo(`export type ResolversInterfaceTypes`); + }); + + it('Should generate valid types even when there are no implementers for an interface', async () => { + const schemaWithNoImplementors = buildSchema(/* GraphQL */ ` + interface Node { + id: ID! + } + + type Query { + node: Node! + } + `); + + const result = await plugin(schemaWithNoImplementors, [], {}, { outputFile: '' }); + + expect(result.content).toBeSimilarStringTo(` + export type NodeResolvers = { + __resolveType: TypeResolveFn; + id?: Resolver; + }; + `); + }); +}); diff --git a/packages/plugins/typescript/resolvers/tests/mapping.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.mapping.spec.ts similarity index 99% rename from packages/plugins/typescript/resolvers/tests/mapping.spec.ts rename to packages/plugins/typescript/resolvers/tests/ts-resolvers.mapping.spec.ts index e96260f2479..0a7ef291458 100644 --- a/packages/plugins/typescript/resolvers/tests/mapping.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.mapping.spec.ts @@ -3,7 +3,7 @@ import { resolversTestingSchema, resolversTestingValidate } from '@graphql-codeg import { buildSchema } from 'graphql'; import { plugin } from '../src/index.js'; -describe('ResolversTypes', () => { +describe('TypeScript Resolvers Plugin - Mapping', () => { it('Should build ResolversTypes object when there are no mappers', async () => { const result = await plugin(resolversTestingSchema, [], {}, { outputFile: '' }); diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.meta.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.meta.spec.ts new file mode 100644 index 00000000000..7bae3a0178f --- /dev/null +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.meta.spec.ts @@ -0,0 +1,119 @@ +import '@graphql-codegen/testing'; +import { plugin } from '../src/index.js'; +import { buildSchema } from 'graphql'; + +describe('TypeScript Resolvers Plugin - Meta', () => { + it('generates meta correctly', async () => { + const result = await plugin( + buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + post(id: ID!): Post + } + + type Mutation { + createUser(name: String!): CreateUserPayload! + } + + interface Node { + id: ID! + } + type Post implements Node { + id: ID! + author: User + } + type User implements Node { + id: ID! + name: String + } + + type CreateUserOk { + user: User! + } + + type CreateUserError { + error: ErrorType! + } + + union CreateUserPayload = CreateUserOk | CreateUserError + + enum ErrorType { + FORBIDDEN_ERROR + INTERNAL_ERROR + } + `), + [], + { + namingConvention: 'change-case-all#snakeCase', + enumValues: { + ErrorType: { + FORBIDDEN_ERROR: '403', + INTERNAL_ERROR: '500', + }, + }, + }, + { outputFile: '' } + ); + + expect(result.content).toBeSimilarStringTo(` + export type resolvers = { + Query?: query_resolvers; + Mutation?: mutation_resolvers; + Node?: node_resolvers; + Post?: post_resolvers; + User?: user_resolvers; + CreateUserOk?: create_user_ok_resolvers; + CreateUserError?: create_user_error_resolvers; + CreateUserPayload?: create_user_payload_resolvers; + ErrorType?: error_type_resolvers; + };`); + expect(result.content).toContain(`export type create_user_error_resolvers`); + expect(result.content).toContain(`export type create_user_ok_resolvers`); + expect(result.content).toContain(`export type create_user_payload_resolvers`); + expect(result.content).toContain(`export type error_type_resolvers`); + expect(result.content).toContain(`export type mutation_resolvers`); + expect(result.content).toContain(`export type node_resolvers`); + expect(result.content).toContain(`export type post_resolvers`); + expect(result.content).toContain(`export type query_resolvers`); + expect(result.content).toContain(`export type user_resolvers`); + + expect(result.meta).toMatchInlineSnapshot(` + Object { + "generatedResolverTypes": Object { + "resolversMap": Object { + "name": "resolvers", + }, + "userDefined": Object { + "CreateUserError": Object { + "name": "create_user_error_resolvers", + }, + "CreateUserOk": Object { + "name": "create_user_ok_resolvers", + }, + "CreateUserPayload": Object { + "name": "create_user_payload_resolvers", + }, + "ErrorType": Object { + "name": "error_type_resolvers", + }, + "Mutation": Object { + "name": "mutation_resolvers", + }, + "Node": Object { + "name": "node_resolvers", + }, + "Post": Object { + "name": "post_resolvers", + }, + "Query": Object { + "name": "query_resolvers", + }, + "User": Object { + "name": "user_resolvers", + }, + }, + }, + } + `); + }); +}); diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts index 2cac594c04b..156a8984d48 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts @@ -1996,241 +1996,6 @@ export type ResolverFn = ( `); }); - it('should generate ResolversUnionTypes', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): UserPayload! - posts: PostsPayload! - } - - type StandardError { - error: String! - } - - type User { - id: ID! - fullName: String! - } - - type UserResult { - result: User - } - - union UserPayload = UserResult | StandardError - - type Post { - author: String - comment: String - } - - type PostsResult { - results: [Post!]! - } - - union PostsPayload = PostsResult | StandardError - `); - const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversUnionTypes<_RefType extends Record> = { - UserPayload: ( UserResult ) | ( StandardError ); - PostsPayload: ( PostsResult ) | ( StandardError ); - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversTypes = { - Query: ResolverTypeWrapper<{}>; - ID: ResolverTypeWrapper; - StandardError: ResolverTypeWrapper; - String: ResolverTypeWrapper; - User: ResolverTypeWrapper; - UserResult: ResolverTypeWrapper; - UserPayload: ResolverTypeWrapper['UserPayload']>; - Post: ResolverTypeWrapper; - PostsResult: ResolverTypeWrapper; - PostsPayload: ResolverTypeWrapper['PostsPayload']>; - Boolean: ResolverTypeWrapper; - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversParentTypes = { - Query: {}; - ID: Scalars['ID']['output']; - StandardError: StandardError; - String: Scalars['String']['output']; - User: User; - UserResult: UserResult; - UserPayload: ResolversUnionTypes['UserPayload']; - Post: Post; - PostsResult: PostsResult; - PostsPayload: ResolversUnionTypes['PostsPayload']; - Boolean: Scalars['Boolean']['output']; - }; - `); - }); - - it('should NOT generate ResolversUnionTypes if there is no Union', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): User - } - - type User { - id: ID! - fullName: String! - } - `); - const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); - - expect(content.content).not.toBeSimilarStringTo(`export type ResolversUnionTypes`); - expect(content.content).not.toBeSimilarStringTo(`export type ResolversUnionParentTypes`); - }); - - it('should generate ResolversInterfaceTypes', async () => { - const content = await plugin(resolversTestingSchema, [], {}, { outputFile: 'graphql.ts' }); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversInterfaceTypes<_RefType extends Record> = { - Node: ( SomeNode ); - AnotherNode: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - WithChild: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - WithChildren: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversTypes = { - MyType: ResolverTypeWrapper & { unionChild?: Maybe }>; - String: ResolverTypeWrapper; - Child: ResolverTypeWrapper; - MyOtherType: ResolverTypeWrapper; - ChildUnion: ResolverTypeWrapper['ChildUnion']>; - Query: ResolverTypeWrapper<{}>; - Subscription: ResolverTypeWrapper<{}>; - Node: ResolverTypeWrapper['Node']>; - ID: ResolverTypeWrapper; - SomeNode: ResolverTypeWrapper; - AnotherNode: ResolverTypeWrapper['AnotherNode']>; - WithChild: ResolverTypeWrapper['WithChild']>; - WithChildren: ResolverTypeWrapper['WithChildren']>; - AnotherNodeWithChild: ResolverTypeWrapper & { unionChild?: Maybe, interfaceChild?: Maybe }>; - AnotherNodeWithAll: ResolverTypeWrapper & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }>; - MyUnion: ResolverTypeWrapper['MyUnion']>; - MyScalar: ResolverTypeWrapper; - Int: ResolverTypeWrapper; - Boolean: ResolverTypeWrapper; - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type ResolversParentTypes = { - MyType: Omit & { unionChild?: Maybe }; - String: Scalars['String']['output']; - Child: Child; - MyOtherType: MyOtherType; - ChildUnion: ResolversUnionTypes['ChildUnion']; - Query: {}; - Subscription: {}; - Node: ResolversInterfaceTypes['Node']; - ID: Scalars['ID']['output']; - SomeNode: SomeNode; - AnotherNode: ResolversInterfaceTypes['AnotherNode']; - WithChild: ResolversInterfaceTypes['WithChild']; - WithChildren: ResolversInterfaceTypes['WithChildren']; - AnotherNodeWithChild: Omit & { unionChild?: Maybe, interfaceChild?: Maybe }; - AnotherNodeWithAll: Omit & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }; - MyUnion: ResolversUnionTypes['MyUnion']; - MyScalar: Scalars['MyScalar']['output']; - Int: Scalars['Int']['output']; - Boolean: Scalars['Boolean']['output']; - }; - `); - }); - - it('should generate ResolversInterfaceTypes with transformed type names correctly', async () => { - const content = await plugin( - resolversTestingSchema, - [], - { typesPrefix: 'I_', typesSuffix: '_Types' }, - { outputFile: 'graphql.ts' } - ); - - expect(content.content).toBeSimilarStringTo(` - export type I_ResolversInterfaceTypes_Types<_RefType extends Record> = { - Node: ( I_SomeNode_Types ); - AnotherNode: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - WithChild: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']> } ) | ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - WithChildren: ( Omit & { unionChild?: Maybe<_RefType['ChildUnion']>, unionChildren: Array<_RefType['ChildUnion']>, interfaceChild?: Maybe<_RefType['Node']>, interfaceChildren: Array<_RefType['Node']> } ); - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type I_ResolversTypes_Types = { - MyType: ResolverTypeWrapper & { unionChild?: Maybe }>; - String: ResolverTypeWrapper; - Child: ResolverTypeWrapper; - MyOtherType: ResolverTypeWrapper; - ChildUnion: ResolverTypeWrapper['ChildUnion']>; - Query: ResolverTypeWrapper<{}>; - Subscription: ResolverTypeWrapper<{}>; - Node: ResolverTypeWrapper['Node']>; - ID: ResolverTypeWrapper; - SomeNode: ResolverTypeWrapper; - AnotherNode: ResolverTypeWrapper['AnotherNode']>; - WithChild: ResolverTypeWrapper['WithChild']>; - WithChildren: ResolverTypeWrapper['WithChildren']>; - AnotherNodeWithChild: ResolverTypeWrapper & { unionChild?: Maybe, interfaceChild?: Maybe }>; - AnotherNodeWithAll: ResolverTypeWrapper & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }>; - MyUnion: ResolverTypeWrapper['MyUnion']>; - MyScalar: ResolverTypeWrapper; - Int: ResolverTypeWrapper; - Boolean: ResolverTypeWrapper; - }; - `); - - expect(content.content).toBeSimilarStringTo(` - export type I_ResolversParentTypes_Types = { - MyType: Omit & { unionChild?: Maybe }; - String: Scalars['String']['output']; - Child: I_Child_Types; - MyOtherType: I_MyOtherType_Types; - ChildUnion: I_ResolversUnionTypes_Types['ChildUnion']; - Query: {}; - Subscription: {}; - Node: I_ResolversInterfaceTypes_Types['Node']; - ID: Scalars['ID']['output']; - SomeNode: I_SomeNode_Types; - AnotherNode: I_ResolversInterfaceTypes_Types['AnotherNode']; - WithChild: I_ResolversInterfaceTypes_Types['WithChild']; - WithChildren: I_ResolversInterfaceTypes_Types['WithChildren']; - AnotherNodeWithChild: Omit & { unionChild?: Maybe, interfaceChild?: Maybe }; - AnotherNodeWithAll: Omit & { unionChild?: Maybe, unionChildren: Array, interfaceChild?: Maybe, interfaceChildren: Array }; - MyUnion: I_ResolversUnionTypes_Types['MyUnion']; - MyScalar: Scalars['MyScalar']['output']; - Int: Scalars['Int']['output']; - Boolean: Scalars['Boolean']['output']; - }; - `); - }); - - it('should NOT generate ResolversInterfaceTypes if there is no Interface', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): User - } - - type User { - id: ID! - fullName: String! - } - `); - const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); - - expect(content.content).not.toBeSimilarStringTo(`export type ResolversInterfaceTypes`); - }); - it('should use correct value when rootValueType mapped as default', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Subscription { @@ -2418,26 +2183,6 @@ export type ResolverFn = ( validateTs(content); }); - it('Should generate valid types even when there are no implementers for an interface', async () => { - const schemaWithNoImplementors = buildSchema(/* GraphQL */ ` - interface Node { - id: ID! - } - - type Query { - node: Node! - } - `); - - const result = await plugin(schemaWithNoImplementors, [], {}, { outputFile: '' }); - - expect(result.content).toBeSimilarStringTo(` - export type NodeResolvers = { - __resolveType: TypeResolveFn; - id?: Resolver; - }; - `); - }); it('should use MaybePromise in ResolverTypeWrapper', async () => { const testSchema = buildSchema(/* GraphQL */ ` type MySubscription { @@ -3039,118 +2784,4 @@ export type ResolverFn = ( }; `); }); - - it('generates meta correctly', async () => { - const result = await plugin( - buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): User - post(id: ID!): Post - } - - type Mutation { - createUser(name: String!): CreateUserPayload! - } - - interface Node { - id: ID! - } - type Post implements Node { - id: ID! - author: User - } - type User implements Node { - id: ID! - name: String - } - - type CreateUserOk { - user: User! - } - - type CreateUserError { - error: ErrorType! - } - - union CreateUserPayload = CreateUserOk | CreateUserError - - enum ErrorType { - FORBIDDEN_ERROR - INTERNAL_ERROR - } - `), - [], - { - namingConvention: 'change-case-all#snakeCase', - enumValues: { - ErrorType: { - FORBIDDEN_ERROR: '403', - INTERNAL_ERROR: '500', - }, - }, - }, - { outputFile: '' } - ); - - expect(result.content).toBeSimilarStringTo(` - export type resolvers = { - Query?: query_resolvers; - Mutation?: mutation_resolvers; - Node?: node_resolvers; - Post?: post_resolvers; - User?: user_resolvers; - CreateUserOk?: create_user_ok_resolvers; - CreateUserError?: create_user_error_resolvers; - CreateUserPayload?: create_user_payload_resolvers; - ErrorType?: error_type_resolvers; - };`); - expect(result.content).toContain(`export type create_user_error_resolvers`); - expect(result.content).toContain(`export type create_user_ok_resolvers`); - expect(result.content).toContain(`export type create_user_payload_resolvers`); - expect(result.content).toContain(`export type error_type_resolvers`); - expect(result.content).toContain(`export type mutation_resolvers`); - expect(result.content).toContain(`export type node_resolvers`); - expect(result.content).toContain(`export type post_resolvers`); - expect(result.content).toContain(`export type query_resolvers`); - expect(result.content).toContain(`export type user_resolvers`); - - expect(result.meta).toMatchInlineSnapshot(` - Object { - "generatedResolverTypes": Object { - "resolversMap": Object { - "name": "resolvers", - }, - "userDefined": Object { - "CreateUserError": Object { - "name": "create_user_error_resolvers", - }, - "CreateUserOk": Object { - "name": "create_user_ok_resolvers", - }, - "CreateUserPayload": Object { - "name": "create_user_payload_resolvers", - }, - "ErrorType": Object { - "name": "error_type_resolvers", - }, - "Mutation": Object { - "name": "mutation_resolvers", - }, - "Node": Object { - "name": "node_resolvers", - }, - "Post": Object { - "name": "post_resolvers", - }, - "Query": Object { - "name": "query_resolvers", - }, - "User": Object { - "name": "user_resolvers", - }, - }, - }, - } - `); - }); }); diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts new file mode 100644 index 00000000000..4df11c5f4f0 --- /dev/null +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.union.spec.ts @@ -0,0 +1,97 @@ +import '@graphql-codegen/testing'; +import { buildSchema } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Resolvers Plugin - Union', () => { + it('should generate ResolversUnionTypes', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): UserPayload! + posts: PostsPayload! + } + + type StandardError { + error: String! + } + + type User { + id: ID! + fullName: String! + } + + type UserResult { + result: User + } + + union UserPayload = UserResult | StandardError + + type Post { + author: String + comment: String + } + + type PostsResult { + results: [Post!]! + } + + union PostsPayload = PostsResult | StandardError + `); + const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversUnionTypes<_RefType extends Record> = { + UserPayload: ( UserResult ) | ( StandardError ); + PostsPayload: ( PostsResult ) | ( StandardError ); + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversTypes = { + Query: ResolverTypeWrapper<{}>; + ID: ResolverTypeWrapper; + StandardError: ResolverTypeWrapper; + String: ResolverTypeWrapper; + User: ResolverTypeWrapper; + UserResult: ResolverTypeWrapper; + UserPayload: ResolverTypeWrapper['UserPayload']>; + Post: ResolverTypeWrapper; + PostsResult: ResolverTypeWrapper; + PostsPayload: ResolverTypeWrapper['PostsPayload']>; + Boolean: ResolverTypeWrapper; + }; + `); + + expect(content.content).toBeSimilarStringTo(` + export type ResolversParentTypes = { + Query: {}; + ID: Scalars['ID']['output']; + StandardError: StandardError; + String: Scalars['String']['output']; + User: User; + UserResult: UserResult; + UserPayload: ResolversUnionTypes['UserPayload']; + Post: Post; + PostsResult: PostsResult; + PostsPayload: ResolversUnionTypes['PostsPayload']; + Boolean: Scalars['Boolean']['output']; + }; + `); + }); + + it('should NOT generate ResolversUnionTypes if there is no Union', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + fullName: String! + } + `); + const content = await plugin(testSchema, [], {}, { outputFile: 'graphql.ts' }); + + expect(content.content).not.toBeSimilarStringTo(`export type ResolversUnionTypes`); + expect(content.content).not.toBeSimilarStringTo(`export type ResolversUnionParentTypes`); + }); +});