44 lines
2.3 KiB
TypeScript
44 lines
2.3 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { readFile } from 'node:fs/promises';
|
|
import { resolve } from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
async function source(relativePath: string): Promise<string> {
|
|
return readFile(resolve(process.cwd(), 'src', relativePath), 'utf8');
|
|
}
|
|
|
|
test('D5.3 migration preserves physical hierarchy and adds operational context', async () => {
|
|
const migration = await source(
|
|
'database/migrations/1787421600000-phase-d5-3-operational-context.ts',
|
|
);
|
|
assert.match(migration, /CREATE TYPE asset_type_operational_role AS ENUM \('GENERIC', 'AREA', 'COMPANY'\)/);
|
|
assert.match(migration, /CREATE TABLE area_company_relations/);
|
|
assert.match(migration, /CREATE UNIQUE INDEX uq_area_company_relations_active_pair/);
|
|
assert.match(migration, /ADD COLUMN operational_area_id uuid/);
|
|
assert.match(migration, /ADD COLUMN operator_company_id uuid/);
|
|
assert.match(migration, /chk_assets_operational_assignment_pair/);
|
|
assert.match(migration, /operational area must be an ancestor in the physical hierarchy/);
|
|
assert.match(migration, /physical hierarchy change would invalidate descendant operational assignments/);
|
|
assert.match(migration, /area cannot be inactivated while operational relations or assignments are active/);
|
|
assert.match(migration, /FOR KEY SHARE/);
|
|
assert.match(migration, /REVOKE DELETE ON TABLE area_company_relations/);
|
|
});
|
|
|
|
test('D5.3 API enforces active relation, exclusive pair and physical ancestry', async () => {
|
|
const assets = await source('asset-master/assets.service.ts');
|
|
assert.match(assets, /ASSET_OPERATIONAL_CONTEXT_INCOMPLETE/);
|
|
assert.match(assets, /ASSET_OPERATIONAL_RELATION_REQUIRED/);
|
|
assert.match(assets, /ASSET_OPERATIONAL_AREA_OUTSIDE_HIERARCHY/);
|
|
assert.match(assets, /ASSET_HIERARCHY_MOVE_BREAKS_OPERATIONAL_CONTEXT/);
|
|
assert.match(assets, /OPERATIONAL_ANCHOR_IN_USE/);
|
|
});
|
|
|
|
test('D5.3 relation lifecycle is historical and audited', async () => {
|
|
const service = await source('asset-master/asset-operational-relations.service.ts');
|
|
assert.match(service, /INSERT INTO area_company_relations/);
|
|
assert.match(service, /valid_until = CURRENT_TIMESTAMP/);
|
|
assert.match(service, /AREA_COMPANY_RELATION_IN_USE/);
|
|
assert.match(service, /ASSET_AREA_COMPANY_RELATION_CREATED/);
|
|
assert.match(service, /ASSET_AREA_COMPANY_RELATION_ENDED/);
|
|
});
|