From 31264ab727496914175f4098b05f0b3cc9f2dbc7 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 29 Sep 2021 15:59:01 +0300 Subject: [PATCH] integrationTests/ts: split tests into separate files --- .../ts/TypedQueryDocumentNode-test.ts | 72 +++++++++ integrationTests/ts/basic-test.ts | 31 ++++ integrationTests/ts/extensions-test.ts | 62 ++++++++ integrationTests/ts/index.ts | 145 ------------------ 4 files changed, 165 insertions(+), 145 deletions(-) create mode 100644 integrationTests/ts/TypedQueryDocumentNode-test.ts create mode 100644 integrationTests/ts/basic-test.ts create mode 100644 integrationTests/ts/extensions-test.ts delete mode 100644 integrationTests/ts/index.ts diff --git a/integrationTests/ts/TypedQueryDocumentNode-test.ts b/integrationTests/ts/TypedQueryDocumentNode-test.ts new file mode 100644 index 0000000000..89044efbfe --- /dev/null +++ b/integrationTests/ts/TypedQueryDocumentNode-test.ts @@ -0,0 +1,72 @@ +import type { ExecutionResult } from 'graphql/execution'; +import type { TypedQueryDocumentNode } from 'graphql/utilities'; + +import { parse } from 'graphql/language'; +import { execute } from 'graphql/execution'; +import { buildSchema } from 'graphql/utilities'; + +const schema = buildSchema(` + type Query { + test: String + } +`); + +// Tests for TS specific TypedQueryDocumentNode type +const queryDocument = parse('{ test }'); + +type ResponseData = { test: string }; +const typedQueryDocument = queryDocument as TypedQueryDocumentNode< + ResponseData, + {} +>; + +// Supports conversion to DocumentNode +execute({ schema, document: typedQueryDocument }); + +function wrappedExecute(document: TypedQueryDocumentNode) { + return execute({ schema, document }) as ExecutionResult; +} + +const response = wrappedExecute(typedQueryDocument); +const responseData: ResponseData | undefined | null = response.data; + +declare function runQueryA( + q: TypedQueryDocumentNode<{ output: string }, { input: string | null }>, +): void; + +// valid +declare const optionalInputRequiredOutput: TypedQueryDocumentNode< + { output: string }, + { input: string | null } +>; +runQueryA(optionalInputRequiredOutput); + +declare function runQueryB( + q: TypedQueryDocumentNode<{ output: string | null }, { input: string }>, +): void; + +// still valid: We still accept {output: string} as a valid result. +// We're now passing in {input: string} which is still assignable to {input: string | null} +runQueryB(optionalInputRequiredOutput); + +// valid: we now accept {output: null} as a valid Result +declare const optionalInputOptionalOutput: TypedQueryDocumentNode< + { output: string | null }, + { input: string | null } +>; +runQueryB(optionalInputOptionalOutput); + +// valid: we now only pass {input: string} to the query +declare const requiredInputRequiredOutput: TypedQueryDocumentNode< + { output: string }, + { input: string } +>; +runQueryB(requiredInputRequiredOutput); + +// valid: we now accept {output: null} as a valid Result AND +// we now only pass {input: string} to the query +declare const requiredInputOptionalOutput: TypedQueryDocumentNode< + { output: null }, + { input: string } +>; +runQueryB(requiredInputOptionalOutput); diff --git a/integrationTests/ts/basic-test.ts b/integrationTests/ts/basic-test.ts new file mode 100644 index 0000000000..76b92a0c0a --- /dev/null +++ b/integrationTests/ts/basic-test.ts @@ -0,0 +1,31 @@ +import type { ExecutionResult } from 'graphql/execution'; + +import { graphqlSync } from 'graphql'; +import { GraphQLString, GraphQLSchema, GraphQLObjectType } from 'graphql/type'; + +const queryType: GraphQLObjectType = new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + sayHi: { + type: GraphQLString, + args: { + who: { type: GraphQLString }, + }, + resolve(_root, args) { + return 'Hello ' + (args.who ?? 'World'); + }, + }, + }), +}); + +const schema: GraphQLSchema = new GraphQLSchema({ query: queryType }); + +const result: ExecutionResult = graphqlSync({ + schema, + source: ` + query helloWho($who: String){ + test(who: $who) + } + `, + variableValues: { who: 'Dolly' }, +}); diff --git a/integrationTests/ts/extensions-test.ts b/integrationTests/ts/extensions-test.ts new file mode 100644 index 0000000000..bd3857e8b3 --- /dev/null +++ b/integrationTests/ts/extensions-test.ts @@ -0,0 +1,62 @@ +import { GraphQLString, GraphQLObjectType } from 'graphql/type'; + +interface SomeExtension { + number: number; + string: string; +} + +const example: SomeExtension = { + number: 42, + string: 'Meaning of life', +}; + +declare module 'graphql' { + interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { + someObjectExtension?: SomeExtension; + } + + interface GraphQLFieldExtensions< + _TSource, + _TContext, + _TArgs = { [argName: string]: any }, + > { + someFieldExtension?: SomeExtension; + } + + interface GraphQLArgumentExtensions { + someArgumentExtension?: SomeExtension; + } +} + +const queryType: GraphQLObjectType = new GraphQLObjectType({ + name: 'Query', + fields: () => ({ + sayHi: { + type: GraphQLString, + args: { + who: { + type: GraphQLString, + extensions: { + someArgumentExtension: example, + }, + }, + }, + resolve: (_root, args) => 'Hello ' + (args.who || 'World'), + extensions: { + someFieldExtension: example, + }, + }, + }), + extensions: { + someObjectExtension: example, + }, +}); + +function checkExtensionTypes(_test: SomeExtension | null | undefined) {} + +checkExtensionTypes(queryType.extensions.someObjectExtension); + +const sayHiField = queryType.getFields().sayHi; +checkExtensionTypes(sayHiField.extensions.someFieldExtension); + +checkExtensionTypes(sayHiField.args[0].extensions.someArgumentExtension); diff --git a/integrationTests/ts/index.ts b/integrationTests/ts/index.ts deleted file mode 100644 index ccc378ab77..0000000000 --- a/integrationTests/ts/index.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { parse } from 'graphql/language'; -import { GraphQLString, GraphQLSchema, GraphQLObjectType } from 'graphql/type'; -import { ExecutionResult, execute } from 'graphql/execution'; -import { TypedQueryDocumentNode, graphqlSync } from 'graphql'; - -interface SomeExtension { - number: number; - string: string; -} - -const example: SomeExtension = { - number: 42, - string: 'Meaning of life', -}; - -declare module 'graphql' { - interface GraphQLObjectTypeExtensions<_TSource = any, _TContext = any> { - someObjectExtension?: SomeExtension; - } - - interface GraphQLFieldExtensions< - _TSource, - _TContext, - _TArgs = { [argName: string]: any }, - > { - someFieldExtension?: SomeExtension; - } - - interface GraphQLArgumentExtensions { - someArgumentExtension?: SomeExtension; - } -} - -const queryType: GraphQLObjectType = new GraphQLObjectType({ - name: 'Query', - fields: () => ({ - sayHi: { - type: GraphQLString, - args: { - who: { - type: GraphQLString, - extensions: { - someArgumentExtension: example, - }, - }, - }, - resolve: (_root, args) => 'Hello ' + (args.who || 'World'), - extensions: { - someFieldExtension: example, - }, - }, - }), - extensions: { - someObjectExtension: example, - }, -}); - -const schema: GraphQLSchema = new GraphQLSchema({ - query: queryType, -}); - -function checkExtensionTypes(_test: SomeExtension | null | undefined) {} - -checkExtensionTypes(queryType.extensions.someObjectExtension); - -const sayHiField = queryType.getFields().sayHi; -checkExtensionTypes(sayHiField.extensions.someFieldExtension); - -checkExtensionTypes(sayHiField.args[0].extensions.someArgumentExtension); - -const result: ExecutionResult = graphqlSync({ - schema, - source: ` - query helloWho($who: String){ - test(who: $who) - } - `, - variableValues: { who: 'Dolly' }, -}); - -// Tests for TS specific TypedQueryDocumentNode type -const queryDocument = parse(` - query helloWho($who: String){ - test(who: $who) - } -`); - -type ResponseData = { test: string }; -const typedQueryDocument = queryDocument as TypedQueryDocumentNode< - ResponseData, - {} ->; - -// Supports conversion to DocumentNode -execute({ schema, document: typedQueryDocument }); - -function wrappedExecute(document: TypedQueryDocumentNode) { - return execute({ schema, document }) as ExecutionResult; -} - -const { data } = wrappedExecute(typedQueryDocument); -if (data != null) { - const typedData: ResponseData = data; -} - -declare function runQueryA( - q: TypedQueryDocumentNode<{ output: string }, { input: string | null }>, -): void; - -// valid -declare const optionalInputRequiredOutput: TypedQueryDocumentNode< - { output: string }, - { input: string | null } ->; -runQueryA(optionalInputRequiredOutput); - -declare function runQueryB( - q: TypedQueryDocumentNode<{ output: string | null }, { input: string }>, -): void; - -// still valid: We still accept {output: string} as a valid result. -// We're now passing in {input: string} which is still assignable to {input: string | null} -runQueryB(optionalInputRequiredOutput); - -// valid: we now accept {output: null} as a valid Result -declare const optionalInputOptionalOutput: TypedQueryDocumentNode< - { output: string | null }, - { input: string | null } ->; -runQueryB(optionalInputOptionalOutput); - -// valid: we now only pass {input: string} to the query -declare const requiredInputRequiredOutput: TypedQueryDocumentNode< - { output: string }, - { input: string } ->; -runQueryB(requiredInputRequiredOutput); - -// valid: we now accept {output: null} as a valid Result AND -// we now only pass {input: string} to the query -declare const requiredInputOptionalOutput: TypedQueryDocumentNode< - { output: null }, - { input: string } ->; -runQueryB(requiredInputOptionalOutput);