learning_ai_invt_trdg/web/src/components/AlertFeed.dom.test.tsx

91 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @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(<AlertFeed alerts={[]} />);
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(<AlertFeed alerts={alerts} />);
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(<AlertFeed alerts={alerts} />);
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(<AlertFeed alerts={alerts} />);
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(<AlertFeed alerts={alerts} />);
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(<AlertFeed alerts={alerts} />);
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(<AlertFeed alerts={alerts} />);
// 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();
});
});