Files
dh-inspeccion-v2/api-v3/test/unit/phase-f1-1-multi-act-operating-model.test.ts
T
admin cd24736df8 F1.1 · Inspección multi-Acta y firma diferida
Implementa el nuevo núcleo operativo: múltiples Actas por Inspección, un Informe por Acta, cierre de campo independiente y firma de empresa diferida con conformidad/disidencia.
2026-09-05 14:46:26 -03:00

72 lines
4.0 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');
test('F1.1 migration allows many acts per inspection while keeping only one draft at a time', () => {
const migration = read('src/database/migrations/1789495200000-phase-f1-1-multi-act-inspections.ts');
assert.match(migration, /DROP CONSTRAINT IF EXISTS uq_inspection_acts_visit/);
assert.match(migration, /CREATE UNIQUE INDEX uq_inspection_acts_one_draft_per_visit/);
assert.match(migration, /WHERE status = 'DRAFT'/);
assert.match(migration, /DROP CONSTRAINT IF EXISTS uq_inspection_reports_visit/);
assert.match(migration, /CREATE INDEX idx_inspection_reports_visit_id/);
});
test('F1.1 preserves exactly one frozen report per act instead of per inspection', () => {
const reportEntity = read('src/database/entities/inspection-report.entity.ts');
const reports = read('src/inspection-reports/inspection-reports.service.ts');
assert.match(reportEntity, /@Index\('uq_inspection_reports_act', \['actId'\], \{ unique: true \}\)/);
assert.match(reportEntity, /@Index\('idx_inspection_reports_visit_id', \['visitId'\]\)/);
assert.doesNotMatch(reportEntity, /visitId'\], \{ unique: true \}/);
assert.match(reports, /WHERE act_id = \$1/);
});
test('F1.1 closes an act without closing its parent inspection', () => {
const closing = read('src/inspection-closing/inspection-closing.service.ts');
const closeBody = closing.slice(closing.indexOf(' async close('), closing.indexOf(' async signatureContent('));
assert.match(closeBody, /UPDATE inspection_acts/);
assert.doesNotMatch(closeBody, /UPDATE inspection_visits/);
assert.match(closeBody, /visitRemainsIndependent: true/);
assert.match(closeBody, /ensureFrozenReport\(manager, actId, principal, request\)/);
});
test('F1.1 exposes an APK-only explicit inspection close and permits pending company signature', () => {
const controller = read('src/inspection-visits/inspection-visits.controller.ts');
const visits = read('src/inspection-visits/inspection-visits.service.ts');
assert.match(controller, /@Post\(':id\/close'\)/);
assert.match(controller, /@RequirePermissions\('inspections\.execute'\)/);
assert.match(visits, /async close\(/);
assert.match(visits, /assertMobileInspector\(principal\)/);
assert.match(visits, /INSPECTION_VISIT_DRAFT_ACTS_PENDING/);
assert.match(visits, /INSPECTION_VISIT_INSPECTOR_SIGNATURE_PENDING/);
assert.match(visits, /pendingCompanySignatures/);
assert.match(visits, /actsMayCompleteCompanySignatureLater: true/);
});
test('F1.1 lets the company sign after the inspection closes and records conformity or dissent', () => {
const closing = read('src/inspection-closing/inspection-closing.service.ts');
const dto = read('src/inspection-closing/dto/create-company-signature.dto.ts');
const signatureEntity = read('src/database/entities/inspection-act-signature.entity.ts');
assert.match(closing, /InspectionVisitStatus\.IN_PROGRESS, InspectionVisitStatus\.CLOSED/);
assert.match(closing, /InspectionCompanySignatureManifestation\.CONFORMITY/);
assert.match(closing, /InspectionCompanySignatureManifestation\.DISSENT/);
assert.match(dto, /@ValidateIf/);
assert.match(dto, /@MinLength\(10\)/);
assert.match(signatureEntity, /CONFORMITY = 'CONFORMITY'/);
assert.match(signatureEntity, /DISSENT = 'DISSENT'/);
assert.match(signatureEntity, /companyStatement/);
});
test('F1.1 keeps field-created Inventory linked only to the current draft act', () => {
const link = read('src/inspection-operations/field-discovery-inspection-link.service.ts');
assert.match(link, /AND status = 'DRAFT'/);
assert.match(link, /if \(act\)/);
assert.match(link, /inspection_visit_assets/);
assert.match(link, /inspection_act_assets/);
assert.match(link, /return \{ actId: act\?\.id \?\? null \}/);
assert.doesNotMatch(link, /status <> 'CANCELLED'/);
});