# Description of Changes Adds auto-redact tool to V2, with manual-redact in the UI but explicitly disabled. Also creates a shared component for the large buttons we're using in a couple different tools and uses consistently.
192 lines
5.5 KiB
TypeScript
192 lines
5.5 KiB
TypeScript
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
||
import { render, screen, fireEvent } from '@testing-library/react';
|
||
import { MantineProvider } from '@mantine/core';
|
||
import WordsToRedactInput from './WordsToRedactInput';
|
||
|
||
// Mock useTranslation
|
||
const mockT = vi.fn((_key: string, fallback: string) => fallback);
|
||
vi.mock('react-i18next', () => ({
|
||
useTranslation: () => ({ t: mockT })
|
||
}));
|
||
|
||
// Wrapper component to provide Mantine context
|
||
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
||
<MantineProvider>{children}</MantineProvider>
|
||
);
|
||
|
||
describe('WordsToRedactInput', () => {
|
||
const mockOnWordsChange = vi.fn();
|
||
|
||
beforeEach(() => {
|
||
vi.clearAllMocks();
|
||
});
|
||
|
||
test('should render with title and input field', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
expect(screen.getByText('Words to Redact')).toBeInTheDocument();
|
||
expect(screen.getByPlaceholderText('Enter a word')).toBeInTheDocument();
|
||
expect(screen.getByRole('button', { name: '+ Add' })).toBeInTheDocument();
|
||
});
|
||
|
||
test.each([
|
||
{ trigger: 'Add button click', action: (_input: HTMLElement, addButton: HTMLElement) => fireEvent.click(addButton) },
|
||
{ trigger: 'Enter key press', action: (input: HTMLElement) => fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' }) },
|
||
])('should add word when $trigger', ({ action }) => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word');
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.change(input, { target: { value: 'TestWord' } });
|
||
action(input, addButton);
|
||
|
||
expect(mockOnWordsChange).toHaveBeenCalledWith(['TestWord']);
|
||
});
|
||
|
||
test('should not add empty word', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.click(addButton);
|
||
|
||
expect(mockOnWordsChange).not.toHaveBeenCalled();
|
||
});
|
||
|
||
test('should not add duplicate word', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={['Existing']}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word');
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.change(input, { target: { value: 'Existing' } });
|
||
fireEvent.click(addButton);
|
||
|
||
expect(mockOnWordsChange).not.toHaveBeenCalled();
|
||
});
|
||
|
||
test('should trim whitespace when adding word', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word');
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.change(input, { target: { value: ' TestWord ' } });
|
||
fireEvent.click(addButton);
|
||
|
||
expect(mockOnWordsChange).toHaveBeenCalledWith(['TestWord']);
|
||
});
|
||
|
||
test('should remove word when x button is clicked', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={['Word1', 'Word2']}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const removeButtons = screen.getAllByText('×');
|
||
fireEvent.click(removeButtons[0]);
|
||
|
||
expect(mockOnWordsChange).toHaveBeenCalledWith(['Word2']);
|
||
});
|
||
|
||
test('should clear input after adding word', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word') as HTMLInputElement;
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.change(input, { target: { value: 'TestWord' } });
|
||
fireEvent.click(addButton);
|
||
|
||
expect(input.value).toBe('');
|
||
});
|
||
|
||
test.each([
|
||
{ description: 'disable Add button when input is empty', inputValue: '', expectedDisabled: true },
|
||
{ description: 'enable Add button when input has text', inputValue: 'TestWord', expectedDisabled: false },
|
||
])('should $description', ({ inputValue, expectedDisabled }) => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={[]}
|
||
onWordsChange={mockOnWordsChange}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word');
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
|
||
fireEvent.change(input, { target: { value: inputValue } });
|
||
|
||
expect(addButton).toHaveProperty('disabled', expectedDisabled);
|
||
});
|
||
|
||
test('should disable all controls when disabled prop is true', () => {
|
||
render(
|
||
<TestWrapper>
|
||
<WordsToRedactInput
|
||
wordsToRedact={['Word1']}
|
||
onWordsChange={mockOnWordsChange}
|
||
disabled={true}
|
||
/>
|
||
</TestWrapper>
|
||
);
|
||
|
||
const input = screen.getByPlaceholderText('Enter a word');
|
||
const addButton = screen.getByRole('button', { name: '+ Add' });
|
||
const removeButton = screen.getByText('×');
|
||
|
||
expect(input).toBeDisabled();
|
||
expect(addButton).toBeDisabled();
|
||
expect(removeButton.closest('button')).toBeDisabled();
|
||
});
|
||
});
|