diff --git a/api-v3/test/unit/phase-d5-3-21-document-delivery.test.ts b/api-v3/test/unit/phase-d5-3-21-document-delivery.test.ts index 43bbdac..f5fc184 100644 --- a/api-v3/test/unit/phase-d5-3-21-document-delivery.test.ts +++ b/api-v3/test/unit/phase-d5-3-21-document-delivery.test.ts @@ -1,7 +1,64 @@ -import assert from 'node:assert/strict'; import test from 'node:test'; import {readFileSync} from 'node:fs'; import {resolve} from 'node:path'; -const read=(path:string)=>readFileSync(resolve(process.cwd(),path),'utf8'); const migration=read('src/database/migrations/1788544800000-phase-d5-3-21-document-delivery.ts'); const delivery=read('src/inspection-reports/inspection-document-delivery.service.ts'); const smtp=read('src/inspection-reports/smtp-delivery.service.ts'); const pdf=read('src/inspection-reports/inspection-act-pdf-builder.ts'); const controller=read('src/inspection-reports/document-delivery.controller.ts'); const reports=read('src/inspection-reports/inspection-reports.service.ts'); -test('D5.3.21 stores institutional and company recipients without hardcoding addresses',()=>{assert.match(migration,/institutional_delivery_settings/);assert.match(migration,/notification_email varchar\(320\)/);assert.match(delivery,/office_email/);assert.match(delivery,/director_email/);assert.doesNotMatch(delivery,/@gmail\.com|@hotmail\.com|@mendoza\.gov/i);}); -test('D5.3.21 creates an immutable act PDF and separates its delivery from the report Word',()=>{assert.match(migration,/inspection_act_pdf_artifacts/);assert.match(migration,/ACT_PDF/);assert.match(migration,/REPORT_WORD/);assert.match(pdf,/%PDF-1\.4/);assert.match(delivery,/this\.pdf\.ensure/);assert.match(delivery,/this\.word\.ensure/);}); -test('D5.3.21 keeps an auditable retryable outbox with explicit waiting states',()=>{assert.match(migration,/WAITING_RECIPIENT/);assert.match(migration,/WAITING_TRANSPORT/);assert.match(migration,/WAITING_ARTIFACT/);assert.match(delivery,/export interface DeliveryRow/);assert.match(controller,/Promise/);assert.match(controller,/outbox\/:id\/retry/);assert.match(controller,/retry-pending/);}); -test('D5.3.21 only attempts SMTP when transport and recipients are configured',()=>{assert.match(smtp,/SMTP_HOST/);assert.match(smtp,/MAIL_FROM/);assert.match(smtp,/STARTTLS/);assert.match(delivery,/this\.smtp\.configured\(\)/);assert.match(delivery,/WAITING_TRANSPORT/);}); -test('D5.3.21 delivery stays act-scoped after F1.1 enables multiple acts',()=>{assert.match(reports,/await this\.delivery\.dispatchForAct\(actId\)/); const acts=read('src/inspection-acts/inspection-acts.service.ts');assert.match(acts,/assertVisitHasNoDraftAct/);assert.match(acts,/INSPECTION_VISIT_DRAFT_ACT_ALREADY_EXISTS/);}); +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const read = (path: string) => readFileSync(resolve(process.cwd(), path), 'utf8'); +const migration = read('src/database/migrations/1788544800000-phase-d5-3-21-document-delivery.ts'); +const f4DirectorRemoval = read('src/database/migrations/1790000400000-f4-remove-director-report-legacy.ts'); +const delivery = read('src/inspection-reports/inspection-document-delivery.service.ts'); +const smtp = read('src/inspection-reports/smtp-delivery.service.ts'); +const pdf = read('src/inspection-reports/inspection-act-pdf-builder.ts'); +const controller = read('src/inspection-reports/document-delivery.controller.ts'); +const reports = read('src/inspection-reports/inspection-reports.service.ts'); + +test('D5.3.21/F4 stores configurable recipients without hardcoding addresses and retires Director delivery', () => { + assert.match(migration, /institutional_delivery_settings/); + assert.match(migration, /notification_email varchar\(320\)/); + assert.match(delivery, /office_email/); + assert.match(delivery, /'COMPANY' \| 'OFFICE' \| 'INSPECTOR'/); + assert.match(delivery, /recipient_kind<>'DIRECTOR'/); + assert.match(f4DirectorRemoval, /DELETE FROM inspection_document_deliveries/); + assert.match(f4DirectorRemoval, /recipient_kind = 'DIRECTOR'/); + assert.doesNotMatch(delivery, /@gmail\.com|@hotmail\.com|@mendoza\.gov/i); +}); + +test('D5.3.21 creates an immutable act PDF and separates its delivery from the editable INF Word', () => { + assert.match(migration, /inspection_act_pdf_artifacts/); + assert.match(migration, /ACT_PDF/); + assert.match(migration, /REPORT_WORD/); + assert.match(pdf, /%PDF-1\.4/); + assert.match(delivery, /this\.pdf\.ensure/); + assert.match(delivery, /this\.word\.ensure/); + assert.match(delivery, /INF editable/); +}); + +test('D5.3.21 keeps an auditable retryable outbox with explicit waiting states', () => { + assert.match(migration, /WAITING_RECIPIENT/); + assert.match(migration, /WAITING_TRANSPORT/); + assert.match(migration, /WAITING_ARTIFACT/); + assert.match(delivery, /export interface DeliveryRow/); + assert.match(controller, /Promise/); + assert.match(controller, /outbox\/:id\/retry/); + assert.match(controller, /retry-pending/); +}); + +test('F4 SMTP can be administered in database while retaining environment fallback', () => { + assert.match(smtp, /system_smtp_settings/); + assert.match(smtp, /async saveSettings/); + assert.match(smtp, /source:'DATABASE'/); + assert.match(smtp, /resolveEnvironment/); + assert.match(smtp, /SMTP_HOST/); + assert.match(smtp, /MAIL_FROM/); + assert.match(smtp, /STARTTLS/); + assert.match(smtp, /SMTP_SETTINGS_MASTER_KEY/); + assert.match(delivery, /await this\.smtp\.configured\(\)/); + assert.match(delivery, /WAITING_TRANSPORT/); +}); + +test('D5.3.21/F4 delivery stays act-scoped after multiple acts per inspection', () => { + assert.match(reports, /await this\.delivery\.dispatchForAct\(actId\)/); + const acts = read('src/inspection-acts/inspection-acts.service.ts'); + assert.match(acts, /assertVisitHasNoDraftAct/); + assert.match(acts, /INSPECTION_VISIT_DRAFT_ACT_ALREADY_EXISTS/); +});