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 root = (path: string) => readFileSync(resolve(process.cwd(), '..', path), 'utf8'); test('F6.18 reuses one auditable Function catalog for Installation and Subinstallation', () => { const module = api('src/asset-master/asset-master.module.ts'); const service = api('src/asset-master/inventory-function.service.ts'); const migration = api('src/database/migrations/1790146200000-f6-18-function-catalog.ts'); const app = root('web-v2/src/app/App.tsx'); const nav = root('web-v2/src/layout/AppLayout.tsx'); assert.match(module, /InventoryFunctionController/); assert.match(service, /value === 'instalacion' \|\| value === 'subinstalacion'/); assert.match(service, /newFunctionName/); assert.match(service, /FIELD_\$\{slug\}_\$\{digest\}/); assert.match(migration, /definition\.code='campo_funcion'/); assert.match(migration, /inventory_function_assignments/); assert.match(migration, /is_active=false,is_required=false/); assert.match(app, /admin\/inventory-functions/); assert.match(nav, /Catálogo de funciones/); }); test('F6.18 makes habitual name mandatory and technical name optional for technical Inventory', () => { const createDto = api('src/asset-master/dto/create-asset.dto.ts'); const fieldDto = api('src/inspection-visits/dto/create-field-inventory.dto.ts'); const service = api('src/asset-master/assets.service.ts'); const editor = root('web-v2/src/pages/AssetEditorPage.tsx'); const mobile = root('android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt'); assert.match(createDto, /name\?: string \| null/); assert.match(fieldDto, /name\?: string \| null/); assert.match(service, /ASSET_COMMON_NAME_REQUIRED/); assert.match(service, /technicalName \|\| habitualName/); assert.match(editor, /Nombre habitual/); assert.match(editor, /Nombre técnico opcional<\/em>/); assert.match(mobile, /Nombre habitual \*/); assert.match(mobile, /Nombre técnico \(opcional\)/); }); test('F6.18 APK can select a catalog Function or add Otro and keeps it in the offline queue', () => { const data = root('android-app/app/src/main/java/com/korexlabs/dhinspeccion/data/DhMobile.kt'); const mobile = root('android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/ModernVisitRoot.kt'); const queue = root('android-app/app/src/main/java/com/korexlabs/dhinspeccion/data/offline/OfflineQueue.kt'); assert.match(data, /@GET\("inventory-functions"\)/); assert.match(data, /val functionId: String\? = null/); assert.match(data, /val newFunctionName: String\? = null/); assert.match(mobile, /Otro · agregar función/); assert.match(mobile, /Nueva función \*/); assert.match(queue, /put\("functionId", request\.functionId\)/); assert.match(queue, /put\("newFunctionName", request\.newFunctionName\)/); }); test('F6.18 freezes every completed technical datum except Inventory description into the Acta', () => { const closing = api('src/inspection-closing/inspection-closing.service.ts'); const pdf = api('src/inspection-reports/inspection-act-pdf-builder.ts'); assert.match(closing, /inventory_function_assignments/); assert.match(closing, /AS "function"/); assert.match(closing, /AS attributes/); assert.match(closing, /definition\.code<>'campo_funcion'/); assert.doesNotMatch(closing, /selected\.description/); assert.match(pdf, /label\('Nombre habitual'/); assert.match(pdf, /label\('Nombre técnico'/); assert.match(pdf, /label\('Código DH'/); assert.match(pdf, /label\('Función'/); assert.match(pdf, /technicalAttributes/); assert.doesNotMatch(pdf, /inventory\.description/); });