Stirling-PDF/frontend/src/components/tools/sanitize/SanitizeSettings.test.tsx
James Brunton 8eeb4c148c
Add Sanitize UI (#4123)
# Description of Changes

Implementation of Sanitize UI for V2.

Also removes parameter validation from standard tool hooks because the
logic would have to be duplicated between parameter handling and
operation hooks, and the nicer workflow is for the tools to reject using
the Go button if the validation fails, rather than the operation hook
checking it, since that can't appear in the UI.

Co-authored-by: James <james@crosscourtanalytics.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Co-authored-by: ConnorYoh <40631091+ConnorYoh@users.noreply.github.com>
2025-08-12 16:05:59 +01:00

195 lines
5.9 KiB
TypeScript

import { describe, expect, test, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { MantineProvider } from '@mantine/core';
import SanitizeSettings from './SanitizeSettings';
import { SanitizeParameters } from '../../../hooks/tools/sanitize/useSanitizeParameters';
// Mock useTranslation with predictable return values
const mockT = vi.fn((key: string) => `mock-${key}`);
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: mockT })
}));
// Wrapper component to provide Mantine context
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
<MantineProvider>{children}</MantineProvider>
);
describe('SanitizeSettings', () => {
const defaultParameters: SanitizeParameters = {
removeJavaScript: true,
removeEmbeddedFiles: true,
removeXMPMetadata: false,
removeMetadata: false,
removeLinks: false,
removeFonts: false,
};
const mockOnParameterChange = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
});
test('should render all sanitization option checkboxes', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
// Should render one checkbox for each parameter
const expectedCheckboxCount = Object.keys(defaultParameters).length;
const checkboxes = screen.getAllByRole('checkbox');
expect(checkboxes).toHaveLength(expectedCheckboxCount);
});
test('should show correct initial checkbox states based on parameters', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
const parameterValues = Object.values(defaultParameters);
parameterValues.forEach((value, index) => {
if (value) {
expect(checkboxes[index]).toBeChecked();
} else {
expect(checkboxes[index]).not.toBeChecked();
}
});
});
test('should call onParameterChange with correct parameters when checkboxes are clicked', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
// Click the first checkbox (removeJavaScript - should toggle from true to false)
fireEvent.click(checkboxes[0]);
expect(mockOnParameterChange).toHaveBeenCalledWith('removeJavaScript', false);
// Click the third checkbox (removeXMPMetadata - should toggle from false to true)
fireEvent.click(checkboxes[2]);
expect(mockOnParameterChange).toHaveBeenCalledWith('removeXMPMetadata', true);
});
test('should disable all checkboxes when disabled prop is true', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
disabled={true}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
checkboxes.forEach(checkbox => {
expect(checkbox).toBeDisabled();
});
});
test('should enable all checkboxes when disabled prop is false or undefined', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
disabled={false}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
checkboxes.forEach(checkbox => {
expect(checkbox).not.toBeDisabled();
});
});
test('should handle different parameter combinations', () => {
const allEnabledParameters: SanitizeParameters = {
removeJavaScript: true,
removeEmbeddedFiles: true,
removeXMPMetadata: true,
removeMetadata: true,
removeLinks: true,
removeFonts: true,
};
render(
<TestWrapper>
<SanitizeSettings
parameters={allEnabledParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
checkboxes.forEach(checkbox => {
expect(checkbox).toBeChecked();
});
});
test('should call translation function with correct keys', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
// Verify that translation keys are being called (just check that it was called, not specific order)
expect(mockT).toHaveBeenCalledWith('sanitize.options.title', expect.any(String));
expect(mockT).toHaveBeenCalledWith('sanitize.options.removeJavaScript', expect.any(String));
expect(mockT).toHaveBeenCalledWith('sanitize.options.removeEmbeddedFiles', expect.any(String));
expect(mockT).toHaveBeenCalledWith('sanitize.options.note', expect.any(String));
});
test('should not call onParameterChange when disabled', () => {
render(
<TestWrapper>
<SanitizeSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
disabled={true}
/>
</TestWrapper>
);
const checkboxes = screen.getAllByRole('checkbox');
// Verify checkboxes are disabled
checkboxes.forEach(checkbox => {
expect(checkbox).toBeDisabled();
});
// Try to click a disabled checkbox - this might still fire the event in tests
// but we can verify the checkbox state doesn't actually change
const firstCheckbox = checkboxes[0] as HTMLInputElement;
const initialChecked = firstCheckbox.checked;
fireEvent.click(firstCheckbox);
expect(firstCheckbox.checked).toBe(initialChecked);
});
});