- Device domain: updateFromValues, organizeParameters, identifier - BaseModel: full CRUD mock tests - DeviceModel: all methods mocked - Other models: collectionName verification - MainStateMachine: start, handleResponse, state transitions - ConfigurationEvaluationState: init, GPN flow, GPN-unsupported skip - MongodbProvider: getMongoDb guard - device_utils: hash determinism - vitest.config.ts: coverage scope (excludes HTTP layer) - 492 tests passing, 78% line coverage
134 lines
4.5 KiB
TypeScript
134 lines
4.5 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { Device } from '../../../app/domain/device/device.js'
|
|
import { DeviceId } from '../../../app/domain/device/device_id.js'
|
|
import { DeviceParameter, DeviceProperty } from '../../../app/domain/device/device_parameter.js'
|
|
|
|
function makeDevice() {
|
|
return new Device(new DeviceId('Sagemcom', 'F8B7FF', 'Livebox 6', 'SN001'))
|
|
}
|
|
|
|
describe('Device', () => {
|
|
it('creates with deviceId', () => {
|
|
const d = makeDevice()
|
|
expect(d.deviceId.manufacturer).toBe('Sagemcom')
|
|
expect(d.gpnStatus).toBe('unknown')
|
|
expect(d.dataModel).toBe('unknown')
|
|
})
|
|
|
|
it('setProperty and getProperty', () => {
|
|
const d = makeDevice()
|
|
d.setProperty(new DeviceProperty('Device.Info.SW', '1.0'))
|
|
expect(d.getProperty('Device.Info.SW')).toBeDefined()
|
|
expect(d.getProperty('Device.Info.SW')!.value).toBe('1.0')
|
|
})
|
|
|
|
it('setParameter and getParameter', () => {
|
|
const d = makeDevice()
|
|
d.setParameter(new DeviceParameter('Device.X', '42'))
|
|
expect(d.getParameter('Device.X')).toBeDefined()
|
|
expect(d.getParameter('Device.X')!.value).toBe('42')
|
|
})
|
|
|
|
it('getProperties returns all properties', () => {
|
|
const d = makeDevice()
|
|
d.setProperty(new DeviceProperty('A', '1'))
|
|
d.setProperty(new DeviceProperty('B', '2'))
|
|
expect(d.getProperties()).toHaveLength(2)
|
|
})
|
|
|
|
it('getParameters returns all parameters', () => {
|
|
const d = makeDevice()
|
|
d.setParameter(new DeviceParameter('X', '1'))
|
|
expect(d.getParameters()).toHaveLength(1)
|
|
})
|
|
|
|
it('setGpnStatus updates gpnStatus', () => {
|
|
const d = makeDevice()
|
|
d.setGpnStatus('supported')
|
|
expect(d.gpnStatus).toBe('supported')
|
|
})
|
|
|
|
it('setDataModel updates dataModel', () => {
|
|
const d = makeDevice()
|
|
d.setDataModel('tr-181')
|
|
expect(d.dataModel).toBe('tr-181')
|
|
})
|
|
|
|
it('updateLastSeen does not crash', () => {
|
|
const d = makeDevice()
|
|
expect(() => d.updateLastSeen()).not.toThrow()
|
|
})
|
|
|
|
it('updateFromValues adds new properties from Inform ParameterValueStruct', () => {
|
|
const d = makeDevice()
|
|
d.updateFromValues([
|
|
{ Name: 'Device.Info.SW', Value: { _: '3.0', $: { Type: 'xsd:string' } } },
|
|
{ Name: 'Device.Info.HW', Value: { _: '1.0', $: { Type: 'xsd:string' } } },
|
|
])
|
|
expect(d.getProperties().length).toBeGreaterThanOrEqual(2)
|
|
})
|
|
|
|
it('toSnapshot returns serializable object', () => {
|
|
const d = makeDevice()
|
|
d.setProperty(new DeviceProperty('A', '1'))
|
|
d.setParameter(new DeviceParameter('X', '2'))
|
|
d.setGpnStatus('supported')
|
|
d.setDataModel('tr-181')
|
|
const snap = d.toSnapshot()
|
|
expect(snap.identifier).toBeDefined()
|
|
expect(snap.deviceId).toBeDefined()
|
|
expect(snap.properties).toHaveLength(1)
|
|
expect(snap.parameters).toHaveLength(1)
|
|
expect(snap.gpnStatus).toBe('supported')
|
|
expect(snap.dataModel).toBe('tr-181')
|
|
})
|
|
|
|
it('organizeParameters classifies properties vs parameters from GPN response', () => {
|
|
const d = makeDevice()
|
|
// Simulate a GPN response
|
|
d.setProperty(new DeviceProperty('Device.ManagementServer.PeriodicInformInterval', '60'))
|
|
d.setProperty(new DeviceProperty('Device.DeviceInfo.Manufacturer', 'Sagemcom'))
|
|
d.organizeParameters(
|
|
{
|
|
ParameterList: {
|
|
ParameterInfoStruct: [
|
|
{ Name: 'Device.ManagementServer.PeriodicInformInterval', Writable: '1' },
|
|
{ Name: 'Device.DeviceInfo.Manufacturer', Writable: '0' },
|
|
],
|
|
},
|
|
},
|
|
new Date()
|
|
)
|
|
// Writable=1 → parameter, Writable=0 → property
|
|
expect(d.getParameter('Device.ManagementServer.PeriodicInformInterval')).toBeDefined()
|
|
// Manufacturer stays as property (Writable=0)
|
|
expect(d.getProperty('Device.DeviceInfo.Manufacturer')).toBeDefined()
|
|
})
|
|
|
|
it('setTmpParamValues stores values', () => {
|
|
const d = makeDevice()
|
|
d.setTmpParamValues([{ Name: 'X', Value: { _: 'v' } }])
|
|
// No crash — internal state
|
|
})
|
|
|
|
it('identifier is computed from deviceId', () => {
|
|
const d = makeDevice()
|
|
expect(d.identifier).toBeDefined()
|
|
expect(d.identifier!.length).toBe(24)
|
|
})
|
|
|
|
it('updateFromValues handles empty array', () => {
|
|
const d = makeDevice()
|
|
d.updateFromValues([])
|
|
expect(d.getProperties()).toHaveLength(0)
|
|
})
|
|
|
|
it('updateFromValues updates existing property value', () => {
|
|
const d = makeDevice()
|
|
d.setProperty(new DeviceProperty('Device.Info.SW', 'old'))
|
|
d.updateFromValues([{ Name: 'Device.Info.SW', Value: { _: 'new', $: { Type: 'xsd:string' } } }])
|
|
const prop = d.getProperty('Device.Info.SW')
|
|
expect(prop!.value).toBe('new')
|
|
})
|
|
})
|