66 lines
4.7 KiB
TypeScript
66 lines
4.7 KiB
TypeScript
// @vitest-environment jsdom
|
|
import { act } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { afterEach, expect, it, vi } from 'vitest';
|
|
import { useApp } from '../../src/app/AppProvider';
|
|
import { AssessorApiClient } from '../../src/api/assessor-api-client';
|
|
import { DashboardPanel } from '../../src/features/dashboard/DashboardPanel';
|
|
import { clientFactsSnapshot, clientFactsState } from '../fixtures/client-info-facts';
|
|
|
|
vi.mock('../../src/app/AppProvider', () => ({ useApp: vi.fn() }));
|
|
vi.mock('../../src/features/search-filter/WorkTimeslotControl', () => ({ WorkTimeslotControl: () => <span>Synthetic timeslot</span> }));
|
|
afterEach(() => { vi.restoreAllMocks(); vi.unstubAllGlobals(); document.body.replaceChildren(); });
|
|
|
|
it.each(['populated', 'unavailable', 'non-numeric count'])('shows each overview fact once in the existing tiles and preserves Results: %s', async mode => {
|
|
vi.stubGlobal('IS_REACT_ACT_ENVIRONMENT', true);
|
|
const snapshot = structuredClone(clientFactsSnapshot);
|
|
if (mode === 'unavailable') { snapshot.observations = []; snapshot.sections = []; }
|
|
if (mode === 'non-numeric count') {
|
|
const count = snapshot.observations.find(item => item.property === 'domain.controller_count')!;
|
|
count.originalValue = count.normalizedValue = 'Two reported controllers'; count.valueType = 'string';
|
|
}
|
|
vi.spyOn(AssessorApiClient.prototype, 'getEnvironmentSnapshot').mockResolvedValue(snapshot);
|
|
vi.spyOn(AssessorApiClient.prototype, 'listProjectGpoBackupStatus').mockResolvedValue({ records: [] } as never);
|
|
vi.mocked(useApp).mockReturnValue(clientFactsState() as unknown as ReturnType<typeof useApp>);
|
|
const host = document.createElement('div'); document.body.append(host); const root = createRoot(host);
|
|
try {
|
|
await act(async () => root.render(<DashboardPanel onOpenWork={vi.fn()}/>));
|
|
const domain = host.querySelector('.client-domain-information')!;
|
|
const groups = [...host.querySelectorAll('.client-env-group')];
|
|
const directory = groups.find(group => group.querySelector('h3')?.textContent === 'Directory')!;
|
|
const inventory = groups.find(group => group.querySelector('h3')?.textContent === 'Inventory')!;
|
|
const labels = (element: Element) => [...element.querySelectorAll('dt')].map(item => item.textContent);
|
|
expect(host.querySelector('.client-posture')).not.toBeNull();
|
|
expect(host.querySelector('.client-posture-connectors')).not.toBeNull();
|
|
expect(host.querySelector('.client-priority')).not.toBeNull();
|
|
expect(host.querySelectorAll('.client-data-fact')).toHaveLength(6);
|
|
expect(groups).toHaveLength(5);
|
|
const tiles = [...host.querySelectorAll('.client-environment-grid > section')];
|
|
expect(tiles).toHaveLength(6);
|
|
for (const tile of tiles) expect(tile.querySelectorAll('.client-env-facts > div').length).toBeLessThanOrEqual(4);
|
|
expect(labels(directory)).toEqual(['NetBIOS name', 'Schema version', 'Domain created', 'Entra ID']);
|
|
expect(labels(domain)).toEqual(mode === 'non-numeric count'
|
|
? ['Domain', 'Forest', 'Domain controllers', 'Domain functional level', 'Forest functional level', 'DC OS']
|
|
: ['Domain', 'Forest', 'Domain functional level', 'Forest functional level', 'DC OS']);
|
|
expect(labels(inventory)).toEqual(['Enabled / disabled', 'Password never expires', 'Admin groups', 'Trusts']);
|
|
// Equal domain/forest and functional-level values are distinct facts, not duplicates.
|
|
if (mode !== 'unavailable') {
|
|
expect([...domain.querySelectorAll('dd')].filter(item => item.textContent === 'contoso.example')).toHaveLength(2);
|
|
expect([...domain.querySelectorAll('dd')].filter(item => item.textContent === 'Windows Server 2016')).toHaveLength(2);
|
|
} else expect([...domain.querySelectorAll('dd')].every(item => item.textContent === '—')).toBe(true);
|
|
for (const [title, group, expected] of [
|
|
['Directory', directory, ['Domain', 'Forest', 'Domains', 'Domain functional level', 'Schema version']],
|
|
['Inventory', inventory, ['User accounts', 'Computer objects', 'Domain controllers', 'Assessed host']]
|
|
] as const) {
|
|
const trigger = group.querySelector<HTMLButtonElement>('button')!;
|
|
expect(trigger.getAttribute('aria-label')).toBe(`Open ${title} results`);
|
|
await act(async () => trigger.click());
|
|
const popup = document.querySelector('.floating-data-window')!;
|
|
for (const label of expected) expect(labels(popup)).toContain(label);
|
|
if (mode !== 'unavailable') expect(popup.querySelector('table')).not.toBeNull();
|
|
await act(async () => document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true })));
|
|
expect(document.querySelector('.floating-data-window')).toBeNull();
|
|
}
|
|
} finally { await act(async () => root.unmount()); }
|
|
});
|