- Pluggable multi-provider architecture (ReferenceEngine) - Wassup provider implementation (HTTP GET + X_WASSUP_USER_IP) - Auto-resolve references on Inform (BOOT/BOOTSTRAP events) - References displayed in device Identity card - REST API: GET/POST references per device - Config via config/references.json - Fix event extraction for single EventStruct and numeric EventCodes - Mock Wassup provisioned by home-device-simulator on device creation
120 lines
3.9 KiB
TypeScript
120 lines
3.9 KiB
TypeScript
import { describe, it, expect, beforeEach, afterEach } from 'vitest'
|
|
import { WassupProvider } from '../../../../app/services/references/providers/wassup_provider.js'
|
|
import type { ProviderConfig } from '../../../../app/services/references/types.js'
|
|
import type { DeviceRecord } from '../../../../app/domain/device/device_record.js'
|
|
import { DeviceId } from '../../../../app/domain/device/device_id.js'
|
|
import { createServer, type Server } from 'node:http'
|
|
|
|
function makeDevice(): DeviceRecord {
|
|
return {
|
|
identifier: 'test-device-001',
|
|
deviceId: new DeviceId('TestCorp', 'AABBCC', 'TestBox', 'SERIAL001'),
|
|
properties: [],
|
|
parameters: [],
|
|
}
|
|
}
|
|
|
|
function makeConfig(overrides: Partial<ProviderConfig> = {}): ProviderConfig {
|
|
return {
|
|
name: 'wassup',
|
|
type: 'wassup',
|
|
enabled: true,
|
|
url: 'http://localhost:19876',
|
|
timeout: 2000,
|
|
trigger: ['BOOT'],
|
|
resolveBy: 'ip',
|
|
options: { service: 'KRMSCO', requestedProperties: ['sai', 'spr'] },
|
|
...overrides,
|
|
}
|
|
}
|
|
|
|
describe('WassupProvider', () => {
|
|
let server: Server
|
|
let responseBody: string
|
|
let responseStatus: number
|
|
|
|
beforeEach(() => {
|
|
responseBody = 'X_WASSUP_STATUS=OK\nX_WASSUP_SAI=123456789\nX_WASSUP_SPR=FR\n'
|
|
responseStatus = 200
|
|
|
|
server = createServer((_req, res) => {
|
|
res.writeHead(responseStatus, { 'Content-Type': 'text/plain' })
|
|
res.end(responseBody)
|
|
})
|
|
server.listen(19876)
|
|
})
|
|
|
|
afterEach(() => {
|
|
server.close()
|
|
})
|
|
|
|
it('resolves successfully with OK status', async () => {
|
|
const provider = new WassupProvider(makeConfig())
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '10.0.0.1', headers: {} })
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.status).toBe('ok')
|
|
expect(result!.provider).toBe('wassup')
|
|
expect(result!.resolvedBy).toBe('ip:10.0.0.1')
|
|
expect(result!.properties.sai).toBe('123456789')
|
|
expect(result!.properties.spr).toBe('FR')
|
|
})
|
|
|
|
it('returns unknown when user not found', async () => {
|
|
responseBody = 'X_WASSUP_STATUS=UNKNOWN_USER\nX_WASSUP_ERROR=ICS_RESULT_LDAP_ERROR\n'
|
|
|
|
const provider = new WassupProvider(makeConfig())
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '10.0.0.99', headers: {} })
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.status).toBe('unknown')
|
|
expect(result!.properties).toEqual({})
|
|
})
|
|
|
|
it('returns error on HTTP failure', async () => {
|
|
responseStatus = 500
|
|
responseBody = 'Internal Server Error'
|
|
|
|
const provider = new WassupProvider(makeConfig())
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '10.0.0.1', headers: {} })
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.status).toBe('error')
|
|
expect(result!.error).toContain('HTTP 500')
|
|
})
|
|
|
|
it('returns error on timeout', async () => {
|
|
server.close()
|
|
server = createServer((_req, res) => {
|
|
// Never respond — simulate timeout
|
|
setTimeout(() => {
|
|
res.writeHead(200)
|
|
res.end('X_WASSUP_STATUS=OK\n')
|
|
}, 5000)
|
|
})
|
|
server.listen(19876)
|
|
|
|
const provider = new WassupProvider(makeConfig({ timeout: 100 }))
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '10.0.0.1', headers: {} })
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.status).toBe('error')
|
|
expect(result!.error).toBe('Timeout')
|
|
})
|
|
|
|
it('returns null when no IP available', async () => {
|
|
const provider = new WassupProvider(makeConfig())
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '', headers: {} })
|
|
|
|
expect(result).toBeNull()
|
|
})
|
|
|
|
it('resolves by serialNumber when configured', async () => {
|
|
const provider = new WassupProvider(makeConfig({ resolveBy: 'serialNumber' }))
|
|
const result = await provider.resolve(makeDevice(), { events: [], remoteIp: '', headers: {} })
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.resolvedBy).toBe('serialNumber:SERIAL001')
|
|
})
|
|
})
|