2024-02-29 22:00:39 +00:00
|
|
|
import type { Knex } from 'knex';
|
|
|
|
import { knex } from 'knex';
|
2022-09-09 15:53:57 +00:00
|
|
|
import { promises as fs } from 'fs';
|
2019-09-12 15:26:21 +00:00
|
|
|
|
2021-04-26 19:54:04 +00:00
|
|
|
import { expect } from 'chai';
|
2022-08-17 23:35:08 +00:00
|
|
|
import * as constants from '~/lib/constants';
|
2019-09-12 15:26:21 +00:00
|
|
|
|
|
|
|
async function createOldDatabase(path: string) {
|
2022-09-26 18:26:48 +00:00
|
|
|
const db = knex({
|
2019-09-12 15:26:21 +00:00
|
|
|
client: 'sqlite3',
|
|
|
|
connection: {
|
|
|
|
filename: path,
|
|
|
|
},
|
|
|
|
useNullAsDefault: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
const createEmptyTable = (
|
|
|
|
name: string,
|
|
|
|
fn: (trx: Knex.CreateTableBuilder) => void,
|
|
|
|
) =>
|
2022-09-26 18:26:48 +00:00
|
|
|
db.schema.createTable(name, (t) => {
|
2019-09-12 15:26:21 +00:00
|
|
|
if (fn != null) {
|
|
|
|
return fn(t);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-05-15 11:01:51 +00:00
|
|
|
await createEmptyTable('app', (t) => {
|
2019-09-12 15:26:21 +00:00
|
|
|
t.increments('id').primary();
|
|
|
|
t.boolean('privileged');
|
|
|
|
return t.string('containerId');
|
|
|
|
});
|
2020-05-15 11:01:51 +00:00
|
|
|
await createEmptyTable('config', (t) => {
|
2019-09-12 15:26:21 +00:00
|
|
|
t.string('key');
|
|
|
|
return t.string('value');
|
|
|
|
});
|
2020-05-15 11:01:51 +00:00
|
|
|
await createEmptyTable('dependentApp', (t) => t.increments('id').primary());
|
|
|
|
await createEmptyTable('dependentDevice', (t) =>
|
|
|
|
t.increments('id').primary(),
|
|
|
|
);
|
2022-09-26 18:26:48 +00:00
|
|
|
return db;
|
2019-09-12 15:26:21 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 15:53:57 +00:00
|
|
|
async function restoreDb() {
|
|
|
|
await fs.unlink(constants.databasePath).catch(() => {
|
|
|
|
/* NOOP */
|
2019-09-12 15:26:21 +00:00
|
|
|
});
|
2022-09-09 15:53:57 +00:00
|
|
|
// Reset the module cache to allow the database to be initialized again
|
|
|
|
delete require.cache[require.resolve('~/src/db')];
|
|
|
|
}
|
2019-09-12 15:26:21 +00:00
|
|
|
|
2022-11-21 20:07:46 +00:00
|
|
|
// Utility method to use along with `require`
|
|
|
|
type Db = typeof import('~/src/db');
|
|
|
|
|
2022-09-09 15:53:57 +00:00
|
|
|
describe('db', () => {
|
|
|
|
afterEach(async () => {
|
|
|
|
await restoreDb();
|
2019-09-12 15:26:21 +00:00
|
|
|
});
|
|
|
|
|
2020-05-28 17:15:33 +00:00
|
|
|
it('creates a database at the path passed on creation', async () => {
|
2024-02-29 22:00:39 +00:00
|
|
|
// eslint-disable-next-line
|
2022-11-21 20:07:46 +00:00
|
|
|
const testDb = require('~/src/db') as Db;
|
2022-09-06 18:03:23 +00:00
|
|
|
await testDb.initialized();
|
2022-09-09 15:53:57 +00:00
|
|
|
await expect(fs.access(constants.databasePath)).to.not.be.rejected;
|
2019-09-12 15:26:21 +00:00
|
|
|
});
|
|
|
|
|
2022-09-09 15:53:57 +00:00
|
|
|
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);
|
2024-02-29 22:00:39 +00:00
|
|
|
// eslint-disable-next-line
|
2022-11-21 20:07:46 +00:00
|
|
|
const testDb = require('~/src/db') as Db;
|
2022-09-06 18:03:23 +00:00
|
|
|
await testDb.initialized();
|
2023-01-30 21:30:17 +00:00
|
|
|
await Promise.all([
|
2019-09-12 15:26:21 +00:00
|
|
|
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,
|
2023-01-30 21:30:17 +00:00
|
|
|
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,
|
2019-09-12 15:26:21 +00:00
|
|
|
]);
|
|
|
|
});
|
2020-05-28 17:15:33 +00:00
|
|
|
|
2019-09-12 15:26:21 +00:00
|
|
|
it('creates a deviceConfig table with a single default value', async () => {
|
2024-02-29 22:00:39 +00:00
|
|
|
// eslint-disable-next-line
|
2022-11-21 20:07:46 +00:00
|
|
|
const testDb = require('~/src/db') as Db;
|
2022-09-09 15:53:57 +00:00
|
|
|
await testDb.initialized();
|
|
|
|
const deviceConfig = await testDb.models('deviceConfig').select();
|
2019-09-12 15:26:21 +00:00
|
|
|
expect(deviceConfig).to.have.lengthOf(1);
|
|
|
|
expect(deviceConfig).to.deep.equal([{ targetValues: '{}' }]);
|
|
|
|
});
|
|
|
|
|
2022-09-09 15:53:57 +00:00
|
|
|
it('allows performing transactions', async () => {
|
2024-02-29 22:00:39 +00:00
|
|
|
// eslint-disable-next-line
|
2022-11-21 20:07:46 +00:00
|
|
|
const testDb = require('~/src/db') as Db;
|
2022-09-09 15:53:57 +00:00
|
|
|
await testDb.initialized();
|
|
|
|
return testDb.transaction((trx) => expect(trx.commit()).to.be.fulfilled);
|
2019-09-12 15:26:21 +00:00
|
|
|
});
|
|
|
|
});
|