mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 03:20:46 +02:00
Restructure frontend code to allow for extensions (#4721)
# Description of Changes Move frontend code into `core` folder and add infrastructure for `proprietary` folder to include premium, non-OSS features
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
import { describe, expect, test, vi, beforeEach } from 'vitest';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { MantineProvider } from '@mantine/core';
|
||||
import SanitizeSettings from '@app/components/tools/sanitize/SanitizeSettings';
|
||||
import { SanitizeParameters } from '@app/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);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Stack, Text, Checkbox } from "@mantine/core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SanitizeParameters, defaultParameters } from "@app/hooks/tools/sanitize/useSanitizeParameters";
|
||||
|
||||
interface SanitizeSettingsProps {
|
||||
parameters: SanitizeParameters;
|
||||
onParameterChange: <K extends keyof SanitizeParameters>(key: K, value: SanitizeParameters[K]) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const SanitizeSettings = ({ parameters, onParameterChange, disabled = false }: SanitizeSettingsProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const options = (Object.keys(defaultParameters) as Array<keyof SanitizeParameters>).map((key) => ({
|
||||
key: key,
|
||||
label: t(`sanitize.options.${key}`, key),
|
||||
description: t(`sanitize.options.${key}.desc`, `${key} from the PDF`),
|
||||
default: defaultParameters[key],
|
||||
}));
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Text size="sm" fw={500}>
|
||||
{t('sanitize.options.title', 'Sanitization Options')}
|
||||
</Text>
|
||||
|
||||
<Stack gap="sm">
|
||||
{options.map((option) => (
|
||||
<Checkbox
|
||||
key={option.key}
|
||||
checked={parameters[option.key]}
|
||||
onChange={(event) => onParameterChange(option.key, event.currentTarget.checked)}
|
||||
disabled={disabled}
|
||||
label={
|
||||
<div>
|
||||
<Text size="sm">{option.label}</Text>
|
||||
<Text size="xs" c="dimmed">{option.description}</Text>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
<Text size="xs" c="dimmed">
|
||||
{t('sanitize.options.note', 'Select the elements you want to remove from the PDF. At least one option must be selected.')}
|
||||
</Text>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SanitizeSettings;
|
||||
Reference in New Issue
Block a user