graphile-test builds on top of pgsql-test to provide robust GraphQL testing utilities for PostGraphile-based projects.
It provides a seamless setup for isolated, seeded, role-aware Postgres databases and injects GraphQL helpers for snapshot testing, role context, and mutation/query assertions.
Note: This is a bare-bones package with no defaults or settings applied. For a batteries-included version with all Constructive plugins pre-configured, use @constructive-io/graphql-test instead.
- 🔁 Per-test rollback via savepoints for isolation
- 🔐 RLS-aware context injection (
setContext) - 🧪 GraphQL integration testing with
query()and snapshot support - 📦 Seed support for
.sql, JSON, CSV, Constructive, or Sqitch - 📊 Introspection query snapshotting
- 🔧 Raw SQL fallback via
pg.client.query
npm install graphile-testimport { getConnections, seed } from 'graphile-test';
let db, query, teardown;
beforeAll(async () => {
({ db, query, teardown } = await getConnections({
schemas: ['app_public'],
authRole: 'authenticated'
}, [
seed.sqlfile(['../sql/test.sql', '../sql/grants.sql'])
]));
});
beforeEach(() => db.beforeEach());
afterEach(() => db.afterEach());
afterAll(() => teardown());
it('runs a GraphQL mutation', async () => {
const res = await query(`mutation { ... }`, { input: { ... } });
expect(res.data.createUser.username).toBe('alice');
});Returns an object with:
query(gqlString, variables?)– A GraphQL executor function with positional argumentsdb,pg–PgTestClientinstancesteardown()– Clean up temp DBs
Basic Usage:
const result = await query(`mutation { ... }`, { input: { ... } });
expect(result.data.createUser.username).toBe('alice');Supports:
query,any,one, etc. (viapg-promise-like helpers)beforeEach()/afterEach()– for savepoint transaction handlingsetContext({...})– sets Postgres config (e.g.,role,myapp.user_id)
See full PgTestClient API docs: pgsql-test → PgTestClient API Overview
const res = await query(`mutation { ... }`, { input: { ... } });
expect(snapshot(res.data)).toMatchSnapshot();db.setContext({ role: 'anonymous' });
const res = await query(`query { ... }`);
expect(res.errors[0].message).toMatch(/permission denied/);interface CreateUserVariables {
input: {
user: {
username: string;
};
};
}
interface CreateUserResult {
createUser: {
user: {
id: number;
username: string;
};
};
}
const res = await query<CreateUserResult, CreateUserVariables>(`
mutation CreateUser($input: CreateUserInput!) {
createUser(input: $input) {
user {
id
username
}
}
}
`,
{ input: { user: { username: 'alice' } } }
);
expect(res.data?.createUser.user.username).toBe('alice');For specific testing needs, additional connection functions are available:
getConnectionsUnwrapped()– Automatically throws on GraphQL errors, returns data directly
getConnectionsWithLogging()– Logs all queries and responsesgetConnectionsWithTiming()– Times query execution
getConnectionsObject()– Usesquery({ query: "...", variables: {} })syntaxgetConnectionsObjectUnwrapped()– Object-based with automatic error throwing
Unwrapped Example (cleaner assertions):
import { getConnectionsUnwrapped } from 'graphile-test';
const { query } = await getConnectionsUnwrapped(config);
// Throws automatically on GraphQL errors, returns data directly
const result = await query(`mutation { ... }`, { input: { ... } });
expect(result.createUser.username).toBe('alice'); // No .data needed!Object-Based Example:
import { getConnectionsObject } from 'graphile-test';
const { query } = await getConnectionsObject(config);
const result = await query({
query: `mutation { ... }`,
variables: { input: { ... } }
});
expect(result.data.createUser.username).toBe('alice');graphile-test wraps and extends pgsql-test with GraphQL helpers like query() and introspection snapshot tools. You can drop into raw SQL testing anytime via pg.client.query() (superuser) or db.client.query() (RLS user).
- Use
db.setContext({ role, user_id })to simulate authentication. - Always wrap tests with
beforeEach/afterEach. - Use
snapshot()to track GraphQL result changes. - Use
useRoot: trueto test schema visibility without RLS. - Start with
getConnections()for most use cases. - Consider
getConnectionsUnwrapped()for cleaner test assertions.
The graphile-test/utils module provides utilities for sanitizing query results for snapshot testing. These helpers replace dynamic values (IDs, UUIDs, dates, hashes) with stable placeholders, making snapshots deterministic.
import { snapshot } from 'graphile-test/utils';
const res = await query(`query { allUsers { nodes { id name createdAt } } }`);
expect(snapshot(res.data)).toMatchSnapshot();See pgsql-test Snapshot Utilities for the full API reference.
# requires a local Postgres available (defaults to postgres/password@localhost:5432)
pnpm --filter graphile-test test