import * as constants from '~/lib/constants'; import * as db from '~/src/db'; import * as sinon from 'sinon'; // Creates a test database and returns a query builder export async function createDB() { const oldDatabasePath = process.env.DATABASE_PATH; // for testing we use an in memory database process.env.DATABASE_PATH = ':memory:'; // @ts-expect-error need to rewrite the value of databasePath as that // is used directly by the db module constants.databasePath = process.env.DATABASE_PATH; // Cleanup the module cache in order to have it reloaded in the local context delete require.cache[require.resolve('~/src/db')]; // Initialize the database module await db.initialized(); // Get the knex instance to allow queries to the db const { models, upsertModel } = db; // This is hacky but haven't found another way to do it, // stubbing the db methods here ensures the module under test // is using the database we want sinon.stub(db, 'models').callsFake(models); sinon.stub(db, 'upsertModel').callsFake(upsertModel); return { // Returns a query builder instance for the given // table in order perform data operations models, // Resets the database to initial value post // migrations async reset() { // Reset the contents of the db await db.transaction(async (trx: any) => { const result = await trx.raw(` SELECT name, sql FROM sqlite_master WHERE type='table'`); for (const r of result) { // We don't run the migrations again if (r.name !== 'knex_migrations') { await trx.raw(`DELETE FROM ${r.name}`); } } // The supervisor expects this value to already have // been pre-populated await trx('deviceConfig').insert({ targetValues: '{}' }); }); // Reset stub call history (db.models as sinon.SinonStub).resetHistory(); (db.upsertModel as sinon.SinonStub).resetHistory(); }, // Destroys the in-memory database and resets environment async destroy() { // Remove data from the in memory database just in case await this.reset(); // Restore the old datbase path process.env.DATABASE_PATH = oldDatabasePath; // Restore stubs (db.models as sinon.SinonStub).restore(); (db.upsertModel as sinon.SinonStub).restore(); // @ts-expect-error restore the constant default constants.databasePath = process.env.DATABASE_PATH; // Cleanup the module cache in order to have it reloaded // correctly next time it's used delete require.cache[require.resolve('~/src/db')]; }, }; } export type TestDatabase = UnwrappedPromise>;