/** * AdminUsersTable Component Tests * * Tests for the AdminUsersTable component that displays users in a table * with selection, status management, and deletion capabilities. */ import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import { AdminUsersTable } from './AdminUsersTable'; import { describe, it, expect, vi } from 'vitest'; // Mock the DateDisplay component vi.mock('@/lib/display-objects/DateDisplay', () => ({ DateDisplay: { formatShort: (date: string) => new Date(date).toLocaleDateString(), }, })); // Mock the AdminUsersViewData vi.mock('@/lib/view-data/AdminUsersViewData', () => ({ AdminUsersViewData: {}, })); // Mock the Button component vi.mock('@/ui/Button', () => ({ Button: ({ children, onClick, disabled }: any) => ( ), })); // Mock the IconButton component vi.mock('@/ui/IconButton', () => ({ IconButton: ({ onClick, disabled, icon, title }: any) => ( ), })); // Mock the SimpleCheckbox component vi.mock('@/ui/SimpleCheckbox', () => ({ SimpleCheckbox: ({ checked, onChange, 'aria-label': ariaLabel }: any) => ( ), })); // Mock the Badge component vi.mock('@/ui/Badge', () => ({ Badge: ({ children }: any) => {children}, })); // Mock the Box component vi.mock('@/ui/Box', () => ({ Box: ({ children }: any) =>
{children}
, })); // Mock the Group component vi.mock('@/ui/Group', () => ({ Group: ({ children }: any) =>
{children}
, })); // Mock the DriverIdentity component vi.mock('@/ui/DriverIdentity', () => ({ DriverIdentity: ({ driver, meta }: any) => (
{driver.name} {meta}
), })); // Mock the Table components vi.mock('@/ui/Table', () => ({ Table: ({ children }: any) => {children}
, TableHead: ({ children }: any) => {children}, TableBody: ({ children }: any) => {children}, TableHeader: ({ children, w, textAlign }: any) => {children}, TableRow: ({ children, variant }: any) => {children}, TableCell: ({ children }: any) => {children}, })); // Mock the Text component vi.mock('@/ui/Text', () => ({ Text: ({ children, size, variant }: any) => ( {children} ), })); // Mock the UserStatusTag component vi.mock('./UserStatusTag', () => ({ UserStatusTag: ({ status }: any) => {status}, })); describe('AdminUsersTable', () => { const mockUsers = [ { id: '1', displayName: 'John Doe', email: 'john@example.com', roles: ['admin'], status: 'active', lastLoginAt: '2024-01-15T10:30:00Z', }, { id: '2', displayName: 'Jane Smith', email: 'jane@example.com', roles: ['user'], status: 'suspended', lastLoginAt: '2024-01-14T15:45:00Z', }, { id: '3', displayName: 'Bob Johnson', email: 'bob@example.com', roles: ['user'], status: 'active', lastLoginAt: null, }, ]; const defaultProps = { users: mockUsers, selectedUserIds: [], onSelectUser: vi.fn(), onSelectAll: vi.fn(), onUpdateStatus: vi.fn(), onDeleteUser: vi.fn(), deletingUserId: null, }; it('should render table headers', () => { render(); expect(screen.getByText('User')).toBeTruthy(); expect(screen.getByText('Roles')).toBeTruthy(); expect(screen.getByText('Status')).toBeTruthy(); expect(screen.getByText('Last Login')).toBeTruthy(); expect(screen.getByText('Actions')).toBeTruthy(); }); it('should render user rows', () => { render(); expect(screen.getByText('John Doe')).toBeTruthy(); expect(screen.getByText('john@example.com')).toBeTruthy(); expect(screen.getByText('Jane Smith')).toBeTruthy(); expect(screen.getByText('jane@example.com')).toBeTruthy(); expect(screen.getByText('Bob Johnson')).toBeTruthy(); expect(screen.getByText('bob@example.com')).toBeTruthy(); }); it('should render user roles', () => { render(); expect(screen.getByText('admin')).toBeTruthy(); expect(screen.getByText('user')).toBeTruthy(); }); it('should render user status tags', () => { render(); expect(screen.getAllByTestId('status-tag')).toHaveLength(3); }); it('should render last login dates', () => { render(); expect(screen.getByText('1/15/2024')).toBeTruthy(); expect(screen.getByText('1/14/2024')).toBeTruthy(); expect(screen.getByText('Never')).toBeTruthy(); }); it('should render select all checkbox', () => { render(); expect(screen.getByLabelText('Select all users')).toBeTruthy(); }); it('should render individual user checkboxes', () => { render(); expect(screen.getByLabelText('Select user John Doe')).toBeTruthy(); expect(screen.getByLabelText('Select user Jane Smith')).toBeTruthy(); expect(screen.getByLabelText('Select user Bob Johnson')).toBeTruthy(); }); it('should render suspend button for active users', () => { render(); expect(screen.getByText('Suspend')).toBeTruthy(); }); it('should render activate button for suspended users', () => { render(); expect(screen.getByText('Activate')).toBeTruthy(); }); it('should render delete button for all users', () => { render(); expect(screen.getAllByTitle('Delete')).toHaveLength(3); }); it('should render more button for all users', () => { render(); expect(screen.getAllByTitle('More')).toHaveLength(3); }); it('should highlight selected rows', () => { const props = { ...defaultProps, selectedUserIds: ['1', '3'], }; render(); // Check that selected rows have highlight variant const rows = screen.getAllByRole('row'); expect(rows[1]).toHaveAttribute('data-variant', 'highlight'); expect(rows[3]).toHaveAttribute('data-variant', 'highlight'); }); it('should disable delete button when deleting', () => { const props = { ...defaultProps, deletingUserId: '1', }; render(); const deleteButtons = screen.getAllByTitle('Delete'); expect(deleteButtons[0]).toBeDisabled(); }); it('should call onSelectUser when checkbox is clicked', () => { const onSelectUser = vi.fn(); const props = { ...defaultProps, onSelectUser, }; render(); const checkboxes = screen.getAllByTestId('checkbox'); fireEvent.click(checkboxes[1]); // Click first user checkbox expect(onSelectUser).toHaveBeenCalledWith('1'); }); it('should call onSelectAll when select all checkbox is clicked', () => { const onSelectAll = vi.fn(); const props = { ...defaultProps, onSelectAll, }; render(); const selectAllCheckbox = screen.getByLabelText('Select all users'); fireEvent.click(selectAllCheckbox); expect(onSelectAll).toHaveBeenCalled(); }); it('should call onUpdateStatus when suspend button is clicked', () => { const onUpdateStatus = vi.fn(); const props = { ...defaultProps, onUpdateStatus, }; render(); const suspendButtons = screen.getAllByText('Suspend'); fireEvent.click(suspendButtons[0]); expect(onUpdateStatus).toHaveBeenCalledWith('1', 'suspended'); }); it('should call onUpdateStatus when activate button is clicked', () => { const onUpdateStatus = vi.fn(); const props = { ...defaultProps, onUpdateStatus, }; render(); const activateButtons = screen.getAllByText('Activate'); fireEvent.click(activateButtons[0]); expect(onUpdateStatus).toHaveBeenCalledWith('2', 'active'); }); it('should call onDeleteUser when delete button is clicked', () => { const onDeleteUser = vi.fn(); const props = { ...defaultProps, onDeleteUser, }; render(); const deleteButtons = screen.getAllByTitle('Delete'); fireEvent.click(deleteButtons[0]); expect(onDeleteUser).toHaveBeenCalledWith('1'); }); it('should render empty table when no users', () => { const props = { ...defaultProps, users: [], }; render(); // Should render table headers but no rows expect(screen.getByText('User')).toBeTruthy(); expect(screen.getByText('Roles')).toBeTruthy(); expect(screen.getByText('Status')).toBeTruthy(); expect(screen.getByText('Last Login')).toBeTruthy(); expect(screen.getByText('Actions')).toBeTruthy(); }); it('should render with all users selected', () => { const props = { ...defaultProps, selectedUserIds: ['1', '2', '3'], }; render(); const selectAllCheckbox = screen.getByLabelText('Select all users'); expect(selectAllCheckbox).toBeChecked(); }); it('should render with some users selected', () => { const props = { ...defaultProps, selectedUserIds: ['1', '2'], }; render(); const selectAllCheckbox = screen.getByLabelText('Select all users'); expect(selectAllCheckbox).not.toBeChecked(); }); });