import { describe, it, expect, vi, beforeEach } from 'vitest' // Mock logger vi.mock('@adonisjs/core/services/logger', () => ({ default: { info: vi.fn(), debug: vi.fn(), warn: vi.fn(), error: vi.fn(), }, })) // Mock DeviceModel vi.mock('../../../../app/models/device.js', () => ({ default: { createOrUpdate: vi.fn().mockResolvedValue({}), findByDeviceId: vi.fn().mockResolvedValue(null), updateOne: vi.fn().mockResolvedValue({}), }, })) // Mock CommandModel vi.mock('../../../../app/models/command.js', () => ({ default: { getCollection: vi.fn().mockReturnValue({ find: vi.fn().mockReturnValue({ sort: vi.fn().mockReturnValue({ toArray: vi.fn().mockResolvedValue([]) }) }), countDocuments: vi.fn().mockResolvedValue(0), }), updateCommand: vi.fn().mockResolvedValue({}), }, })) // Mock ConfigurationModel vi.mock('#models/configuration', () => ({ default: { find: vi.fn().mockResolvedValue([]), findByIdentifier: vi.fn().mockResolvedValue(null), }, })) // Mock firmware catalog service vi.mock('../../../../app/services/firmware_catalog_service.js', () => ({ default: class { async resolveUpgradePath() { return [] } }, FirmwareCatalogService: class { async resolveUpgradePath() { return [] } }, })) // Mock parameter_writability vi.mock('../../../../app/services/parameter_writability.js', () => ({ reclassifyDeviceFromCatalog: vi.fn(), })) import { ConfigurationEvaluationState, ComplianceUpdateState } from '../../../../app/services/cwmp/configuration_evaluation_state.js' import { Device } from '../../../../app/domain/device/device.js' import { DeviceId } from '../../../../app/domain/device/device_id.js' import { DeviceProperty } from '../../../../app/domain/device/device_parameter.js' import { CWMPTaskQueue } from '../../../../app/services/cwmp/task_queue.js' import { DeviceActionExecutor } from '../../../../app/services/cwmp/device_action_executor.js' import { ParameterType } from '../../../../app/domain/shared/types.js' import { buildProvisioningCode } from '../../../../app/utils/provisioning_code.js' function makeDevice(): Device { const device = new Device(new DeviceId('Sagemcom', 'F8B7FF', 'Livebox 4', 'LB4-TEST-001')) device.setDataModel('tr-181') device.setGpnStatus('unsupported') return device } function makeContext(device: Device) { const taskQueue = new CWMPTaskQueue() return { device, session: 'test-session', taskQueue, services: { deviceAction: new DeviceActionExecutor(taskQueue), }, } } describe('ConfigurationEvaluationState — skip inventory when already compliant', () => { beforeEach(() => { vi.clearAllMocks() }) it('skips inventory when isAlreadyCompliant is true (no matching config)', async () => { const device = makeDevice() const context = makeContext(device) const state = new ConfigurationEvaluationState() const result = await state.handle(context as any) // With no configs in DB, evaluate returns isAlreadyCompliant: true // State should transition forward without sending any GPN/GPV // (no inventory, no diffs) expect(result.response).toBeFalsy() expect(result.nextState || result.isComplete).toBeTruthy() }) }) describe('ComplianceUpdateState — skip provCode SPV when matching', () => { beforeEach(() => { vi.clearAllMocks() }) it('skips SPV when device already has matching provisioning code', async () => { const device = makeDevice() const mockConfig = { identifier: 'TestConfig', version: '1.0', desiredParameters: [], firmwareTarget: null } const expectedProvCode = buildProvisioningCode(mockConfig as any) // Set the device's ProvisioningCode to match what buildProvisioningCode produces device.setProperty(new DeviceProperty( 'Device.DeviceInfo.ProvisioningCode', expectedProvCode, ParameterType.STRING )) const context = makeContext(device) const mockEngineResult = { configuration: mockConfig, inventoryPaths: [], parameterDiffs: [], firmwareMigrationPath: [], isAlreadyCompliant: true, skipFirmware: false, } const state = new ComplianceUpdateState(mockEngineResult as any) const result = await state.handle(context as any) // Should NOT produce a response (no SPV sent) // Should transition to ExecutingCommandsState expect(result.response).toBeFalsy() expect(result.nextState).toBeDefined() }) })