// @vitest-environment jsdom import { beforeEach, afterEach, describe, expect, it, vi } from 'vitest'; import { render, screen } from '@testing-library/react'; import { AlertFeed } from './AlertFeed'; describe('AlertFeed DOM behavior', () => { beforeEach(() => { vi.useFakeTimers(); vi.setSystemTime(new Date('2026-02-17T12:00:00Z')); }); afterEach(() => { vi.useRealTimers(); }); it('renders recent activity header', () => { render(); expect(screen.getByText('Recent Activity')).toBeInTheDocument(); }); it('renders different alert types with correct icons', () => { const alerts: any[] = [ { timestamp: Date.now(), type: 'signal', symbol: 'BTC', message: 'Signal Alert' }, { timestamp: Date.now(), type: 'pulse', symbol: 'ETH', message: 'Pulse Alert' }, { timestamp: Date.now(), type: 'error', symbol: 'SOL', message: 'Error Alert' }, { timestamp: Date.now(), type: 'info', symbol: 'ADA', message: 'Info Alert' } ]; render(); expect(screen.getByText('🚀')).toBeInTheDocument(); expect(screen.getByText('⏰')).toBeInTheDocument(); expect(screen.getByText('âš ī¸')).toBeInTheDocument(); expect(screen.getByText('â„šī¸')).toBeInTheDocument(); expect(screen.getByText('Signal Alert')).toBeInTheDocument(); expect(screen.getByText('Pulse Alert')).toBeInTheDocument(); expect(screen.getByText('Error Alert')).toBeInTheDocument(); expect(screen.getByText('Info Alert')).toBeInTheDocument(); }); it('displays relative time correctly (just now)', () => { const alerts: any[] = [{ timestamp: Date.now(), type: 'info', symbol: 'BTC', message: 'test' }]; render(); expect(screen.getByText('just now')).toBeInTheDocument(); }); it('displays relative time correctly (minutes ago)', () => { const alerts: any[] = [{ timestamp: Date.now() - 5 * 60000, type: 'info', symbol: 'BTC', message: 'test' }]; render(); expect(screen.getByText('5m ago')).toBeInTheDocument(); }); it('displays relative time correctly (hours ago)', () => { const alerts: any[] = [{ timestamp: Date.now() - 3 * 3600000, type: 'info', symbol: 'BTC', message: 'test' }]; render(); expect(screen.getByText('3h ago')).toBeInTheDocument(); }); it('displays relative time correctly (days ago)', () => { const alerts: any[] = [{ timestamp: Date.now() - 2 * 86400000, type: 'info', symbol: 'BTC', message: 'test' }]; render(); expect(screen.getByText('2d ago')).toBeInTheDocument(); }); it('limits alerts to 50 items and reverses order', () => { // Since AlertFeed does .reverse().slice(0, 50), // if we want SYM0 to be the first one visible (most recent), // it should be at the END of the input array. const alerts = Array.from({ length: 60 }, (_, i) => ({ timestamp: Date.now() - (60 - i) * 1000, type: 'info' as const, symbol: `SYM${i}`, message: `Msg ${i}` })); const { container } = render(); // Should only show 50 items const alertItems = container.querySelectorAll('.alert-item'); expect(alertItems.length).toBe(50); // After reverse, SYM59 should be first (it was at the end and has largest timestamp in this mock data) expect(screen.getByText('SYM59')).toBeInTheDocument(); // SYM10 should be the last visible one (50th item) expect(screen.getByText('SYM10')).toBeInTheDocument(); // SYM9 should not be visible (it's at index 9, so it would be at index 50 after reverse) expect(screen.queryByText('SYM9')).not.toBeInTheDocument(); }); });