Add tests for Remove Password

This commit is contained in:
James Brunton 2025-08-18 09:56:48 +01:00
parent 7de298ea81
commit f03bf6258b
3 changed files with 312 additions and 0 deletions

View File

@ -0,0 +1,127 @@
import { describe, expect, test, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { MantineProvider } from '@mantine/core';
import RemovePasswordSettings from './RemovePasswordSettings';
import { defaultParameters } from '../../../hooks/tools/removePassword/useRemovePasswordParameters';
// 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('RemovePasswordSettings', () => {
const mockOnParameterChange = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
});
test('should render password input field', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
expect(screen.getByText('mock-removePassword.password.label')).toBeInTheDocument();
});
test('should call onParameterChange when password is entered', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const passwordInput = screen.getByPlaceholderText('mock-removePassword.password.placeholder');
fireEvent.change(passwordInput, { target: { value: 'test-password' } });
expect(mockOnParameterChange).toHaveBeenCalledWith('password', 'test-password');
});
test('should display current password value', () => {
const parametersWithPassword = { ...defaultParameters, password: 'current-password' };
render(
<TestWrapper>
<RemovePasswordSettings
parameters={parametersWithPassword}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const passwordInput = screen.getByPlaceholderText('mock-removePassword.password.placeholder') as HTMLInputElement;
expect(passwordInput.value).toBe('current-password');
});
test('should disable password input when disabled prop is true', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
disabled={true}
/>
</TestWrapper>
);
const passwordInput = screen.getByPlaceholderText('mock-removePassword.password.placeholder');
expect(passwordInput).toBeDisabled();
});
test('should enable password input when disabled prop is false', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
disabled={false}
/>
</TestWrapper>
);
const passwordInput = screen.getByPlaceholderText('mock-removePassword.password.placeholder');
expect(passwordInput).not.toBeDisabled();
});
test('should show password input as required', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
const passwordInput = screen.getByPlaceholderText('mock-removePassword.password.placeholder');
expect(passwordInput).toHaveAttribute('required');
});
test('should call translation function with correct keys', () => {
render(
<TestWrapper>
<RemovePasswordSettings
parameters={defaultParameters}
onParameterChange={mockOnParameterChange}
/>
</TestWrapper>
);
expect(mockT).toHaveBeenCalledWith('removePassword.password.label', 'Current Password');
expect(mockT).toHaveBeenCalledWith('removePassword.password.placeholder', 'Enter current password');
});
});

View File

@ -0,0 +1,104 @@
import { describe, expect, test, vi, beforeEach } from 'vitest';
import { renderHook } from '@testing-library/react';
import { useRemovePasswordOperation } from './useRemovePasswordOperation';
import type { RemovePasswordParameters } from './useRemovePasswordParameters';
// Mock the useToolOperation hook
vi.mock('../shared/useToolOperation', () => ({
useToolOperation: vi.fn()
}));
// Mock the translation hook
const mockT = vi.fn((key: string) => `translated-${key}`);
vi.mock('react-i18next', () => ({
useTranslation: () => ({ t: mockT })
}));
// Mock the error handler
vi.mock('../../../utils/toolErrorHandler', () => ({
createStandardErrorHandler: vi.fn(() => 'error-handler-function')
}));
// Import the mocked function
import { ToolOperationConfig, ToolOperationHook, useToolOperation } from '../shared/useToolOperation';
describe('useRemovePasswordOperation', () => {
const mockUseToolOperation = vi.mocked(useToolOperation);
const getToolConfig = (): ToolOperationConfig<RemovePasswordParameters> => mockUseToolOperation.mock.calls[0][0];
const mockToolOperationReturn: ToolOperationHook<unknown> = {
files: [],
thumbnails: [],
downloadUrl: null,
downloadFilename: '',
isLoading: false,
errorMessage: null,
status: '',
isGeneratingThumbnails: false,
progress: null,
executeOperation: vi.fn(),
resetResults: vi.fn(),
clearError: vi.fn(),
cancelOperation: vi.fn(),
};
beforeEach(() => {
vi.clearAllMocks();
mockUseToolOperation.mockReturnValue(mockToolOperationReturn);
});
test.each([
{
description: 'with valid password',
password: 'test-password'
},
{
description: 'with complex password',
password: 'C0mpl3x@P@ssw0rd!'
},
{
description: 'with single character password',
password: 'a'
}
])('should create form data correctly $description', ({ password }) => {
renderHook(() => useRemovePasswordOperation());
const callArgs = getToolConfig();
const buildFormData = callArgs.buildFormData;
const testParameters: RemovePasswordParameters = {
password
};
const testFile = new File(['test content'], 'test.pdf', { type: 'application/pdf' });
const formData = buildFormData(testParameters, testFile as any);
// Verify the form data contains the file
expect(formData.get('fileInput')).toBe(testFile);
// Verify password parameter
expect(formData.get('password')).toBe(password);
});
test('should use correct translation for error messages', () => {
renderHook(() => useRemovePasswordOperation());
expect(mockT).toHaveBeenCalledWith(
'removePassword.error.failed',
'An error occurred while removing the password from the PDF.'
);
});
test.each([
{ property: 'multiFileEndpoint' as const, expectedValue: false },
{ property: 'endpoint' as const, expectedValue: '/api/v1/security/remove-password' },
{ property: 'filePrefix' as const, expectedValue: 'translated-removePassword.filenamePrefix_' },
{ property: 'operationType' as const, expectedValue: 'removePassword' }
])('should configure $property correctly', ({ property, expectedValue }) => {
renderHook(() => useRemovePasswordOperation());
const callArgs = getToolConfig();
expect(callArgs[property]).toBe(expectedValue);
});
});

View File

@ -0,0 +1,81 @@
import { describe, expect, test } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { useRemovePasswordParameters, defaultParameters } from './useRemovePasswordParameters';
describe('useRemovePasswordParameters', () => {
test('should initialize with default parameters', () => {
const { result } = renderHook(() => useRemovePasswordParameters());
expect(result.current.parameters).toStrictEqual(defaultParameters);
});
test('should update password parameter', () => {
const { result } = renderHook(() => useRemovePasswordParameters());
act(() => {
result.current.updateParameter('password', 'test-password');
});
expect(result.current.parameters.password).toBe('test-password');
});
test('should reset parameters to defaults', () => {
const { result } = renderHook(() => useRemovePasswordParameters());
// First, change the password
act(() => {
result.current.updateParameter('password', 'test-password');
});
expect(result.current.parameters.password).toBe('test-password');
// Then reset
act(() => {
result.current.resetParameters();
});
expect(result.current.parameters).toStrictEqual(defaultParameters);
});
test('should return correct endpoint name', () => {
const { result } = renderHook(() => useRemovePasswordParameters());
expect(result.current.getEndpointName()).toBe('remove-password');
});
test.each([
{
description: 'with valid password',
password: 'valid-password',
expectedValid: true
},
{
description: 'with empty password',
password: '',
expectedValid: false
},
{
description: 'with whitespace only password',
password: ' \t ',
expectedValid: true
},
{
description: 'with password containing special characters',
password: 'p@ssw0rd!',
expectedValid: true
},
{
description: 'with single character password',
password: 'a',
expectedValid: true
}
])('should validate parameters correctly $description', ({ password, expectedValid }) => {
const { result } = renderHook(() => useRemovePasswordParameters());
act(() => {
result.current.updateParameter('password', password);
});
expect(result.current.validateParameters()).toBe(expectedValid);
});
});