balena-supervisor/test/integration/db.spec.ts
Felipe Lalanne 988a1c9e9a Update @balena/lint to v7
This updates balena lint to the latest version to enable eslint support
and unblock Typescript updates. This is a huge number of changes as the
linting rules are much more strict now, requiring modifiying most files
in the codebase. This commit also bumps the test dependency `rewire` as
that was interfering with the update of balena-lint

Change-type: patch
2024-03-01 18:27:30 -03:00

108 lines
3.2 KiB
TypeScript

import type { Knex } from 'knex';
import { knex } from 'knex';
import { promises as fs } from 'fs';
import { expect } from 'chai';
import * as constants from '~/lib/constants';
async function createOldDatabase(path: string) {
const db = knex({
client: 'sqlite3',
connection: {
filename: path,
},
useNullAsDefault: true,
});
const createEmptyTable = (
name: string,
fn: (trx: Knex.CreateTableBuilder) => void,
) =>
db.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 db;
}
async function restoreDb() {
await fs.unlink(constants.databasePath).catch(() => {
/* NOOP */
});
// Reset the module cache to allow the database to be initialized again
delete require.cache[require.resolve('~/src/db')];
}
// Utility method to use along with `require`
type Db = typeof import('~/src/db');
describe('db', () => {
afterEach(async () => {
await restoreDb();
});
it('creates a database at the path passed on creation', async () => {
// eslint-disable-next-line
const testDb = require('~/src/db') as Db;
await testDb.initialized();
await expect(fs.access(constants.databasePath)).to.not.be.rejected;
});
it('migrations add new fields and removes old ones in an old database', async () => {
// Create a database with an older schema
const knexForDB = await createOldDatabase(constants.databasePath);
// eslint-disable-next-line
const testDb = require('~/src/db') as Db;
await testDb.initialized();
await Promise.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.hasTable('dependentDeviceTarget')).to.eventually
.be.false,
expect(knexForDB.schema.hasTable('dependentDevice')).to.eventually.be
.false,
expect(knexForDB.schema.hasTable('dependentAppTarget')).to.eventually.be
.false,
expect(knexForDB.schema.hasTable('dependentApp')).to.eventually.be.false,
]);
});
it('creates a deviceConfig table with a single default value', async () => {
// eslint-disable-next-line
const testDb = require('~/src/db') as Db;
await testDb.initialized();
const deviceConfig = await testDb.models('deviceConfig').select();
expect(deviceConfig).to.have.lengthOf(1);
expect(deviceConfig).to.deep.equal([{ targetValues: '{}' }]);
});
it('allows performing transactions', async () => {
// eslint-disable-next-line
const testDb = require('~/src/db') as Db;
await testDb.initialized();
return testDb.transaction((trx) => expect(trx.commit()).to.be.fulfilled);
});
});