GraphQL Yoga v3 documentation (superseded by v5): GraphQL Yoga makes it easy to test your GraphQL API. It has built-in support for HTTP injection. You can use any testing framework of your choice.
GraphQL Yoga makes it easy to test your GraphQL API. It has built-in support for HTTP injection. You
can use any testing framework of your choice.
You can use the fetch method on your yoga instance for calling the yoga instance as if you were
doing an HTTP request.
Test Utility
Writing parsers for the Subscription or Incremental Delivery (@defer/@stream) protocol is
annoying and cumbersome. Instead you can use the buildHTTPExecutor utility function from
@graphql-tools/executor-http.
import { parse } from 'graphql'import { createSchema, createYoga } from 'graphql-yoga'import { buildHTTPExecutor } from '@graphql-tools/executor-http'const schema = createSchema({ typeDefs: /* GraphQL */ ` type Query { greetings: String! } `, resolvers: { Query: { greetings: () => 'Hello World!' } }})function assertSingleValue<TValue extends object>( value: TValue | AsyncIterable<TValue>): asserts value is TValue { if (Symbol.asyncIterator in value) { throw new Error('Expected single value') }}const executor = buildHTTPExecutor({ fetch: yoga.fetch})const result = await executor({ document: parse(/* GraphQL */ ` query { greetings } `)})assertSingleValue(result)console.assert( result.data?.greetings === 'Hello World!', `Expected 'Hello World!' but got ${executionResult.data.greetings}`)
Subscription Operations
Subscription Operations
import { parse } from 'graphql'import { createSchema, createYoga, Repeater } from 'graphql-yoga'import { buildHTTPExecutor } from '@graphql-tools/executor-http'const schema = createSchema({ typeDefs: /* GraphQL */ ` type Query { greetings: String! } type Subscription { counter: Int! } `, resolvers: { Subscription: { counter: { subscribe: () => new Repeater((push, end) => { let i = 0 const interval = setInterval(() => { push({ counter: i++ }) }, 100) end.then(() => clearInterval(interval)) }) } } }})function assertStreamValue<TValue extends object>( value: TValue | AsyncIterable<TValue>): asserts value is AsyncIterable<TValue> { if (Symbol.asyncIterator in value) { return } throw new Error('Expected single value')}const executor = buildHTTPExecutor({ fetch: yoga.fetch})const result1 = await executor({ document: parse(/* GraphQL */ ` subscription { counter } `)})const result2 = await executor({ document: parse(/* GraphQL */ ` subscription { counter } `)})assertStreamValue(result1)assertStreamValue(result2)let iterationCounter = 0for await (const value of result1) { if (iterationCounter === 0) { console.assert(value.data?.counter === 1, `Expected 1 but got ${value.data?.counter}`) iterationCounter++ } else if (iterationCounter === 1) { console.assert(value.data?.counter === 1, `Expected 2 but got ${value.data?.counter}`) break } else { throw new Error('Expected only two iterations') }}// the server will terminate the iteration after yielding 2 values, for this subscription resolver definition// on the other hand, for most use cases where we are listening to an indefinitely long stream, we trigger cleanup from the client-side as follows:// here we demonstrate listening to one value:const result2It = result2[Symbol.asyncIterator]()const itResult = await result2It.next()console.assert(itResult.value.data?.counter === 1)// after listening to the value, we cleanup by calling return(), if presentawait roomUpdatesIterator.return?.()
TypeScript safe Test Suits with GraphQL Code Generator
The GraphQL Code Generator allows you to generate TypeScript types for your GraphQL operations
(queries, mutations and subscriptions), leading to a better developer experience when writing tests.
You can simply pass the documents from GraphQL Code Generator to the executor for a fully typed
experience.
TypeScript safe usage of executor
import { buildHTTPExecutor } from '@graphql-tools/executor-http'import { graphql } from './gql'import { yoga } from './yoga'const HelloWorldQuery = graphql(/* GraphQL */ ` query HelloWorld { hello }`)const executor = buildHTTPExecutor({ fetch: yoga.fetch})const result = await executor({ document: HelloWorldQuery})// this is now a type-safe when being accessed// result.data?.hello