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
94 lines (93 loc) • 3.23 kB
JavaScript
import { getConnEnvOptions } from '@pgpmjs/env';
import { randomUUID } from 'crypto';
import { teardownPgPools } from 'pg-cache';
import { getPgEnvOptions, } from 'pg-env';
import { getDefaultRole } from 'pgsql-client';
import { DbAdmin } from './admin';
import { PgTestConnector } from './manager';
import { seed } from './seed';
import { formatPgError } from './utils';
let manager;
export const getPgRootAdmin = (config, connOpts = {}) => {
const opts = getPgEnvOptions({
user: config.user,
password: config.password,
host: config.host,
port: config.port,
database: connOpts.rootDb
});
const admin = new DbAdmin(opts, false, connOpts);
return admin;
};
const getConnOopts = (cn = {}) => {
const connect = getConnEnvOptions(cn.db);
const config = getPgEnvOptions({
database: `${connect.prefix}${randomUUID()}`,
...cn.pg
});
return {
pg: config,
db: connect
};
};
export const getConnections = async (cn = {}, seedAdapters = [seed.pgpm()]) => {
cn = getConnOopts(cn);
const config = cn.pg;
const connOpts = cn.db;
const root = getPgRootAdmin(config, connOpts);
await root.createUserRole(connOpts.connections.app.user, connOpts.connections.app.password, connOpts.rootDb);
const admin = new DbAdmin(config, false, connOpts);
if (process.env.TEST_DB) {
config.database = process.env.TEST_DB;
}
else if (connOpts.template) {
admin.createFromTemplate(connOpts.template, config.database);
}
else {
admin.create(config.database);
admin.installExtensions(connOpts.extensions);
}
await admin.grantConnect(connOpts.connections.app.user, config.database);
manager = PgTestConnector.getInstance(config);
const pg = manager.getClient(config);
let teardownPromise = null;
let teardownOpts = {};
const teardown = async (opts = {}) => {
teardownOpts = opts;
if (teardownPromise)
return teardownPromise;
teardownPromise = (async () => {
manager.beginTeardown();
await teardownPgPools();
await manager.closeAll({ keepDb: teardownOpts.keepDb });
})();
return teardownPromise;
};
if (seedAdapters.length) {
try {
await seed.compose(seedAdapters).seed({
connect: connOpts,
admin,
config: config,
pg: manager.getClient(config)
});
}
catch (error) {
// Format the error with PostgreSQL extended fields for better debugging
const formatted = formatPgError(error);
process.stderr.write(`[pgsql-test] Seed error (continuing):\n${formatted}\n`);
// continue without teardown to allow caller-managed lifecycle
}
}
const dbConfig = {
...config,
user: connOpts.connections.app.user,
password: connOpts.connections.app.password
};
const db = manager.getClient(dbConfig, {
auth: connOpts.auth,
roles: connOpts.roles
});
db.setContext({ role: getDefaultRole(connOpts) });
return { pg, db, teardown, manager, admin };
};