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/1790117400000-f6-2-user-smtp-and-act-representative.ts'); const closing = read('src/inspection-closing/inspection-closing.service.ts'); const responsibleDto = read('src/inspection-closing/dto/upsert-inspection-responsible.dto.ts'); const prepareDto = read('src/inspection-closing/dto/prepare-inspection-act.dto.ts'); const findingEntity = read('src/database/entities/inspection-finding.entity.ts'); const smtp = read('src/inspection-reports/smtp-delivery.service.ts'); const users = read('src/administration/users/users.controller.ts'); const delivery = read('src/inspection-reports/inspection-document-delivery.service.ts'); const android = read('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernMobileActsScreen.kt'); const androidModel = read('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/data/MobileActs.kt'); const profilePage = read('../web-v2/src/pages/MyProfilePage.tsx'); test('F6.2 keeps urgency exclusively at Act close, never on individual findings', () => { assert.match(prepareDto, /InspectionActUrgency/); assert.match(prepareDto, /urgency!/); assert.doesNotMatch(findingEntity, /\burgency\b/i); assert.match(android, /Urgencia del Acta/); assert.match(android, /urgencia no se asigna a cada Hallazgo/i); }); test('F6.2 requires the company representative identity and email on every Act', () => { assert.match(responsibleDto, /attendanceStatus === InspectionResponsibleAttendanceStatus\.PRESENT/); assert.match(responsibleDto, /@IsEmail\(\)/); assert.match(migration, /LENGTH\(TRIM\(COALESCE\(email, ''\)\)\) > 0/); assert.match(closing, /representativeSuggestion/); assert.match(closing, /previous_act\.visit_id=current_act\.visit_id/); assert.match(androidModel, /representativeSuggestion/); assert.match(android, /Nombres y apellidos \*/); assert.match(android, /DNI \*/); assert.match(android, /Cargo \/ función \*/); assert.match(android, /Email \*/); assert.match(android, /Firma del representante de la empresa/); assert.match(android, /En disconformidad/); assert.match(android, /Motivo de disconformidad \*/); }); test('F6.2 gives every authenticated user a general SMTP default and encrypted custom override', () => { assert.match(migration, /CREATE TABLE user_smtp_settings/); assert.match(migration, /ALTER COLUMN email SET NOT NULL/); assert.match(migration, /mode IN \('SYSTEM','CUSTOM'\)/); assert.match(smtp, /publicUserSettings/); assert.match(smtp, /saveUserSettings/); assert.match(smtp, /source:\s*["']USER["']/); assert.match(smtp, /encryptSecret/); assert.match(smtp, /password_enc/); }); test('F6.2 exposes personal mail settings in Mi perfil without granting administration permissions', () => { assert.match(users, /@Get\('self\/profile'\)/); assert.match(users, /@Patch\('self\/profile'\)/); assert.match(users, /@Get\('self\/smtp'\)/); assert.match(users, /@Put\('self\/smtp'\)/); assert.match(users, /@Post\('self\/smtp\/test'\)/); assert.match(profilePage, /MI PERFIL/); assert.match(profilePage, /Usar SMTP general/); assert.match(profilePage, /Usar SMTP propio/); assert.match(profilePage, /Enviar correo de prueba/); assert.doesNotMatch(profilePage, /document_delivery\.manage/); }); test('F6.2 sends Act-related mail through the lead inspector transport selection', () => { assert.match(delivery, /lead_inspector_user_id AS "userId"/); assert.match(delivery, /configured\(senderUserId\)/); assert.match(delivery, /}, senderUserId\);/); });