Files
breakpilot-compliance/admin-compliance/lib/sdk/__tests__/advisor-copy.test.ts
T
Benjamin Admin e8ea179228 feat(advisor): topic threads, per-question delete/copy, fullscreen
Adds case management to the Compliance Advisor widget.

- topic threads: cases group into threads; the left menu shows each
  thread's first question as the Thema with expandable follow-ups.
  Send = follow-up to the active thread (carries the thread's prior Q&A
  as history for contextual answers); "+" starts a new topic.
- delete: a trash action per question (menu + stacked view).
- copy: single Q&A (question + answer + evidence + footnotes) or a whole
  thread, as Markdown to the clipboard (pure formatters in copy.ts).
- fullscreen: compact -> panel -> fullscreen view.
- route.ts consumes an optional bounded `history` so follow-ups are
  contextual for both the widget and the workspace consumer.

Tests: copy formatter unit tests + Playwright specs (threads/new-topic,
delete, fullscreen, copy affordance). No deploy.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-01 18:51:17 +02:00

66 lines
2.4 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { formatCaseForCopy, formatThreadForCopy } from '../advisor/copy'
import type { AdvisorResponse } from '../advisor/contract'
const answer: AdvisorResponse = {
mode: 'answer',
question: 'CRA Meldefrist',
clarity: { is_underspecified: false, concentration: 0.9 },
general_answer: null,
answer: 'Unverzüglich melden [1].',
scoped_query: 'cyber',
evidence: [{ evidence_id: 'e1', document: 'CRA', section: 'Art. 14', paragraph: 'Abs. 1', url: 'https://x' }],
citations: [],
visual_evidence: [],
footnotes: [{ footnote_id: 'f1', ref: 'Fußnote 3', document: 'EDPB', section: 'Kap III', text: 'Detail' }],
}
const clarify: AdvisorResponse = {
mode: 'clarify',
question: 'Was ist PDCA?',
clarity: { is_underspecified: true, concentration: 0.3 },
general_answer: 'PDCA = Plan-Do-Check-Act.',
answer: null,
scoped_query: null,
evidence: [],
citations: [],
visual_evidence: [],
footnotes: [],
}
describe('formatCaseForCopy', () => {
it('includes question, answer, resolved evidence and footnotes', () => {
const s = formatCaseForCopy({ question: 'CRA Meldefrist', response: answer })
expect(s).toContain('### Frage\nCRA Meldefrist')
expect(s).toContain('### Antwort\nUnverzüglich melden [1].')
expect(s).toContain('### Belege')
expect(s).toContain('Cyber Resilience Act (CRA), Art. 14 Abs. 1 (https://x)')
expect(s).toContain('### Fußnoten')
expect(s).toContain('Fußnote 3 — EDPB / Kap III: Detail')
})
it('falls back to the general definition for a clarify case', () => {
const s = formatCaseForCopy({ question: 'Was ist PDCA?', response: clarify })
expect(s).toContain('### Antwort\nPDCA = Plan-Do-Check-Act.')
expect(s).not.toContain('### Belege')
})
it('handles a case without a response', () => {
const s = formatCaseForCopy({ question: 'offen', response: null })
expect(s).toContain('### Antwort\n(keine Antwort)')
})
})
describe('formatThreadForCopy', () => {
it('renders a title heading + every case separated by a rule', () => {
const s = formatThreadForCopy('CRA Meldefrist', [
{ question: 'CRA Meldefrist', response: answer },
{ question: 'Und für KMU?', response: clarify },
])
expect(s.startsWith('# CRA Meldefrist')).toBe(true)
expect(s).toContain('\n---\n')
expect(s).toContain('CRA Meldefrist')
expect(s).toContain('Und für KMU?')
})
})