UNPKG

pgsql-test

Version:

pgsql-test offers isolated, role-aware, and rollback-friendly PostgreSQL environments for integration tests — giving developers realistic test coverage without external state pollution

106 lines (105 loc) 3 kB
import { Client } from 'pg'; export class PgTestClient { config; client; ctxStmts = ''; _ended = false; connectPromise = null; constructor(config, opts = {}) { this.config = config; this.client = new Client({ host: this.config.host, port: this.config.port, database: this.config.database, user: this.config.user, password: this.config.password }); if (!opts.deferConnect) { this.connectPromise = this.client.connect(); if (opts.trackConnect) opts.trackConnect(this.connectPromise); } } async ensureConnected() { if (this.connectPromise) { try { await this.connectPromise; } catch { } } } async close() { if (!this._ended) { this._ended = true; await this.ensureConnected(); this.client.end(); } } async begin() { await this.client.query('BEGIN;'); } async savepoint(name = 'lqlsavepoint') { await this.client.query(`SAVEPOINT "${name}";`); } async rollback(name = 'lqlsavepoint') { await this.client.query(`ROLLBACK TO SAVEPOINT "${name}";`); } async commit() { await this.client.query('COMMIT;'); } async beforeEach() { await this.begin(); await this.savepoint(); } async afterEach() { await this.rollback(); await this.commit(); } setContext(ctx) { this.ctxStmts = Object.entries(ctx) .map(([key, val]) => val === null ? `SELECT set_config('${key}', NULL, true);` : `SELECT set_config('${key}', '${val}', true);`) .join('\n'); } async any(query, values) { const result = await this.query(query, values); return result.rows; } async one(query, values) { const rows = await this.any(query, values); if (rows.length !== 1) { throw new Error('Expected exactly one result'); } return rows[0]; } async oneOrNone(query, values) { const rows = await this.any(query, values); return rows[0] || null; } async many(query, values) { const rows = await this.any(query, values); if (rows.length === 0) throw new Error('Expected many rows, got none'); return rows; } async manyOrNone(query, values) { return this.any(query, values); } async none(query, values) { await this.query(query, values); } async result(query, values) { return this.query(query, values); } async query(query, values) { await this.ctxQuery(); const result = await this.client.query(query, values); return result; } async ctxQuery() { if (this.ctxStmts) { await this.client.query(this.ctxStmts); } } }