| name | constructive-testing |
| description | All PostgreSQL and database testing frameworks — pgsql-test (RLS, seeding, snapshots, JWT context, scenario setup), drizzle-orm-test (type-safe Drizzle testing), supabase-test (Supabase RLS testing), drizzle-orm (schema patterns), and pgsql-parser testing. Use when writing database tests, testing RLS policies, seeding test data, or testing with any Constructive test framework. |
| compatibility | pgsql-test, drizzle-orm-test, supabase-test, Jest/Vitest, PostgreSQL |
| metadata | {"author":"constructive-io","version":"2.0.0"} |
Constructive Testing
All database testing frameworks for Constructive. Each framework builds on pgsql-test underneath — they all create isolated test databases with proper teardown.
When to Apply
Use this skill when:
- Writing PostgreSQL integration tests
- Testing RLS policies, permissions, multi-tenant security
- Seeding test data (fixtures, JSON, SQL, CSV)
- Testing with Drizzle ORM or Supabase
- Working in the pgsql-parser repository
- Choosing which test framework to use
Which Framework to Use
| Scenario | Framework | Reference |
|---|
| Raw SQL, RLS policies, database functions | pgsql-test | pgsql-test.md |
| PostGraphile schema, basic GraphQL queries | graphile-test | (part of constructive monorepo) |
| GraphQL with Constructive plugins (search, pgvector, etc.) | @constructive-io/graphql-test | (part of constructive monorepo) |
| HTTP endpoints, auth headers, middleware | @constructive-io/graphql-server-test | (part of constructive monorepo) |
| Type-safe Drizzle ORM tests | drizzle-orm-test | drizzle-orm-test.md |
| Supabase applications, auth.users | supabase-test | supabase-test.md |
| pgsql-parser repo specifically | pgsql-parser workflow | pgsql-parser-testing.md |
Quick Start (pgsql-test)
import { getConnections } from 'pgsql-test';
let db, teardown;
beforeAll(async () => ({ db, teardown } = await getConnections()));
afterAll(() => teardown());
beforeEach(() => db.beforeEach());
afterEach(() => db.afterEach());
test('example', async () => {
db.setContext({ role: 'authenticated', 'jwt.claims.user_id': '123' });
const result = await db.query('SELECT current_user_id()');
expect(result.rows[0].current_user_id).toBe('123');
});
The Testing Framework Hierarchy
Choose the highest-level framework that fits your test scenario:
┌─────────────────────────────────────────────────────┐
│ @constructive-io/graphql-server-test │ HTTP-level
│ SuperTest against real Express + PostGraphile │ (full stack)
├─────────────────────────────────────────────────────┤
│ @constructive-io/graphql-test │ GraphQL + Constructive
│ GraphQL queries with all Constructive plugins │ plugins loaded
├─────────────────────────────────────────────────────┤
│ graphile-test │ GraphQL schema-level
│ GraphQL queries against PostGraphile schema │ (no HTTP)
├─────────────────────────────────────────────────────┤
│ pgsql-test │ SQL-level
│ Raw SQL queries, RLS, seeding, snapshots │ (database only)
└─────────────────────────────────────────────────────┘
Critical Rules
- Always include
beforeEach/afterEach hooks — savepoint-based isolation prevents test state leakage
- Never create
new pg.Pool() or new pg.Client() in tests — use getConnections()
- Never manually create/drop databases — the framework handles this
- Never skip hooks — tests will leak state
Reference Guide
Core Test Framework (pgsql-test)
Additional Frameworks
| Reference | Topic | Consult When |
|---|
| drizzle-orm-test.md | Drizzle ORM testing | Type-safe database tests with Drizzle |
| drizzle-orm.md | Drizzle ORM schema patterns | Schema design, query building with Drizzle |
| supabase-test.md | Supabase testing | Testing Supabase apps, auth.users, anon/authenticated roles |
| pgsql-parser-testing.md | pgsql-parser repo testing | SQL parser/deparser tests, round-trip validation |
Cross-References
pgpm — Database migrations (deploy before testing)
constructive — Platform core, environment configuration