FABRIC/src/web/frontend/test/CollisionAlert.test.tsx
jeda 9ffbda241a feat(bd-1fz): Add React Testing Library tests for WorkerGrid component
- Add 28 comprehensive tests covering:
  - Empty state rendering
  - Worker count display
  - Status display (active, idle, error)
  - Event count formatting
  - Last seen time formatting (seconds, minutes, hours)
  - Worker selection/deselection
  - Collision indicators and warnings
  - CSS class application
  - Accessibility attributes

- Fix cleanup issue in existing test files:
  - Add afterEach cleanup to ActivityStream.test.tsx
  - Add afterEach cleanup to CollisionAlert.test.tsx

All 317 tests pass.

Co-Authored-By: Claude Worker <noreply@anthropic.com>
2026-03-03 14:59:37 +00:00

549 lines
15 KiB
TypeScript

/**
* Tests for CollisionAlert component
* @vitest-environment jsdom
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, fireEvent, cleanup } from '@testing-library/react';
import CollisionAlert from '../src/components/CollisionAlert';
import { CollisionAlert as CollisionAlertData } from '../src/types';
describe('CollisionAlert', () => {
const createMockAlert = (overrides: Partial<CollisionAlertData> = {}): CollisionAlertData => ({
id: 'alert-1',
type: 'file',
severity: 'warning',
title: 'Test Alert',
description: 'Test description',
workers: ['worker-alpha', 'worker-beta'],
timestamp: Date.now(),
acknowledged: false,
collision: {
path: '/test/file.ts',
workers: ['worker-alpha', 'worker-beta'],
detectedAt: Date.now(),
isActive: true,
},
...overrides,
});
const mockOnAcknowledge = vi.fn();
const mockOnAcknowledgeAll = vi.fn();
const mockOnClose = vi.fn();
beforeEach(() => {
mockOnAcknowledge.mockClear();
mockOnAcknowledgeAll.mockClear();
mockOnClose.mockClear();
});
afterEach(() => {
cleanup();
});
describe('rendering', () => {
it('should not render when visible is false', () => {
const { container } = render(
<CollisionAlert
alerts={[]}
visible={false}
/>
);
expect(container.querySelector('.collision-alert-panel')).not.toBeInTheDocument();
});
it('should render empty state when no alerts', () => {
const { container } = render(
<CollisionAlert
alerts={[]}
visible={true}
/>
);
expect(container.querySelector('.collision-alert-panel')).toBeInTheDocument();
expect(container.querySelector('.collision-empty')).toBeInTheDocument();
});
it('should render alerts count', () => {
const alerts = [
createMockAlert({ id: 'alert-1', title: 'Alert 1' }),
createMockAlert({ id: 'alert-2', title: 'Alert 2' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-summary')?.textContent).toContain('Alerts: 2');
});
it('should render unacknowledged count', () => {
const alerts = [
createMockAlert({ id: 'alert-1', acknowledged: false }),
createMockAlert({ id: 'alert-2', acknowledged: true }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-summary')?.textContent).toContain('1 unacknowledged');
});
});
describe('severity grouping', () => {
it('should group critical alerts together', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'critical', title: 'Critical Alert' }),
createMockAlert({ id: 'alert-2', severity: 'error', title: 'Error Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
const criticalGroup = container.querySelector('.collision-group-critical');
expect(criticalGroup).toBeInTheDocument();
expect(criticalGroup?.textContent).toContain('CRITICAL/ERROR');
expect(criticalGroup?.textContent).toContain('Critical Alert');
expect(criticalGroup?.textContent).toContain('Error Alert');
});
it('should group warning alerts together', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'warning', title: 'Warning Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
const warningGroup = container.querySelector('.collision-group-warning');
expect(warningGroup).toBeInTheDocument();
expect(warningGroup?.textContent).toContain('WARNINGS');
expect(warningGroup?.textContent).toContain('Warning Alert');
});
it('should group info alerts together', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'info', title: 'Info Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
const infoGroup = container.querySelector('.collision-group-info');
expect(infoGroup).toBeInTheDocument();
expect(infoGroup?.textContent).toContain('INFO');
expect(infoGroup?.textContent).toContain('Info Alert');
});
});
describe('type icons', () => {
it('should show [F] for file type', () => {
const alerts = [
createMockAlert({ id: 'alert-1', type: 'file' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-type')?.textContent).toBe('[F]');
});
it('should show [B] for bead type', () => {
const alerts = [
createMockAlert({ id: 'alert-1', type: 'bead' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-type')?.textContent).toBe('[B]');
});
it('should show [T] for task type', () => {
const alerts = [
createMockAlert({ id: 'alert-1', type: 'task' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-type')?.textContent).toBe('[T]');
});
});
describe('severity icons', () => {
it('should show !!! for critical', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'critical' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-icon')?.textContent).toBe('!!!');
});
it('should show !! for error', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'error' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-icon')?.textContent).toBe('!!');
});
it('should show ! for warning', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'warning' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-icon')?.textContent).toBe('!');
});
it('should show i for info', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'info' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-icon')?.textContent).toBe('i');
});
});
describe('acknowledgment', () => {
it('should call onAcknowledge when acknowledge button clicked', () => {
const alerts = [
createMockAlert({ id: 'alert-1', title: 'Test Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
onAcknowledge={mockOnAcknowledge}
/>
);
// Click acknowledge button (alert is already selected by default)
const ackBtn = container.querySelector('.collision-action-btn');
expect(ackBtn).toBeInTheDocument();
fireEvent.click(ackBtn!);
expect(mockOnAcknowledge).toHaveBeenCalledWith('alert-1');
});
it('should call onAcknowledgeAll when acknowledge all clicked', () => {
const alerts = [
createMockAlert({ id: 'alert-1' }),
createMockAlert({ id: 'alert-2' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
onAcknowledgeAll={mockOnAcknowledgeAll}
/>
);
const ackAllBtn = container.querySelectorAll('.collision-action-btn')[1];
fireEvent.click(ackAllBtn);
expect(mockOnAcknowledgeAll).toHaveBeenCalled();
});
it('should show [ACK] for acknowledged alerts', () => {
const alerts = [
createMockAlert({ id: 'alert-1', acknowledged: true, title: 'Acknowledged Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-ack')?.textContent).toBe('[ACK]');
});
it('should disable acknowledge button for acknowledged alerts', () => {
const alerts = [
createMockAlert({ id: 'alert-1', acknowledged: true, title: 'Acknowledged Alert' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
onAcknowledge={mockOnAcknowledge}
/>
);
const acknowledgeBtn = container.querySelector('.collision-action-btn');
expect(acknowledgeBtn).toBeDisabled();
});
});
describe('detail view', () => {
it('should show detail section when alert selected', () => {
const alerts = [
createMockAlert({ id: 'alert-1', title: 'Test Alert', description: 'Detailed description' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
const detailSection = container.querySelector('.collision-detail');
expect(detailSection).toBeInTheDocument();
expect(detailSection?.textContent).toContain('Selected Alert Details:');
expect(detailSection?.textContent).toContain('Detailed description');
});
it('should show workers in detail view', () => {
const alerts = [
createMockAlert({
id: 'alert-1',
workers: ['worker-alpha', 'worker-beta']
}),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
const detailSection = container.querySelector('.collision-detail');
expect(detailSection?.textContent).toContain('worker-alpha');
expect(detailSection?.textContent).toContain('worker-beta');
});
it('should show suggestion when present', () => {
const alerts = [
createMockAlert({
id: 'alert-1',
suggestion: 'Consider coordinating with other worker'
}),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-detail-suggestion')?.textContent).toContain('Consider coordinating');
});
});
describe('close button', () => {
it('should call onClose when close button clicked', () => {
const alerts = [
createMockAlert({ id: 'alert-1' }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
onClose={mockOnClose}
/>
);
const closeBtn = container.querySelector('.collision-alert-close');
fireEvent.click(closeBtn!);
expect(mockOnClose).toHaveBeenCalled();
});
});
describe('worker display', () => {
it('should show worker count when more than 2 workers', () => {
const alerts = [
createMockAlert({
id: 'alert-1',
workers: ['w1', 'w2', 'w3', 'w4']
}),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-workers')?.textContent).toBe('4 workers');
});
it('should show worker names when 2 or fewer workers', () => {
const alerts = [
createMockAlert({
id: 'alert-1',
workers: ['alpha', 'beta']
}),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
expect(container.querySelector('.collision-item-workers')?.textContent).toBe('alpha, beta');
});
});
describe('title truncation', () => {
it('should truncate long titles', () => {
const longTitle = 'A'.repeat(50);
const alerts = [
createMockAlert({ id: 'alert-1', title: longTitle }),
];
const { container } = render(
<CollisionAlert
alerts={alerts}
visible={true}
/>
);
// Title should be truncated to 40 chars + '...'
const titleEl = container.querySelector('.collision-item-title');
expect(titleEl?.textContent).toBe('A'.repeat(40) + '...');
});
});
describe('CSS classes', () => {
it('should apply collision-alert-panel class', () => {
const { container } = render(
<CollisionAlert alerts={[]} visible={true} />
);
expect(container.querySelector('.collision-alert-panel')).toBeInTheDocument();
});
it('should apply severity class to items', () => {
const alerts = [
createMockAlert({ id: 'alert-1', severity: 'critical' }),
];
const { container } = render(
<CollisionAlert alerts={alerts} visible={true} />
);
expect(container.querySelector('.collision-severity-critical')).toBeInTheDocument();
});
it('should apply selected class to selected item', () => {
const alerts = [
createMockAlert({ id: 'alert-1', title: 'First' }),
createMockAlert({ id: 'alert-2', title: 'Second' }),
];
const { container } = render(
<CollisionAlert alerts={alerts} visible={true} />
);
// First item should be selected by default
const selectedItems = container.querySelectorAll('.collision-item.selected');
expect(selectedItems.length).toBe(1);
});
it('should apply acknowledged class', () => {
const alerts = [
createMockAlert({ id: 'alert-1', acknowledged: true }),
];
const { container } = render(
<CollisionAlert alerts={alerts} visible={true} />
);
expect(container.querySelector('.collision-item.acknowledged')).toBeInTheDocument();
});
});
describe('selection', () => {
it('should change selection when clicking an alert', () => {
const alerts = [
createMockAlert({ id: 'alert-1', title: 'First Alert' }),
createMockAlert({ id: 'alert-2', title: 'Second Alert' }),
];
const { container } = render(
<CollisionAlert alerts={alerts} visible={true} />
);
// Click second item
const items = container.querySelectorAll('.collision-item');
fireEvent.click(items[1]);
// Second item should now be selected
expect(items[1]).toHaveClass('selected');
expect(items[0]).not.toHaveClass('selected');
});
});
});