import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
render as rtlRender,
screen,
fireEvent,
waitFor,
} from '@testing-library/react';
import React from 'react';
import { MantineProvider } from '@mantine/core';
import DeleteUserModal from './DeleteUserModal';
import { UserRole, Theme, type User } from '@/types/models';
// Mock notifications
vi.mock('@mantine/notifications', () => ({
notifications: {
show: vi.fn(),
},
}));
// Helper wrapper component for testing
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
{children}
);
// Custom render function
const render = (ui: React.ReactElement) => {
return rtlRender(ui, { wrapper: TestWrapper });
};
describe('DeleteUserModal', () => {
const mockOnConfirm = vi.fn();
const mockOnClose = vi.fn();
const mockUser: User = {
id: 1,
email: 'test@example.com',
displayName: 'Test User',
role: UserRole.Editor,
theme: Theme.Dark,
createdAt: '2024-01-01T00:00:00Z',
lastWorkspaceId: 1,
};
beforeEach(() => {
vi.clearAllMocks();
mockOnConfirm.mockResolvedValue(undefined);
});
describe('Modal Visibility and Content', () => {
it('renders modal when opened with user data and confirmation message', () => {
render(
);
expect(screen.getByText('Delete User')).toBeInTheDocument();
expect(
screen.getByText(
'Are you sure you want to delete user "test@example.com"? This action cannot be undone and all associated data will be permanently deleted.'
)
).toBeInTheDocument();
expect(
screen.getByTestId('cancel-delete-user-button')
).toBeInTheDocument();
expect(
screen.getByTestId('confirm-delete-user-button')
).toBeInTheDocument();
});
it('does not render modal when closed', () => {
render(
);
expect(screen.queryByText('Delete User')).not.toBeInTheDocument();
});
it('renders modal with null user showing empty email', () => {
render(
);
expect(screen.getByText('Delete User')).toBeInTheDocument();
expect(
screen.getByText(
'Are you sure you want to delete user ""? This action cannot be undone and all associated data will be permanently deleted.'
)
).toBeInTheDocument();
});
});
describe('Modal Actions', () => {
it('calls onConfirm when delete button is clicked', async () => {
render(
);
fireEvent.click(screen.getByTestId('confirm-delete-user-button'));
await waitFor(() => {
expect(mockOnConfirm).toHaveBeenCalledTimes(1);
});
});
it('calls onClose when cancel button is clicked', () => {
render(
);
fireEvent.click(screen.getByTestId('cancel-delete-user-button'));
expect(mockOnClose).toHaveBeenCalled();
});
});
describe('Loading State', () => {
it('shows loading state and disables delete button when loading', () => {
render(
);
const deleteButton = screen.getByTestId('confirm-delete-user-button');
expect(deleteButton).toHaveAttribute('data-loading', 'true');
expect(deleteButton).toBeDisabled();
});
});
describe('Accessibility and Security', () => {
it('has properly labeled buttons and destructive action warning', () => {
render(
);
expect(
screen.getByRole('button', { name: /cancel/i })
).toBeInTheDocument();
expect(
screen.getByRole('button', { name: /delete/i })
).toBeInTheDocument();
// Security: Clear warning about destructive action
expect(
screen.getByText(
/This action cannot be undone and all associated data will be permanently deleted/
)
).toBeInTheDocument();
// Security: User identifier for verification
expect(
screen.getByText(/delete user "test@example.com"/)
).toBeInTheDocument();
});
});
});