@backstage/backend-test-utils
Version:
Test helpers library for Backstage backends
129 lines (125 loc) • 4.16 kB
JavaScript
;
var isDockerDisabledForTests = require('../util/isDockerDisabledForTests.cjs.js');
var mysql = require('./mysql.cjs.js');
var postgres = require('./postgres.cjs.js');
var sqlite = require('./sqlite.cjs.js');
var types = require('./types.cjs.js');
class TestDatabases {
engineFactoryByDriver = {
pg: postgres.PostgresEngine.create,
mysql: mysql.MysqlEngine.create,
mysql2: mysql.MysqlEngine.create,
"better-sqlite3": sqlite.SqliteEngine.create,
sqlite3: sqlite.SqliteEngine.create
};
engineByTestDatabaseId;
supportedIds;
static defaultIds;
/**
* Creates an empty `TestDatabases` instance, and sets up Jest to clean up
* all of its acquired resources after all tests finish.
*
* You typically want to create just a single instance like this at the top
* of your test file or `describe` block, and then call `init` many times on
* that instance inside the individual tests. Spinning up a "physical"
* database instance takes a considerable amount of time, slowing down tests.
* But initializing a new logical database inside that instance using `init`
* is very fast.
*/
static create(options) {
const ids = options?.ids;
const disableDocker = options?.disableDocker ?? isDockerDisabledForTests.isDockerDisabledForTests();
let testDatabaseIds;
if (ids) {
testDatabaseIds = ids;
} else if (TestDatabases.defaultIds) {
testDatabaseIds = TestDatabases.defaultIds;
} else {
testDatabaseIds = Object.keys(types.allDatabases);
}
const supportedIds = testDatabaseIds.filter((id) => {
const properties = types.allDatabases[id];
if (!properties) {
return false;
}
if (properties.connectionStringEnvironmentVariableName && process.env[properties.connectionStringEnvironmentVariableName]) {
return true;
}
if (!properties.dockerImageName) {
return true;
}
if (disableDocker) {
return false;
}
return true;
});
const databases = new TestDatabases(supportedIds);
if (supportedIds.length > 0) {
afterAll(async () => {
await databases.shutdown();
});
}
return databases;
}
static setDefaults(options) {
TestDatabases.defaultIds = options.ids;
}
constructor(supportedIds) {
this.engineByTestDatabaseId = /* @__PURE__ */ new Map();
this.supportedIds = supportedIds;
}
supports(id) {
return this.supportedIds.includes(id);
}
eachSupportedId() {
return this.supportedIds.map((id) => [id]);
}
/**
* Returns a fresh, unique, empty logical database on an instance of the
* given database ID platform.
*
* @param id - The ID of the database platform to use, e.g. 'POSTGRES_13'
* @returns A `Knex` connection object
*/
async init(id) {
const properties = types.allDatabases[id];
if (!properties) {
const candidates = Object.keys(types.allDatabases).join(", ");
throw new Error(
`Unknown test database ${id}, possible values are ${candidates}`
);
}
if (!this.supportedIds.includes(id)) {
const candidates = this.supportedIds.join(", ");
throw new Error(
`Unsupported test database ${id} for this environment, possible values are ${candidates}`
);
}
let engine = this.engineByTestDatabaseId.get(id);
if (!engine) {
const factory = this.engineFactoryByDriver[properties.driver];
if (!factory) {
throw new Error(`Unknown database driver ${properties.driver}`);
}
engine = await factory(properties);
this.engineByTestDatabaseId.set(id, engine);
}
return await engine.createDatabaseInstance();
}
async shutdown() {
const engines = [...this.engineByTestDatabaseId.values()];
this.engineByTestDatabaseId.clear();
for (const engine of engines) {
try {
await engine.shutdown();
} catch (error) {
console.warn(`TestDatabases: Failed to shutdown engine`, {
engine,
error
});
}
}
}
}
exports.TestDatabases = TestDatabases;
//# sourceMappingURL=TestDatabases.cjs.js.map