import { describe, it, expect } from 'vitest' import { licenseTierBadgeClass, commercialBadgeClass, groupUseCases, provenanceLabel, provenanceBadgeClass, splitByTier, severityBadgeClass, addresseeLabel, categorizeCorpusDoc, groupCorpusDocs, type UseCaseRow, type ControlItem, type CorpusDoc, } from './_helpers' const doc = (src: string, n = 1): CorpusDoc => ({ source_regulation: src, license_rule: 1, license_tier: 't', atom_count: n, use_case: null, }) const ctrl = (over: Partial): ControlItem => ({ id: 'id', title: 'T', relevant: true, tier: 'core', source_type: 'derived', applicable: true, is_gov: false, ...over, }) const uc = (over: Partial): UseCaseRow => ({ key: 'x', label: 'X', group: 'security', regulations: [], verification_methods: [], mapped_controls: 0, atom_total: 0, atom_relevant: 0, ...over, }) describe('coverage helpers', () => { it('license tier badge classes', () => { expect(licenseTierBadgeClass(1)).toContain('green') expect(licenseTierBadgeClass(2)).toContain('blue') expect(licenseTierBadgeClass(3)).toContain('amber') expect(licenseTierBadgeClass(null)).toContain('gray') }) it('commercial-use badge classes', () => { expect(commercialBadgeClass('allowed')).toContain('green') expect(commercialBadgeClass('restricted')).toContain('amber') expect(commercialBadgeClass('prohibited')).toContain('red') expect(commercialBadgeClass(null)).toContain('gray') }) it('groups use-cases in stable order and sorts by relevant desc', () => { const groups = groupUseCases([ uc({ key: 'a', group: 'security', atom_relevant: 5 }), uc({ key: 'b', group: 'security', atom_relevant: 15 }), uc({ key: 'c', group: 'document', atom_relevant: 1 }), ]) expect(groups[0].group).toBe('document') expect(groups[1].group).toBe('security') expect(groups[1].rows[0].key).toBe('b') expect(groups[1].rows[1].key).toBe('a') }) it('appends unknown groups after the known order', () => { const groups = groupUseCases([ uc({ key: 'z', group: 'mystery', atom_relevant: 9 }), uc({ key: 'd', group: 'document', atom_relevant: 2 }), ]) expect(groups.map((g) => g.group)).toEqual(['document', 'mystery']) }) it('provenance label: own library vs derived (with document + article)', () => { expect(provenanceLabel(ctrl({ source_type: 'own_library' }))).toBe( 'Eigene Bibliothek', ) expect( provenanceLabel( ctrl({ source_type: 'derived', source_regulation: 'DSGVO' }), ), ).toBe('Abgeleitet · DSGVO') expect( provenanceLabel( ctrl({ source_type: 'derived', source_regulation: 'DSGVO', source_article: 'Art. 30', }), ), ).toBe('Abgeleitet · DSGVO Art. 30') // derived but no document known → graceful fallback expect(provenanceLabel(ctrl({ source_type: 'derived' }))).toBe('Abgeleitet') }) it('provenance + severity badge classes', () => { expect(provenanceBadgeClass('own_library')).toContain('amber') expect(provenanceBadgeClass('derived')).toContain('blue') expect(severityBadgeClass('critical')).toContain('red') expect(severityBadgeClass('high')).toContain('orange') expect(severityBadgeClass(null)).toContain('gray') }) it('addressee label maps keys to German labels', () => { expect(addresseeLabel('oeffentliche_stelle')).toBe('Öffentliche Stelle') expect(addresseeLabel('aufsichtsbefugnis')).toBe('Aufsichtsbehörde') expect(addresseeLabel('staat_eu')).toBe('Mitgliedstaat/EU') expect(addresseeLabel(null)).toBe('') expect(addresseeLabel('unbekannt_neu')).toBe('unbekannt_neu') }) it('categorizes corpus docs by type + issuer family', () => { expect(categorizeCorpusDoc('DSGVO (EU) 2016/679').cat.key).toBe('law') expect(categorizeCorpusDoc('Medizinprodukteverordnung (EU) 2017/745 (MDR)').cat.key).toBe('law') expect(categorizeCorpusDoc('DSK OH Telemedien')).toMatchObject({ cat: { key: 'guidance' }, family: 'DSK (Datenschutzkonferenz)', }) expect(categorizeCorpusDoc('EDPB Fines Calculation')).toMatchObject({ cat: { key: 'guidance' }, family: 'EDPB', }) expect(categorizeCorpusDoc('OWASP Top 10 (2021)')).toMatchObject({ cat: { key: 'standard' }, family: 'OWASP', }) expect(categorizeCorpusDoc('NIST SP 800-53 Rev. 5').family).toBe('NIST') expect(categorizeCorpusDoc('ENISA NIS2 Security Measures').family).toBe('ENISA') expect(categorizeCorpusDoc('BGH I ZR 7/16').cat.key).toBe('court') }) it('groups corpus docs: laws → guidance → standards → court, families clustered', () => { const groups = groupCorpusDocs([ doc('OWASP Top 10', 10), doc('DSGVO (EU) 2016/679', 50), doc('DSK OH Telemedien', 5), doc('EDPB Fines', 8), doc('NIST SP 800-53', 20), doc('DSK OH Direktwerbung', 3), doc('BGH I ZR 7/16', 1), ]) expect(groups.map((g) => g.key)).toEqual(['law', 'guidance', 'standard', 'court']) const guidance = groups.find((g) => g.key === 'guidance')! // two DSK docs collapse into one family const dsk = guidance.families.find((f) => f.family.startsWith('DSK'))! expect(dsk.docs.length).toBe(2) const std = groups.find((g) => g.key === 'standard')! // NIST (20) before OWASP (10) — families sorted by size desc expect(std.families.map((f) => f.family)).toEqual(['NIST', 'OWASP']) }) it('splitByTier separates core (relevant) from review', () => { const { core, review } = splitByTier([ ctrl({ id: 'a', relevant: true }), ctrl({ id: 'b', relevant: false, tier: 'review' }), ctrl({ id: 'c', relevant: true }), ]) expect(core.map((c) => c.id)).toEqual(['a', 'c']) expect(review.map((c) => c.id)).toEqual(['b']) }) })