From b23d7736c0b74755aac3517bf880a47427cc5f6c Mon Sep 17 00:00:00 2001 From: enlineawork Date: Thu, 10 Sep 2026 21:34:55 -0300 Subject: [PATCH] test(api): cover immutable context and scoped preventive inventory --- ...f6-2-inspection-context-preventive.test.ts | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 api-v3/test/unit/f6-2-inspection-context-preventive.test.ts diff --git a/api-v3/test/unit/f6-2-inspection-context-preventive.test.ts b/api-v3/test/unit/f6-2-inspection-context-preventive.test.ts new file mode 100644 index 0000000..4d26bfa --- /dev/null +++ b/api-v3/test/unit/f6-2-inspection-context-preventive.test.ts @@ -0,0 +1,40 @@ +import assert from 'node:assert/strict'; +import { readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import test from 'node:test'; + +const api = (path: string) => readFileSync(resolve(process.cwd(), path), 'utf8'); +const web = (path: string) => readFileSync(resolve(process.cwd(), '..', 'web-v2', path), 'utf8'); + +test('F6.2 protects the frozen Inspection context at database level', () => { + const migration = api('src/database/migrations/1790098200000-f6-2-freeze-inspection-context.ts'); + + assert.match(migration, /prevent_inspection_context_mutation/); + assert.match(migration, /NEW\.operational_area_id IS DISTINCT FROM OLD\.operational_area_id/); + assert.match(migration, /NEW\.scope_asset_id IS DISTINCT FROM OLD\.scope_asset_id/); + assert.match(migration, /NEW\.operator_company_id IS DISTINCT FROM OLD\.operator_company_id/); + assert.match(migration, /BEFORE UPDATE OF operational_area_id, scope_asset_id, operator_company_id/); +}); + +test('F6.2 preventive candidates are descendants of the frozen Yacimiento only', () => { + const service = api('src/inspection-visits/inspection-preventive-candidates.service.ts'); + const controller = api('src/inspection-visits/inspection-preventive-candidates.controller.ts'); + + assert.match(service, /COALESCE\(visit\.scope_asset_id, visit\.operational_area_id\) AS "scopeAssetId"/); + assert.match(service, /WITH RECURSIVE scope_tree AS/); + assert.match(service, /child\.parent_id/); + assert.match(service, /asset\.operational_area_id = \$3::uuid/); + assert.match(service, /lower\(asset_type\.code\) IN \('instalacion', 'subinstalacion'\)/); + assert.match(service, /NOT EXISTS \([\s\S]*inspection_visit_assets linked/); + assert.match(controller, /:id\/preventive-candidates/); +}); + +test('F6.2 WEB uses the server-scoped preventive selector instead of the mutable Area form', () => { + const page = web('src/pages/InspectionVisitEditorF4Page.tsx'); + const apiClient = web('src/features/inspections/preventiveCandidatesApi.ts'); + + assert.match(page, /listInspectionPreventiveCandidates\(id, assetSearch\)/); + assert.doesNotMatch(page, /listAssets\(\{[\s\S]{0,220}operationalAreaId: form\.operationalAreaId/); + assert.match(page, /Sólo se muestran Instalaciones y Subinstalaciones pertenecientes al Yacimiento/); + assert.match(apiClient, /inspection-visits\/\$\{visitId\}\/preventive-candidates/); +});