Assessor_2.0/tests/postgres/result-db-materialization-s...

32 lines
1.7 KiB
TypeScript

import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { describe, expect, it } from 'vitest';
import { databaseMigrations } from '../../server/postgres/migration-catalog';
const root = resolve(import.meta.dirname, '..', '..', 'server', 'postgres');
describe('PostgreSQL materialized Result DB migration', () => {
it('is registered as an additive migration after reference recognition', () => {
expect(databaseMigrations.find(migration => migration.version === '024')).toMatchObject({
version: '024', name: 'result-db-materialization'
});
});
it('stores derived rows per client with cascade deletion and one state record', async () => {
const sql = await readFile(resolve(root, 'migrations', '024_result_db_materialization.sql'), 'utf8');
expect(sql).toContain('CREATE TABLE assessor_result_db_rows');
expect(sql).toContain('REFERENCES assessor_projects(id) ON DELETE CASCADE');
expect(sql).toContain('CREATE TABLE assessor_result_db_state');
expect(sql).not.toMatch(/\bDROP\b|\bALTER TABLE assessor_(?!result_db)/u);
});
it('serves every Result DB read from the stored rows and rebuilds after committed changes', async () => {
const repository = await readFile(resolve(root, 'postgres-assessor-repository.ts'), 'utf8');
expect(repository).toContain("if (query.audience !== 'internal-analysis') return this.storedResultDbRows(query.projectId);");
expect(repository).toContain("'SELECT row_data FROM assessor_result_db_rows WHERE result_projection_id = $1'");
expect(repository).toContain('if (changed(result)) this.scheduleResultDbRebuild();');
expect(repository).toContain('pg_advisory_lock($1)');
expect(repository).not.toContain('discloseResultDbProjection(');
});
});