Merge pull request #32468 from backstage/freben/refactor-pg-tests
test the pg thing too
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user