124 lines
4.4 KiB
TypeScript
124 lines
4.4 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
|
import { parseSoapXml, extractCwmpMessage, buildSoapEnvelope } from '../../../app/protocol/soap.js'
|
|
|
|
describe('parseSoapXml', () => {
|
|
it('parses a basic Inform SOAP envelope', () => {
|
|
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
|
|
<soap-env:Header>
|
|
<cwmp:ID soap-env:mustUnderstand="1">0001</cwmp:ID>
|
|
</soap-env:Header>
|
|
<soap-env:Body>
|
|
<cwmp:Inform>
|
|
<DeviceId><Manufacturer>Test</Manufacturer></DeviceId>
|
|
</cwmp:Inform>
|
|
</soap-env:Body>
|
|
</soap-env:Envelope>`
|
|
const result = parseSoapXml(xml)
|
|
expect(result.header.id).toBe('0001')
|
|
expect(result.body).toBeDefined()
|
|
expect(result.cwmpVersion).toBe('1.0')
|
|
})
|
|
|
|
it('parses soapenv prefix variant', () => {
|
|
const xml = `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cwmp="urn:dslforum-org:cwmp-1-0">
|
|
<soapenv:Header><cwmp:ID soapenv:mustUnderstand="1">42</cwmp:ID></soapenv:Header>
|
|
<soapenv:Body><cwmp:InformResponse><MaxEnvelopes>1</MaxEnvelopes></cwmp:InformResponse></soapenv:Body>
|
|
</soapenv:Envelope>`
|
|
const result = parseSoapXml(xml)
|
|
expect(String(result.header.id)).toBe('42')
|
|
})
|
|
|
|
it('handles missing header gracefully', () => {
|
|
const xml = `<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
|
|
<soap-env:Body><cwmp:GetParameterValuesResponse xmlns:cwmp="urn:dslforum-org:cwmp-1-0"></cwmp:GetParameterValuesResponse></soap-env:Body>
|
|
</soap-env:Envelope>`
|
|
const result = parseSoapXml(xml)
|
|
expect(result.header.id).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('extractCwmpMessage', () => {
|
|
it('extracts Inform message', () => {
|
|
const body = { 'cwmp:Inform': { DeviceId: { Manufacturer: 'Test' } } }
|
|
const msg = extractCwmpMessage(body)
|
|
expect(msg).not.toBeNull()
|
|
expect(msg!.type).toBe('Inform')
|
|
expect(msg!.data.DeviceId.Manufacturer).toBe('Test')
|
|
})
|
|
|
|
it('extracts GetParameterValuesResponse', () => {
|
|
const body = { 'cwmp:GetParameterValuesResponse': { ParameterList: [] } }
|
|
const msg = extractCwmpMessage(body)
|
|
expect(msg!.type).toBe('GetParameterValuesResponse')
|
|
})
|
|
|
|
it('returns null for empty body', () => {
|
|
expect(extractCwmpMessage({})).toBeNull()
|
|
})
|
|
|
|
it('returns null for non-cwmp keys', () => {
|
|
expect(extractCwmpMessage({ 'other:Thing': {} })).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('buildSoapEnvelope', () => {
|
|
it('builds valid XML envelope', () => {
|
|
const xml = buildSoapEnvelope('id-123', '<cwmp:Test/>')
|
|
expect(xml).toContain('soap-env:Envelope')
|
|
expect(xml).toContain('id-123')
|
|
expect(xml).toContain('<cwmp:Test/>')
|
|
})
|
|
|
|
it('builds envelope without id', () => {
|
|
const xml = buildSoapEnvelope(undefined, '<cwmp:Reboot/>')
|
|
expect(xml).toContain('<cwmp:Reboot/>')
|
|
})
|
|
})
|
|
|
|
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')
|
|
})
|
|
|
|
it('detects bare Fault as Fault message', () => {
|
|
const body = { Fault: { FaultCode: '9002', FaultString: 'Internal error' } }
|
|
const msg = extractCwmpMessage(body)
|
|
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!.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!.type).toBe('GetParameterValuesResponse')
|
|
})
|
|
|
|
it('returns null when body has no cwmp: keys and no Fault', () => {
|
|
expect(extractCwmpMessage({ 'other:Something': {} })).toBeNull()
|
|
})
|
|
})
|
|
|