feat: TR-069 CWMP state machine hardening + exchange viewer improvements
- TR-069 CWMP state machine hardening (14 phases): shared event utility, multi-event routing, GPN circuit breaker, IdleState GPN guard, expanded GPN fault codes, CriticalReadsState, ConfigEval GPN guard, task queue race condition fix, explicit error handling, terminal states (OperationalState/PartialOperationalState), consolidated reclassify, crash pattern detection, removed enqueueImmediate, state flow wiring - Fix SOAP Fault not processed by state machine (soap-env:Fault detection) - Fix GPN circuit breaker not persisting after session drops - Fix CriticalReadsState GPV response parsing (xsi:type normalization) - Fix CriticalReadsState not processing GPV response values - Skip SPV when device is already compliant (ProvisioningCode check) - Add Device.DeviceInfo.ModelName to critical reads GPV - Fix TypeError on DeviceDetail parameters view (null guards) - Log empty 204 responses in exchange trace UI - TR-181 catalog: type corrections and new entries (+6640 lines) - SequenceViewer: replace session-nav buttons with compact dropdown select - SequenceViewer: fix CPE/ACS lifeline headers wrapping to 2 lines - Add 20 unit tests for state machine fixes (SOAP Fault, GPN circuit breaker, CriticalReads, stale session, ConfigEval/ComplianceUpdate skips) Generated with [Continue](https://continue.dev) Co-Authored-By: Continue <noreply@continue.dev>
This commit is contained in:
1 parent
dabe15839d
commit
aad93911e4
35 files changed
+8593
-4497
No files matched your search
@@ -0,0 +1,64 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { extractCwmpMessage } from '../../../app/protocol/soap.js'
|
||||
|
||||
describe('extractCwmpMessage — SOAP Fault detection', () => {
|
||||
it('detects soap-env:Fault as Fault message', () => {
|
||||
const body = {
|
||||
'soap-env:Fault': {
|
||||
faultcode: 'Client',
|
||||
faultstring: 'CWMP fault',
|
||||
detail: { 'cwmp:Fault': { FaultCode: '9001', FaultString: 'Request denied' } },
|
||||
},
|
||||
}
|
||||
const msg = extractCwmpMessage(body)
|
||||
expect(msg).not.toBeNull()
|
||||
expect(msg!.type).toBe('Fault')
|
||||
expect(msg!.data.faultcode).toBe('Client')
|
||||
})
|
||||
|
||||
it('detects SOAP-ENV:Fault as Fault message', () => {
|
||||
const body = {
|
||||
'SOAP-ENV:Fault': {
|
||||
faultcode: 'Server',
|
||||
faultstring: 'Internal error',
|
||||
},
|
||||
}
|
||||
const msg = extractCwmpMessage(body)
|
||||
expect(msg).not.toBeNull()
|
||||
expect(msg!.type).toBe('Fault')
|
||||
expect(msg!.data.faultcode).toBe('Server')
|
||||
})
|
||||
|
||||
it('detects bare Fault as Fault message', () => {
|
||||
const body = {
|
||||
Fault: { FaultCode: '9002', FaultString: 'Internal error' },
|
||||
}
|
||||
const msg = extractCwmpMessage(body)
|
||||
expect(msg).not.toBeNull()
|
||||
expect(msg!.type).toBe('Fault')
|
||||
})
|
||||
|
||||
it('detects soapenv:Fault as Fault message', () => {
|
||||
const body = {
|
||||
'soapenv:Fault': { faultcode: 'Client', faultstring: 'Fault' },
|
||||
}
|
||||
const msg = extractCwmpMessage(body)
|
||||
expect(msg).not.toBeNull()
|
||||
expect(msg!.type).toBe('Fault')
|
||||
})
|
||||
|
||||
it('prefers cwmp: prefixed keys over Fault detection', () => {
|
||||
const body = {
|
||||
'cwmp:GetParameterValuesResponse': { ParameterList: [] },
|
||||
'soap-env:Fault': { faultcode: 'Client' },
|
||||
}
|
||||
const msg = extractCwmpMessage(body)
|
||||
expect(msg).not.toBeNull()
|
||||
expect(msg!.type).toBe('GetParameterValuesResponse')
|
||||
})
|
||||
|
||||
it('returns null when body has no cwmp: keys and no Fault', () => {
|
||||
const body = { 'other:Something': {} }
|
||||
expect(extractCwmpMessage(body)).toBeNull()
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user