UNPKG

graphql-typed-client

Version:

A tool that generates a strongly typed client library for any GraphQL endpoint. The client allows writing GraphQL queries as plain JS objects (with type safety, awesome code completion experience, custom scalar type mapping, type guards and more)

165 lines (143 loc) 3.88 kB
import { GraphQLNamedType } from 'graphql' import { toClientSchema } from '../../testHelpers/render' import { RenderContext } from '../common/RenderContext' import { Type } from './renderTypeMap' import { objectType } from './objectType' import { scalarType } from './scalarType' import { unionType } from './unionType' interface Renderer { (type: GraphQLNamedType, ctx: RenderContext): Type } const testCase = async (schemaGql: string, renderer: Renderer, cases: { [type: string]: Type }, output = false) => { const schema = await toClientSchema(schemaGql) const ctx = new RenderContext(schema) for (const t in cases) { const type = schema.getType(t) const expected = cases[t] if (!type) { throw new Error(`type ${t} is not defined in the schema`) } if (output) { console.log(JSON.stringify(renderer(type, ctx), null, 2)) } else { expect(renderer(type, ctx)).toEqual(expected) } } if (output) throw new Error('test case did not run') } test('scalarType', () => testCase( /* GraphQL */ ` enum Enum { some other } scalar Scalar type Query { scalar: String customScalar: Scalar enum: Enum } `, <Renderer>scalarType, { String: { name: 'String' }, Scalar: { name: 'Scalar' }, Enum: { name: 'Enum' }, }, )) test('objectType', () => testCase( /* GraphQL */ ` interface Interface { some: String } type ImplementorA implements Interface { some: String } type ImplementorB implements Interface { some: String } type Object { scalar: Int object: Object interface: Interface optionalArgScalar(arg: Int): Int optionalArgObject(arg: Int): Object optionalArgInterface(arg: Int): Interface nestedArg(a: [[[Int]]], b: [[[Int!]!]!]!): Boolean } type ObjectWithoutScalar { object: Object interface: Interface } type Query { _: Boolean } `, <Renderer>objectType, { Object: { name: 'Object', fields: { scalar: { type: 'Int' }, object: { type: 'Object' }, interface: { type: 'Interface' }, optionalArgScalar: { type: 'Int', args: { arg: ['Int', 'Int'] } }, optionalArgObject: { type: 'Object', args: { arg: ['Int', 'Int'] } }, optionalArgInterface: { type: 'Interface', args: { arg: ['Int', 'Int'] } }, nestedArg: { type: 'Boolean', args: { a: ['[[[Int]]]', 'Int'], b: ['[[[Int!]!]!]!', 'Int'] } }, __typename: { type: 'String' }, }, scalar: ['scalar', 'optionalArgScalar', 'nestedArg'], }, Interface: { name: 'Interface', fields: { some: { type: 'String' }, on_ImplementorA: { type: 'ImplementorA' }, on_ImplementorB: { type: 'ImplementorB' }, __typename: { type: 'String' }, }, scalar: ['some'], }, ObjectWithoutScalar: { name: 'ObjectWithoutScalar', fields: { __typename: { type: 'String' }, interface: { type: 'Interface' }, object: { type: 'Object' }, }, }, }, )) test('unionType', () => testCase( /* GraphQL */ ` type Some { field: Int } type Other { field: Int } type Another { field: Int } union Union = Some | Other | Another type Query { _: Boolean } `, <Renderer>unionType, { Union: { name: 'Union', fields: { on_Some: { type: 'Some' }, on_Other: { type: 'Other' }, on_Another: { type: 'Another' }, __typename: { type: 'String' }, }, }, }, ))