import 'reflect-metadata'; import assert from 'node:assert/strict'; import test from 'node:test'; import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; import { CloseInspectionFindingDto } from '../../src/inspection-findings/dto/close-inspection-finding.dto'; import { CreateInspectionFindingDto } from '../../src/inspection-findings/dto/create-inspection-finding.dto'; import { ListInspectionFindingsQueryDto } from '../../src/inspection-findings/dto/list-inspection-findings-query.dto'; import { CreateFindingCatalogItemDto } from '../../src/inspection-findings/dto/create-finding-catalog-item.dto'; import { CreateFindingCategoryDto } from '../../src/inspection-findings/dto/create-finding-category.dto'; import { UpdateFindingCatalogItemDto } from '../../src/inspection-findings/dto/update-finding-catalog-item.dto'; import { UpdateInspectionFindingFollowUpDto } from '../../src/inspection-findings/dto/update-inspection-finding-follow-up.dto'; const ASSET_ID = '16e54e65-60cf-4739-b0d1-ccdd904fbfd5'; const CATALOG_ID = '9e38a67b-d6b1-49e0-8ec3-69a68366bd88'; test('finding DTO accepts catalog findings with a correction deadline', async () => { const dto = plainToInstance(CreateInspectionFindingDto, { assetId: ASSET_ID, catalogItemId: CATALOG_ID, description: ' Pérdida visible en la unión bridada. ', correctionDueOn: '2026-09-15', }); assert.deepEqual(await validate(dto), []); assert.equal(dto.description, 'Pérdida visible en la unión bridada.'); }); test('custom findings require a title and reject malformed dates', async () => { const dto = plainToInstance(CreateInspectionFindingDto, { assetId: ASSET_ID, catalogItemId: null, description: 'Observación específica', correctionDueOn: '15/09/2026', }); const errors = await validate(dto); assert.equal(errors.some((error) => error.property === 'customTitle'), true); assert.equal(errors.some((error) => error.property === 'correctionDueOn'), true); }); test('follow-up DTO keeps company response and verification planning as separate dates', async () => { const dto = plainToInstance(UpdateInspectionFindingFollowUpDto, { companyResponse: ' Se corregirá durante la parada programada. ', companyResponseReceivedOn: '2026-08-20', companyCommittedCorrectionOn: '2026-09-10', nextControlOn: '2026-09-15', }); assert.deepEqual(await validate(dto), []); assert.equal(dto.companyResponse, 'Se corregirá durante la parada programada.'); }); test('global finding filters accept the two operational work queues', async () => { const administrative = plainToInstance(ListInspectionFindingsQueryDto, { page: '1', pageSize: '25', workflow: 'COMPANY_OVERDUE', search: ' PSEnergy ', }); const operational = plainToInstance(ListInspectionFindingsQueryDto, { page: '1', pageSize: '25', workflow: 'VERIFICATION_OVERDUE', }); assert.deepEqual(await validate(administrative), []); assert.deepEqual(await validate(operational), []); assert.equal(administrative.search, 'PSEnergy'); }); test('finding close DTO requires a meaningful conclusion', async () => { const valid = plainToInstance(CloseInspectionFindingDto, { closureNotes: ' Solución verificada en campo. ' }); const invalid = plainToInstance(CloseInspectionFindingDto, { closureNotes: 'x' }); assert.deepEqual(await validate(valid), []); assert.equal(valid.closureNotes, 'Solución verificada en campo.'); assert.equal((await validate(invalid)).length > 0, true); }); test('catalog category DTO normalizes the immutable code', async () => { const dto = plainToInstance(CreateFindingCategoryDto, { code: ' seguridad_operativa ', name: ' Seguridad operativa ', sortOrder: '25', }); assert.deepEqual(await validate(dto), []); assert.equal(dto.code, 'SEGURIDAD_OPERATIVA'); assert.equal(dto.name, 'Seguridad operativa'); assert.equal(dto.sortOrder, 25); }); test('catalog item DTO accepts nullable reference fields and normalizes its code', async () => { const dto = plainToInstance(CreateFindingCatalogItemDto, { categoryId: CATALOG_ID, code: ' perdida_brida ', sourceNumber: '171', title: ' Pérdida visible en unión bridada ', legalBasis: ' ', glossary: null, importNote: ' Alta manual ', }); assert.deepEqual(await validate(dto), []); assert.equal(dto.code, 'PERDIDA_BRIDA'); assert.equal(dto.legalBasis, null); assert.equal(dto.importNote, 'Alta manual'); }); test('catalog item update rejects an empty title and invalid source number', async () => { const dto = plainToInstance(UpdateFindingCatalogItemDto, { title: ' ', sourceNumber: 0, }); const errors = await validate(dto); assert.equal(errors.some((error) => error.property === 'title'), true); assert.equal(errors.some((error) => error.property === 'sourceNumber'), true); });