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
76 lines (75 loc) • 2.71 kB
JavaScript
import { PgClient } from 'pgsql-client';
import { insertJsonMap } from 'pgsql-seed';
import { loadCsvMap } from 'pgsql-seed';
import { loadSqlFiles } from 'pgsql-seed';
import { deployPgpm } from 'pgsql-seed';
import { formatPgError } from './utils';
export class PgTestClient extends PgClient {
testOpts;
constructor(config, opts = {}) {
super(config, opts);
this.testOpts = opts;
}
/**
* Check if enhanced errors are enabled. Defaults to true.
* Can be disabled by setting enhancedErrors: false in options.
*/
shouldEnhanceErrors() {
// Default to true unless explicitly disabled via option
return this.testOpts.enhancedErrors !== false;
}
/**
* Override query to enhance PostgreSQL errors with extended fields.
* When enhancedErrors is enabled, errors will include detail, hint, where, position, etc.
*/
async query(query, values) {
try {
return await super.query(query, values);
}
catch (err) {
if (this.shouldEnhanceErrors()) {
// Enhance the error message with PostgreSQL extended fields
err.message = formatPgError(err, { query, values });
}
throw err;
}
}
async beforeEach() {
await this.begin();
await this.savepoint();
}
async afterEach() {
await this.rollback();
await this.commit();
}
/**
* Commit current transaction to make data visible to other connections, then start fresh transaction.
* Maintains test isolation by creating a savepoint and reapplying session context.
*/
async publish() {
await this.commit(); // make data visible to other sessions
await this.begin(); // fresh tx
await this.savepoint(); // keep rollback harness
await this.ctxQuery(); // reapply all setContext()
}
async loadJson(data) {
await this.ctxQuery();
await insertJsonMap(this.client, data);
}
async loadSql(files) {
await this.ctxQuery();
await loadSqlFiles(this.client, files);
}
// NON-RLS load/seed methods:
async loadCsv(tables) {
// await this.ctxQuery(); // no point to call ctxQuery() here
// because POSTGRES doesn't support row-level security on COPY FROM...
await loadCsvMap(this.client, tables);
}
async loadPgpm(cwd, cache = false) {
// await this.ctxQuery(); // no point to call ctxQuery() here
// because deployPgpm() has it's own way of getting the client...
// so for now, we'll expose this but it's limited
await deployPgpm(this.config, cwd, cache);
}
}