// @vitest-environment jsdom import { act, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { afterEach, describe, expect, it, vi } from 'vitest'; import type { FindingRecord } from '../../src/domain/finding'; import { TileCard } from '../../src/components/TileCard/TileCard'; import { FindingReader } from '../../src/features/finding-reader/FindingReader'; const record: FindingRecord = { id: 'synthetic-removable-scan', index: 0, title: 'Synthetic removable drive scan check', filled: [], meta: [], fields: [['Source: Scan', 'Maester'], ['Source Rule ID', 'MT.1154'], ['Result', 'Failed'], ['Severity', 'High'], ['Block', 'Maester/Defender'], ['Tag', '["Maester","Defender","MT.1154"]'], ['Description', 'Synthetic scanner description']].map(([label, value], index) => ({ label, value, index })) }; const noop = () => {}; function WorkReading({ finding, toolId }: { finding: FindingRecord; toolId: string }) { const [opened, setOpened] = useState(false); return opened ? <> : setOpened(true)} onBookmark={noop}/>; } afterEach(() => { vi.unstubAllGlobals(); document.body.replaceChildren(); }); describe.each(['light', 'dark'])('Native Maester category badges (%s)', theme => { it.each(['maester', 'generic'])('keeps the category visible when opening compact tiles by mouse and keyboard in a %s workspace', async toolId => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); document.documentElement.dataset.theme = theme; const original = JSON.stringify(record); const host = document.createElement('div'); document.body.append(host); const root = createRoot(host); try { await act(async () => root.render()); for (const activation of ['mouse', 'keyboard']) { const tile = host.querySelector('.data-tile')!; expect(tile.querySelector('[data-badge-role="category"]')?.textContent).toBe('Maester/Defender'); expect(tile.querySelector('[data-badge-role="status"]')?.textContent).toBe('Failed'); expect([...tile.querySelector('.data-tile-badges')!.children].map(badge => badge.textContent)).toEqual(['Failed', 'High', 'Maester/Defender']); await act(async () => { if (activation === 'mouse') tile.click(); else tile.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true })); }); const badges = host.querySelector('.finding-badges')!; expect([...badges.querySelectorAll('.status-badge')].map(badge => badge.textContent)).toEqual(['Category: Maester/Defender']); expect(badges.querySelector('.severity-badge')?.textContent).toBe('High'); expect(badges.querySelector('.outcome-mark')?.textContent).toBe('Failed'); expect([...badges.children].map(badge => badge.textContent)).toEqual(['Failed', 'High', 'Category: Maester/Defender']); expect(host.querySelector('.reader-summary')?.textContent).toContain('CategoryMaester/Defender'); expect(JSON.stringify(record)).toBe(original); await act(async () => host.querySelector('button')!.click()); } } finally { await act(async () => root.unmount()); host.remove(); } }); it('preserves explicit categories and does not turn missing or non-Maester Block fields into categories', async () => { vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true); document.documentElement.dataset.theme = theme; const host = document.createElement('div'); document.body.append(host); const root = createRoot(host); const cases = [ { finding: { ...record, fields: [...record.fields, { label: 'Category', value: 'Explicit scanner category', index: 8 }] }, toolId: 'maester', category: 'Explicit scanner category' }, { finding: { ...record, fields: record.fields.map(field => field.label === 'Block' ? { ...field, value: ' ' } : field) }, toolId: 'maester', category: undefined }, { finding: { ...record, fields: record.fields.filter(field => field.label !== 'Source: Scan') }, toolId: 'purple-knight', category: undefined } ]; try { for (const { finding, toolId, category } of cases) { await act(async () => root.render()); expect(host.querySelector('[data-badge-role="category"]')?.textContent).toBe(category); await act(async () => host.querySelector('.data-tile')!.click()); const categoryBadge = [...host.querySelectorAll('.finding-badges .status-badge')].find(badge => badge.textContent?.startsWith('Category:')); expect(categoryBadge?.textContent).toBe(category ? `Category: ${category}` : undefined); } } finally { await act(async () => root.unmount()); host.remove(); } }); });