balena-supervisor/test/02-db.spec.ts
Christina Wang 4a2ac557ef
Remove mz, mkdirp, body-parser dependencies
'mz' can be safely replaced with fs.promises
and util.promisify for faster native methods.
'mkdirp' after Node v8 uses native fs.mkdir, thus
is redundant. 'body-parser' is deprecated and
contained within express v4.x.

Closes: #1567
Change-type: patch
Signed-off-by: Christina Wang <christina@balena.io>
2021-04-28 07:20:15 +09:00

122 lines
3.6 KiB
TypeScript

import * as Bluebird from 'bluebird';
import * as Knex from 'knex';
import { expect } from 'chai';
import prepare = require('./lib/prepare');
import * as constants from '../src/lib/constants';
import { exists } from '../src/lib/fs-utils';
async function createOldDatabase(path: string) {
const knex = Knex({
client: 'sqlite3',
connection: {
filename: path,
},
useNullAsDefault: true,
});
const createEmptyTable = (
name: string,
fn: (trx: Knex.CreateTableBuilder) => void,
) =>
knex.schema.createTable(name, (t) => {
if (fn != null) {
return fn(t);
}
});
await createEmptyTable('app', (t) => {
t.increments('id').primary();
t.boolean('privileged');
return t.string('containerId');
});
await createEmptyTable('config', (t) => {
t.string('key');
return t.string('value');
});
await createEmptyTable('dependentApp', (t) => t.increments('id').primary());
await createEmptyTable('dependentDevice', (t) =>
t.increments('id').primary(),
);
return knex;
}
describe('Database Migrations', () => {
before(async () => {
await prepare();
});
after(() => {
// @ts-ignore
constants.databasePath = process.env.DATABASE_PATH;
delete require.cache[require.resolve('../src/db')];
});
it('creates a database at the path passed on creation', async () => {
const databasePath = process.env.DATABASE_PATH_2!;
// @ts-ignore
constants.databasePath = databasePath;
delete require.cache[require.resolve('../src/db')];
const testDb = await import('../src/db');
await testDb.initialized;
expect(await exists(databasePath)).to.be.true;
});
it('adds new fields and removes old ones in an old database', async () => {
const databasePath = process.env.DATABASE_PATH_3!;
const knexForDB = await createOldDatabase(databasePath);
// @ts-ignore
constants.databasePath = databasePath;
delete require.cache[require.resolve('../src/db')];
const testDb = await import('../src/db');
await testDb.initialized;
await Bluebird.all([
expect(knexForDB.schema.hasColumn('app', 'appId')).to.eventually.be.true,
expect(knexForDB.schema.hasColumn('app', 'releaseId')).to.eventually.be
.true,
expect(knexForDB.schema.hasColumn('app', 'config')).to.eventually.be
.false,
expect(knexForDB.schema.hasColumn('app', 'privileged')).to.eventually.be
.false,
expect(knexForDB.schema.hasColumn('app', 'containerId')).to.eventually.be
.false,
expect(knexForDB.schema.hasColumn('dependentApp', 'environment')).to
.eventually.be.true,
expect(knexForDB.schema.hasColumn('dependentDevice', 'markedForDeletion'))
.to.eventually.be.true,
expect(knexForDB.schema.hasColumn('dependentDevice', 'localId')).to
.eventually.be.true,
expect(knexForDB.schema.hasColumn('dependentDevice', 'is_managed_by')).to
.eventually.be.true,
expect(knexForDB.schema.hasColumn('dependentDevice', 'lock_expiry_date'))
.to.eventually.be.true,
]);
});
});
describe('Database', () => {
let db: typeof import('../src/db');
before(async () => {
await prepare();
db = await import('../src/db');
});
it('initializes correctly, running the migrations', () => {
return expect(db.initialized).to.be.fulfilled;
});
it('creates a database at the path from an env var', async () => {
expect(await exists(process.env.DATABASE_PATH!)).to.be.true;
});
it('creates a deviceConfig table with a single default value', async () => {
const deviceConfig = await db.models('deviceConfig').select();
expect(deviceConfig).to.have.lengthOf(1);
expect(deviceConfig).to.deep.equal([{ targetValues: '{}' }]);
});
it('allows performing transactions', () => {
return db.transaction((trx) => expect(trx.commit()).to.be.fulfilled);
});
});