47 lines
2.6 KiB
TypeScript
47 lines
2.6 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import test from 'node:test';
|
|
|
|
const root = process.cwd();
|
|
const read = (relative: string) => fs.readFileSync(path.join(root, relative), 'utf8');
|
|
|
|
const migration = read('src/database/migrations/1790000700000-f4-align-asset-version-function-change.ts');
|
|
const workflow = read('src/inspection-reports/inspection-report-workflow.service.ts');
|
|
const word = read('src/inspection-reports/inspection-report-word.service.ts');
|
|
const controller = read('src/inspection-reports/inspection-reports.controller.ts');
|
|
const compose = read('../docker-compose.yml');
|
|
const webApi = read('../web-v2/src/lib/reportWorkflowApi.ts');
|
|
const reportPage = read('../web-v2/src/pages/ReportDetailPage.tsx');
|
|
|
|
test('F4 physically permits FUNCTION_CHANGED asset versions with a reversible downgrade', () => {
|
|
const up = migration.slice(migration.indexOf(' public async up('), migration.indexOf(' public async down('));
|
|
const down = migration.slice(migration.indexOf(' public async down('));
|
|
assert.match(up, /FUNCTION_CHANGED/);
|
|
assert.match(down, /SET change_type='UPDATED'[\s\S]*WHERE change_type='FUNCTION_CHANGED'/);
|
|
});
|
|
|
|
test('F4 GEDO and follow-up uploads stay under the persisted asset-media volume', () => {
|
|
assert.match(workflow, /\?\? '\/app\/storage\/asset-media\/inspection-reports'/);
|
|
assert.match(compose, /INSPECTION_REPORT_UPLOAD_ROOT: \/app\/storage\/asset-media\/inspection-reports/);
|
|
assert.match(compose, /dhv2_asset_media:\/app\/storage\/asset-media/);
|
|
});
|
|
|
|
test('F4 narrative edits invalidate the current generated Word without overwriting its historical file', () => {
|
|
const update = workflow.slice(workflow.indexOf(' async updateNarrative('), workflow.indexOf(' async officialize('));
|
|
assert.match(update, /word_status=CASE[\s\S]*THEN 'PENDING'/);
|
|
assert.match(update, /word_stored_name=CASE[\s\S]*THEN NULL/);
|
|
assert.match(update, /word_sha256=CASE[\s\S]*THEN NULL/);
|
|
assert.match(word, /built\.sha256\.slice\(0, 16\)/);
|
|
});
|
|
|
|
test('F4 exposes the immutable official GEDO PDF through a protected integrity-checked download', () => {
|
|
assert.match(controller, /@Get\(':id\/gedo-pdf'\)[\s\S]*@RequirePermissions\('inspection_reports\.read'\)/);
|
|
assert.match(controller, /this\.workflow\.officialPdfContent\(id\)/);
|
|
assert.match(workflow, /async officialPdfContent\(/);
|
|
assert.match(workflow, /fileStat\.size !== row\.sizeBytes/);
|
|
assert.match(workflow, /createHash\('sha256'\)\.update\(buffer\)\.digest\('hex'\)/);
|
|
assert.match(webApi, /inspectionReportGedoPdfDownloadUrl/);
|
|
assert.match(reportPage, /Descargar PDF oficial/);
|
|
});
|