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 = ` 0001 Test ` 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 = ` 42 1 ` const result = parseSoapXml(xml) expect(String(result.header.id)).toBe('42') }) it('handles missing header gracefully', () => { const xml = ` ` 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', '') expect(xml).toContain('soap-env:Envelope') expect(xml).toContain('id-123') expect(xml).toContain('') }) it('builds envelope without id', () => { const xml = buildSoapEnvelope(undefined, '') expect(xml).toContain('') }) }) 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() }) })