Testing
The suite is designed so that you never need a running database to test schema generation, introspection, or component rendering.
Schema introspection tests
Section titled “Schema introspection tests”Use buildSchemaFromDrizzle to build a full GraphQL schema from your Drizzle table definitions. No database connection or .env file is required — the function creates stub resolvers internally.
import { printSchema } from 'graphql'import { describe, expect, test } from 'bun:test'import { buildSchemaFromDrizzle } from '@graphql-suite/schema'import * as schema from './db'
const config = { mutations: true, limitRelationDepth: 2, suffixes: { list: 'List', single: '' },}const { schema: gqlSchema, entities } = buildSchemaFromDrizzle(schema, config)
describe('GraphQL schema', () => { test('generates article list query type', () => { const queryType = gqlSchema.getQueryType() expect(queryType?.getFields().articleList).toBeDefined() })
test('generates insert mutation', () => { const mutationType = gqlSchema.getMutationType() expect(mutationType?.getFields().insertIntoArticle).toBeDefined() })
test('SDL contains expected types', () => { const sdl = printSchema(gqlSchema) expect(sdl).toContain('type ArticleSelectItem') })})E2E tests with mock DB
Section titled “E2E tests with mock DB”For testing actual GraphQL query execution, create a mock database that returns seed data, build a real schema from it, and run queries against it using a GraphQL server like graphql-yoga:
import { describe, expect, test } from 'bun:test'import { buildSchema } from '@graphql-suite/schema'import { createYoga } from 'graphql-yoga'
function createSeededMockDb(drizzleSchema, tables, tableNamesMap) { const seedData = { article: [ { id: '1', title: 'First' }, { id: '2', title: 'Second' }, { id: '3', title: 'Third' }, ], }
const query = Object.fromEntries( Object.keys(tables).map((name) => [ name, { findMany: () => Promise.resolve(seedData[name] ?? []), findFirst: () => Promise.resolve(seedData[name]?.[0] ?? null), }, ]), )
return { _: { fullSchema: drizzleSchema, schema: tables, tableNamesMap }, query, select: () => ({ from: () => ({ where: () => ({}) }) }), }}
const config = { mutations: true, suffixes: { list: 'List', single: '' },}
// biome-ignore lint/suspicious/noExplicitAny: mock db for testingconst mockDb = createSeededMockDb(schema, tables, tableNamesMap) as anyconst { schema: gqlSchema } = buildSchema(mockDb, config)const yoga = createYoga({ schema: gqlSchema })
test('fetches articles', async () => { const res = await yoga.fetch( new Request('http://test/graphql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: '{ articleList { title } }' }), }), ) const json = await res.json() expect(json.data.articleList).toHaveLength(3)})Asserting the query a resolver builds
Section titled “Asserting the query a resolver builds”The resolvers prune columns and derive nested relation arguments from the GraphQL selection, so a
mock that records what it was asked for tests that logic directly — no graphql-yoga needed, just
graphql():
import { describe, expect, test } from 'bun:test'import { buildSchema } from '@graphql-suite/schema'import { createTableRelationsHelpers, extractTablesRelationalConfig } from 'drizzle-orm'import { graphql } from 'graphql'
import * as drizzleSchema from './db/schema'
const { tables, tableNamesMap } = extractTablesRelationalConfig( drizzleSchema, createTableRelationsHelpers,)
type FindConfig = { columns?: Record<string, true> with?: Record<string, FindConfig> limit?: number offset?: number}
let calls: { table: string; config: FindConfig }[] = []
const query = Object.fromEntries( Object.keys(tables).map((name) => [ name, { findMany: (config: FindConfig = {}) => { calls.push({ table: name, config }) return Promise.resolve([]) }, }, ]),)
// biome-ignore lint/suspicious/noExplicitAny: mock db for testingconst mockDb = { _: { fullSchema: drizzleSchema, schema: tables, tableNamesMap }, query } as anyconst { schema } = buildSchema(mockDb)
test('selects only the requested columns', async () => { calls = [] await graphql({ schema, source: '{ article { id title } }' })
expect(Object.keys(calls[0]?.config.columns ?? {})).toEqual(['id', 'title'])})
test('carries relation arguments into the nested query', async () => { calls = [] await graphql({ schema, source: '{ article { id comments(limit: 3) { id } } }' })
expect(calls[0]?.config.with?.comments?.limit).toBe(3)})The same tree is available in your own resolvers via
parseResolveInfo.
Component tests with linkedom
Section titled “Component tests with linkedom”For testing React components that use the query hooks, set up a DOM environment with linkedom and mock the GraphQL client.
import { describe, expect, mock, test } from 'bun:test'import { parseHTML } from 'linkedom'import { act, createRoot } from 'react-dom/client'import { renderToString } from 'react-dom/server'import { createElement } from 'react'import { QueryClient, QueryClientProvider } from '@tanstack/react-query'import { GraphQLProvider } from '@graphql-suite/query'
// Set up DOM globalsconst { document, window } = parseHTML('<!DOCTYPE html><html><body></body></html>')globalThis.document = documentglobalThis.window = window
// Create a mock clientconst mockClient = { entity: mock(() => ({ query: mock(() => Promise.resolve([])), querySingle: mock(() => Promise.resolve(null)), count: mock(() => Promise.resolve(0)), })), execute: mock(() => Promise.resolve({})),}
function renderWithProviders(component) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } }, })
return renderToString( createElement( QueryClientProvider, { client: queryClient }, createElement(GraphQLProvider, { client: mockClient }, component), ), )}