Merge pull request #32468 from backstage/freben/refactor-pg-tests

test the pg thing too
This commit is contained in:
Fredrik Adelöw
2026-01-22 14:02:07 +01:00
committed by GitHub
2 changed files with 494 additions and 2 deletions
@@ -17,10 +17,12 @@
import { Config, ConfigReader } from '@backstage/config';
import {
buildPgDatabaseConfig,
computePgPluginConfig,
createPgDatabaseClient,
getPgConnectionConfig,
parsePgConnectionString,
} from './postgres';
import { type Knex } from 'knex';
jest.mock('@google-cloud/cloud-sql-connector');
@@ -394,3 +396,493 @@ describe('postgres', () => {
});
});
});
describe('computePgPluginConfig', () => {
const prefix = 'backstage_plugin_';
describe('client', () => {
it('uses base client when no plugin client specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.client).toBe('pg');
expect(result.clientOverridden).toBe(false);
});
it('uses plugin client when specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
plugin: {
catalog: {
client: 'better-sqlite3',
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.client).toBe('better-sqlite3');
expect(result.clientOverridden).toBe(true);
});
});
describe('role', () => {
it('returns undefined when no role specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.role).toBeUndefined();
});
it('uses base role when no plugin role specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
role: 'base_role',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.role).toBe('base_role');
});
it('uses plugin role when specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
role: 'base_role',
plugin: {
catalog: {
role: 'plugin_role',
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.role).toBe('plugin_role');
});
});
describe('additionalKnexConfig', () => {
it('returns empty object when no knexConfig specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.additionalKnexConfig).toEqual({});
});
it('uses base knexConfig when no plugin config', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
knexConfig: { debug: true },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.additionalKnexConfig).toEqual({ debug: true });
});
it('merges base and plugin knexConfig', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
knexConfig: { debug: true, pool: { min: 0 } },
plugin: {
catalog: {
knexConfig: { pool: { max: 10 } },
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.additionalKnexConfig).toEqual({
debug: true,
pool: { min: 0, max: 10 },
});
});
});
describe('ensureExists', () => {
it('defaults to true when not specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.ensureExists).toBe(true);
});
it('uses base ensureExists when no plugin setting', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
ensureExists: false,
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.ensureExists).toBe(false);
});
it('uses plugin ensureExists when specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
ensureExists: true,
plugin: {
catalog: {
ensureExists: false,
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.ensureExists).toBe(false);
});
});
describe('ensureSchemaExists', () => {
it('defaults to false when not specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.ensureSchemaExists).toBe(false);
});
it('uses base ensureSchemaExists when no plugin setting', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
ensureSchemaExists: true,
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.ensureSchemaExists).toBe(true);
});
});
describe('pluginDivisionMode', () => {
it('defaults to database when not specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.pluginDivisionMode).toBe('database');
});
it('uses specified pluginDivisionMode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.pluginDivisionMode).toBe('schema');
});
});
describe('connection', () => {
it('sets application_name to plugin id', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection).toMatchObject({
application_name: 'backstage_plugin_catalog',
});
});
it('preserves existing application_name', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', application_name: 'custom_name' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection).toMatchObject({
application_name: 'custom_name',
});
});
it('omits database from base connection when pluginDivisionMode is database', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', database: 'shared_db' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection.database).toBeUndefined();
});
it('keeps database from base connection when pluginDivisionMode is schema', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', database: 'shared_db' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection.database).toBe('shared_db');
});
it('merges plugin connection with base connection', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', user: 'base_user' },
plugin: {
catalog: {
connection: { password: 'plugin_pass' },
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection).toMatchObject({
host: 'localhost',
user: 'base_user',
password: 'plugin_pass',
});
});
it('excludes base connection when client is overridden', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', user: 'base_user' },
plugin: {
catalog: {
client: 'better-sqlite3',
connection: { filename: ':memory:' },
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection.host).toBeUndefined();
expect(result.connection.user).toBeUndefined();
expect(
(result.connection as Knex.BetterSqlite3ConnectionConfig).filename,
).toBe(':memory:');
});
it('parses connection string in base config', () => {
const config = new ConfigReader({
client: 'pg',
connection: 'postgresql://user:pass@localhost:5432/mydb',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection).toMatchObject({
host: 'localhost',
user: 'user',
password: 'pass',
port: '5432',
});
});
it('parses connection string in plugin config', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'base-host' },
plugin: {
catalog: {
connection: 'postgresql://plugin:pass@plugin-host:5432/plugindb',
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.connection).toMatchObject({
host: 'plugin-host',
user: 'plugin',
password: 'pass',
port: '5432',
});
});
});
describe('databaseName', () => {
it('auto-generates database name with prefix in database mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseName).toBe('backstage_plugin_catalog');
});
it('uses connection database when specified in database mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
plugin: {
catalog: {
connection: { database: 'custom_db' },
},
},
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseName).toBe('custom_db');
});
it('uses connection database in schema mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', database: 'shared_db' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseName).toBe('shared_db');
});
it('returns undefined when no database in schema mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseName).toBeUndefined();
});
});
describe('databaseClientOverrides', () => {
it('sets connection.database when databaseName exists', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseClientOverrides).toEqual({
connection: { database: 'backstage_plugin_catalog' },
});
});
it('adds searchPath when in schema mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost', database: 'shared_db' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseClientOverrides).toEqual({
connection: { database: 'shared_db' },
searchPath: ['catalog'],
});
});
it('returns empty object when no databaseName in schema mode', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
pluginDivisionMode: 'schema',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.databaseClientOverrides).toEqual({
searchPath: ['catalog'],
});
});
});
describe('knexConfig', () => {
it('includes client and connection', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.knexConfig.client).toBe('pg');
expect(result.knexConfig.connection).toBeDefined();
});
it('includes role when specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
role: 'my_role',
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect((result.knexConfig as any).role).toBe('my_role');
});
it('does not include role when not specified', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect((result.knexConfig as any).role).toBeUndefined();
});
it('includes additionalKnexConfig properties', () => {
const config = new ConfigReader({
client: 'pg',
connection: { host: 'localhost' },
knexConfig: { debug: true, pool: { min: 2 } },
});
const result = computePgPluginConfig(config, 'catalog', prefix);
expect(result.knexConfig.debug).toBe(true);
expect(result.knexConfig.pool).toEqual({ min: 2 });
});
});
});
@@ -310,7 +310,7 @@ export interface PgPluginDatabaseConfig {
/** The plugin division mode ('database' or 'schema') */
pluginDivisionMode: string;
/** The connection configuration */
connection: Knex.StaticConnectionConfig;
connection: Knex.PgConnectionConfig;
/** The database name, if any */
databaseName: string | undefined;
/** Database client overrides including schema overrides if applicable */
@@ -394,7 +394,7 @@ export function computePgPluginConfig(
// Include base connection if client type has not been overridden
...(clientOverridden ? {} : baseConnection),
...pluginConnection,
} as Knex.StaticConnectionConfig;
} as Knex.PgConnectionConfig;
// Database name
const connectionDatabaseName = (connection as Knex.ConnectionConfig)