47 lines
2.8 KiB
TypeScript
47 lines
2.8 KiB
TypeScript
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { describe, expect, it } from 'vitest';
|
|
import { AiOverviewPanel, AiOverviewResultView } from '../../src/compliance/ui/AiOverviewPanel';
|
|
import type { AiOverviewResponse, AiOverviewRun } from '../../src/compliance/ai-overview';
|
|
import { validAiOverviewResult } from './ai-overview-fixtures';
|
|
import { readFileSync } from 'node:fs';
|
|
|
|
describe('Client Info AI Overview', () => {
|
|
it('renders every section of the validated output contract as text', () => {
|
|
const html = renderToStaticMarkup(<AiOverviewResultView
|
|
result={validAiOverviewResult()} generatedAt="2026-09-14T08:00:00.000Z" model="work-model" />);
|
|
for (const heading of ['Executive summary', 'Environment overview', 'Security themes', 'Priorities',
|
|
'Five-phase roadmap', 'Coverage gaps', 'Quick wins', 'Questions', 'Assumptions']) {
|
|
expect(html).toContain(heading);
|
|
}
|
|
expect(html).toContain('Synthetic executive summary.');
|
|
expect(html).toContain('RULE-1');
|
|
expect(html).toContain('Advisory AI output');
|
|
});
|
|
|
|
it('shows the failed regeneration and the previous saved overview together', () => {
|
|
const base: AiOverviewRun = {
|
|
version: 1, id: 'run-1', projectId: 'project-1', scopeKey: 'scope-1', assessmentIds: [], scanRunIds: [],
|
|
idempotencyKey: 'request-1', status: 'succeeded', inputHash: 'a'.repeat(64), promptVersion: '1',
|
|
outputSchemaVersion: 1, model: 'work-model', createdAt: '2026-09-14T08:00:00.000Z',
|
|
updatedAt: '2026-09-14T08:00:00.000Z', callCount: 1, result: validAiOverviewResult()
|
|
};
|
|
const response: AiOverviewResponse = {
|
|
version: 1, projectId: 'project-1', scope: { assessmentIds: [], scanRunIds: [] },
|
|
generationEnabled: true, state: 'failed', stale: false,
|
|
run: { ...base, id: 'run-2', status: 'failed', result: undefined, errorMessage: 'Generation failed safely.' },
|
|
previousSuccessfulRun: base
|
|
};
|
|
const html = renderToStaticMarkup(<AiOverviewPanel controller={{ available: true, response, loading: false, generating: false, generate: async () => {} }} />);
|
|
expect(html).toContain('Generation failed safely.');
|
|
expect(html).toContain('Synthetic executive summary.');
|
|
expect(html).toContain('previous saved overview');
|
|
});
|
|
|
|
it('adds the AI tab beside the Client Info overview', () => {
|
|
const dashboard = readFileSync(new URL('../../src/features/dashboard/DashboardPanel.tsx', import.meta.url), 'utf8');
|
|
expect(dashboard).toContain("[{ id: 'overview', label: 'Overview', content:");
|
|
// The AI tab is the last Client Info tab and mounts only while selected.
|
|
expect(dashboard).toContain("...(showAiOverview ? [{ id: 'ai', label: 'AI Overview', content: <AiOverviewPanel controller={aiOverview} />, lazy: true }] : [])]} />");
|
|
});
|
|
});
|