open-multi-agent/tests/dashboard-render.test.ts

93 lines
3.1 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { renderTeamRunDashboard } from '../src/dashboard/render-team-run-dashboard.js'
describe('renderTeamRunDashboard', () => {
it('does not embed unescaped script terminators in the JSON payload and keeps XSS payloads out of HTML markup', () => {
const malicious = '"</script><img src=x onerror=alert(1)>"'
const html = renderTeamRunDashboard({
success: true,
goal: 'safe-goal',
tasks: [
{
id: 't1',
title: malicious,
status: 'pending',
dependsOn: [],
},
],
agentResults: new Map(),
totalTokenUsage: { input_tokens: 0, output_tokens: 0 },
})
const dataOpen = 'id="oma-data">'
const start = html.indexOf(dataOpen)
expect(start).toBeGreaterThan(-1)
const contentStart = start + dataOpen.length
const end = html.indexOf('</script>', contentStart)
expect(end).toBeGreaterThan(contentStart)
const jsonSlice = html.slice(contentStart, end)
expect(jsonSlice.toLowerCase()).not.toContain('</script')
const parsed = JSON.parse(jsonSlice) as { tasks: { title: string }[] }
expect(parsed.tasks[0]!.title).toBe(malicious)
const beforeData = html.slice(0, start)
expect(beforeData).not.toContain(malicious)
expect(beforeData.toLowerCase()).not.toMatch(/\sonerror\s*=/)
})
it('keeps task description text in JSON payload', () => {
const description = 'danger: </script><svg onload=alert(1)>'
const html = renderTeamRunDashboard({
success: true,
goal: 'safe-goal',
tasks: [
{
id: 't1',
title: 'task',
description,
status: 'pending',
dependsOn: [],
} as { id: string; title: string; description: string; status: 'pending'; dependsOn: string[] },
],
agentResults: new Map(),
totalTokenUsage: { input_tokens: 0, output_tokens: 0 },
})
const start = html.indexOf('id="oma-data">')
const contentStart = start + 'id="oma-data">'.length
const end = html.indexOf('</script>', contentStart)
const parsed = JSON.parse(html.slice(contentStart, end)) as {
tasks: Array<{ description?: string }>
}
expect(parsed.tasks[0]!.description).toBe(description)
})
it('keeps task result text in JSON payload', () => {
const result = 'final output </script><img src=x onerror=alert(1)>'
const html = renderTeamRunDashboard({
success: true,
goal: 'safe-goal',
tasks: [
{
id: 't1',
title: 'task',
result,
status: 'completed',
dependsOn: [],
} as { id: string; title: string; result: string; status: 'completed'; dependsOn: string[] },
],
agentResults: new Map(),
totalTokenUsage: { input_tokens: 0, output_tokens: 0 },
})
const start = html.indexOf('id="oma-data">')
const contentStart = start + 'id="oma-data">'.length
const end = html.indexOf('</script>', contentStart)
const parsed = JSON.parse(html.slice(contentStart, end)) as {
tasks: Array<{ result?: string }>
}
expect(parsed.tasks[0]!.result).toBe(result)
})
})