/**
* Tests for ConnectionStatus Component
*/
import { render, screen, fireEvent } from '@testing-library/react';
import { ConnectionStatus } from '@/components/events/ConnectionStatus';
import type { SSEError } from '@/lib/types/events';
describe('ConnectionStatus', () => {
const mockOnReconnect = jest.fn();
beforeEach(() => {
jest.clearAllMocks();
});
describe('connected state', () => {
it('renders connected status', () => {
render();
expect(screen.getByText('Connected')).toBeInTheDocument();
expect(screen.getByText('Receiving real-time updates')).toBeInTheDocument();
});
it('does not show reconnect button when connected', () => {
render();
expect(screen.queryByRole('button', { name: /reconnect/i })).not.toBeInTheDocument();
});
it('applies connected styling', () => {
const { container } = render();
expect(container.querySelector('.border-green-200')).toBeInTheDocument();
});
});
describe('connecting state', () => {
it('renders connecting status', () => {
render();
expect(screen.getByText('Connecting')).toBeInTheDocument();
expect(screen.getByText('Establishing connection...')).toBeInTheDocument();
});
it('shows retry count when retrying', () => {
render();
expect(screen.getByText('Retry 3')).toBeInTheDocument();
});
});
describe('disconnected state', () => {
it('renders disconnected status', () => {
render();
expect(screen.getByText('Disconnected')).toBeInTheDocument();
expect(screen.getByText('Not connected to server')).toBeInTheDocument();
});
it('shows reconnect button when disconnected', () => {
render();
const button = screen.getByRole('button', { name: /reconnect/i });
expect(button).toBeInTheDocument();
});
it('calls onReconnect when button is clicked', () => {
render();
const button = screen.getByRole('button', { name: /reconnect/i });
fireEvent.click(button);
expect(mockOnReconnect).toHaveBeenCalledTimes(1);
});
});
describe('error state', () => {
it('renders error status', () => {
render();
expect(screen.getByText('Connection Error')).toBeInTheDocument();
expect(screen.getByText('Failed to connect')).toBeInTheDocument();
});
it('shows reconnect button when in error state', () => {
render();
const button = screen.getByRole('button', { name: /reconnect/i });
expect(button).toBeInTheDocument();
});
it('applies error styling', () => {
const { container } = render();
expect(container.querySelector('.border-destructive')).toBeInTheDocument();
});
});
describe('error details', () => {
const mockError: SSEError = {
message: 'Connection timeout',
code: 'TIMEOUT',
timestamp: '2024-01-15T10:30:00Z',
retryAttempt: 2,
};
it('shows error message when error is provided', () => {
render();
expect(screen.getByText(/Error: Connection timeout/)).toBeInTheDocument();
});
it('shows error code when provided', () => {
render();
expect(screen.getByText(/Code: TIMEOUT/)).toBeInTheDocument();
});
it('hides error details when showErrorDetails is false', () => {
render();
expect(screen.queryByText(/Error: Connection timeout/)).not.toBeInTheDocument();
});
});
describe('compact mode', () => {
it('renders compact version', () => {
const { container } = render();
// Compact mode should not have the full description
expect(screen.queryByText('Receiving real-time updates')).not.toBeInTheDocument();
// Should still show the label
expect(screen.getByText('Connected')).toBeInTheDocument();
// Should use smaller container
expect(container.querySelector('.rounded-lg')).not.toBeInTheDocument();
});
it('shows compact reconnect button when disconnected', () => {
render();
// Should have a small reconnect button
const button = screen.getByRole('button', { name: /reconnect/i });
expect(button).toBeInTheDocument();
expect(button.className).toContain('h-6');
});
it('shows retry count in compact mode', () => {
render();
expect(screen.getByText(/retry 5/i)).toBeInTheDocument();
});
});
describe('showReconnectButton prop', () => {
it('hides reconnect button when showReconnectButton is false', () => {
render(
);
expect(screen.queryByRole('button', { name: /reconnect/i })).not.toBeInTheDocument();
});
});
describe('accessibility', () => {
it('has role="status" for screen readers', () => {
render();
expect(screen.getByRole('status')).toBeInTheDocument();
});
it('has aria-live="polite" for status updates', () => {
render();
const status = screen.getByRole('status');
expect(status).toHaveAttribute('aria-live', 'polite');
});
});
describe('className prop', () => {
it('applies custom className', () => {
const { container } = render();
expect(container.querySelector('.custom-class')).toBeInTheDocument();
});
});
});