103 lines
2.9 KiB
TypeScript
103 lines
2.9 KiB
TypeScript
import { VaMessagingService, VaMessage } from './va-messaging.service'
|
|
|
|
// Sample message taken from the official SAS DDC docs (brush column included).
|
|
const SAMPLE = {
|
|
version: '1',
|
|
resultName: 'dd40',
|
|
rowCount: 3,
|
|
availableRowCount: 3,
|
|
data: [
|
|
['Finch', 95000.0, 0.4285],
|
|
['Jones', 26000.0, 0.0],
|
|
['Smith', 108000.0, 0.5]
|
|
],
|
|
columns: [
|
|
{ name: 'bi184', label: 'dealer', type: 'string' },
|
|
{
|
|
name: 'bi258',
|
|
label: 'sales',
|
|
type: 'number',
|
|
usage: 'quantitative',
|
|
aggregation: 'sum'
|
|
},
|
|
{ name: 'ri1', type: 'number', usage: 'brush' }
|
|
]
|
|
}
|
|
|
|
describe('VaMessagingService', () => {
|
|
let service: VaMessagingService
|
|
|
|
beforeEach(() => {
|
|
service = new VaMessagingService()
|
|
})
|
|
|
|
describe('parseMessage', () => {
|
|
it('parses a valid DDC message and defaults parameters to []', () => {
|
|
const msg = service.parseMessage({ data: SAMPLE } as MessageEvent)
|
|
expect(msg).not.toBeNull()
|
|
expect(msg!.resultName).toBe('dd40')
|
|
expect(msg!.rowCount).toBe(3)
|
|
expect(msg!.parameters).toEqual([])
|
|
})
|
|
|
|
it('returns null for unrelated / malformed messages', () => {
|
|
expect(service.parseMessage({ data: null } as MessageEvent)).toBeNull()
|
|
expect(
|
|
service.parseMessage({ data: 'hello' } as unknown as MessageEvent)
|
|
).toBeNull()
|
|
expect(
|
|
service.parseMessage({ data: { columns: [] } } as MessageEvent)
|
|
).toBeNull()
|
|
})
|
|
})
|
|
|
|
describe('dataColumns', () => {
|
|
it('excludes brush columns and keeps original indices', () => {
|
|
const msg = service.parseMessage({ data: SAMPLE } as MessageEvent)!
|
|
const cols = service.dataColumns(msg)
|
|
expect(cols.map((c) => c.column.name)).toEqual(['bi184', 'bi258'])
|
|
expect(cols.map((c) => c.index)).toEqual([0, 1])
|
|
})
|
|
})
|
|
|
|
describe('onData', () => {
|
|
const sameOrigin = window.location.origin
|
|
|
|
it('invokes the callback for valid messages and unsubscribes cleanly', () => {
|
|
const received: VaMessage[] = []
|
|
const off = service.onData((m) => received.push(m))
|
|
|
|
window.dispatchEvent(
|
|
new MessageEvent('message', { data: SAMPLE, origin: sameOrigin })
|
|
)
|
|
expect(received.length).toBe(1)
|
|
expect(received[0].resultName).toBe('dd40')
|
|
|
|
// unrelated traffic is ignored
|
|
window.dispatchEvent(
|
|
new MessageEvent('message', { data: { foo: 1 }, origin: sameOrigin })
|
|
)
|
|
expect(received.length).toBe(1)
|
|
|
|
off()
|
|
window.dispatchEvent(
|
|
new MessageEvent('message', { data: SAMPLE, origin: sameOrigin })
|
|
)
|
|
expect(received.length).toBe(1)
|
|
})
|
|
|
|
it('rejects messages from an untrusted origin', () => {
|
|
const received: VaMessage[] = []
|
|
service.onData((m) => received.push(m))
|
|
|
|
window.dispatchEvent(
|
|
new MessageEvent('message', {
|
|
data: SAMPLE,
|
|
origin: 'https://evil.example.com'
|
|
})
|
|
)
|
|
expect(received.length).toBe(0)
|
|
})
|
|
})
|
|
})
|