import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import test from 'node:test'; function source(path: string) { return readFileSync(resolve(process.cwd(), path), 'utf8'); } test('F6.1 allows direct findings only on Yacimiento, Instalacion and Subinstalacion', () => { const findings = source('src/inspection-visits/field-findings.service.ts'); assert.match(findings, /\['yacimiento', 'instalacion', 'subinstalacion'\]\.includes\(assetTypeCode\)/); assert.match(findings, /FIELD_FINDING_TARGET_LEVEL_INVALID/); assert.match(findings, /Los Hallazgos pueden registrarse sobre Yacimiento, Instalación o Subinstalación/); assert.match(findings, /assetTypeCode !== 'yacimiento' && !row\.inventoryFamilyId/); assert.match(findings, /FIELD_FINDING_FAMILY_REQUIRED/); }); test('F6.1 uses contextual type catalog for Yacimiento and keeps OTROS/add-another everywhere', () => { const findings = source('src/inspection-visits/field-findings.service.ts'); const resolver = source('src/inspection-findings/f3-finding-catalog-resolver.service.ts'); const catalog = source('src/inspection-findings/finding-catalog.service.ts'); const androidFinding = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/FieldFindingScreen.kt'); assert.match(findings, /canAddAnother: true/); assert.match(resolver, /typeCode\.toLowerCase\(\) === 'yacimiento'/); assert.match(resolver, /contextualCatalog\.listApplicableForAsset\(assetId, query\)/); assert.match(resolver, /catalogSource: 'ASSET_TYPE'/); assert.match(catalog, /finding_catalog_item_asset_types mapping/); assert.match(catalog, /finding_catalog_asset_overrides override/); assert.match(resolver, /code: 'OTHER'/); assert.match(resolver, /label: 'OTROS'/); assert.match(androidFinding, /OTROS · No está en el catálogo/); assert.match(androidFinding, /También podés registrar otro Hallazgo sobre el mismo Inventario/); }); test('F6.1 exposes mobile planning context and opens an inspection self-assigned to the current inspector', () => { const controller = source('src/inspection-visits/inspection-visits.controller.ts'); const dto = source('src/inspection-visits/dto/open-mobile-inspection.dto.ts'); assert.match(controller, /@Get\('mobile\/planning-context\/areas'\)/); assert.match(controller, /@Get\('mobile\/planning-context\/areas\/:areaId\/operators'\)/); assert.match(controller, /@Post\('mobile\/open'\)/); assert.match(controller, /@RequirePermissions\('inspections\.execute'\)/); assert.match(controller, /assertMobileInspector\(principal\)/); assert.match(controller, /leadInspectorUserId: principal\.userId/); assert.match(controller, /plannedStartAt: new Date\(\)\.toISOString\(\)/); assert.match(controller, /this\.lifecycle\.plan\(created\.id/); assert.match(controller, /this\.lifecycle\.start\(created\.id/); assert.match(dto, /operationalAreaId!: string/); assert.match(dto, /operatorCompanyId!: string/); }); test('F6.1 Android lets the inspector choose Area and current Operator and open the inspection now', () => { const client = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/data/MobileInspectionOpen.kt'); const home = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/MobileHomeScreen.kt'); const gate = source('../android-app/app/src/main/java/com/korexlabs/dhinspeccion/ui/LoginGate.kt'); assert.match(client, /inspection-visits\/mobile\/planning-context\/areas/); assert.match(client, /inspection-visits\/mobile\/open/); assert.match(home, /Abrir inspección/); assert.match(home, /Abrir inspección ahora/); assert.match(home, /Operadora vigente/); assert.match(home, /model\.openVisit\(opened\.id\)/); assert.match(gate, /else -> MobileHomeScreen\(model\)/); });