mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 02:54:06 +02:00
Enforce type checking in CI (#4126)
# Description of Changes Currently, the `tsconfig.json` file enforces strict type checking, but nothing in CI checks that the code is actually correctly typed. [Vite only transpiles TypeScript code](https://vite.dev/guide/features.html#transpile-only) so doesn't ensure that the TS code we're running is correct. This PR adds running of the type checker to CI and fixes the type errors that have already crept into the codebase. Note that many of the changes I've made to 'fix the types' are just using `any` to disable the type checker because the code is under too much churn to fix anything properly at the moment. I still think enabling the type checker now is the best course of action though because otherwise we'll never be able to fix all of them, and it should at least help us not break things when adding new code. Co-authored-by: James <[email protected]>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { describe, test, expect, vi, beforeEach, afterEach } from 'vitest';
|
||||
import { describe, test, expect, vi, beforeEach, afterEach, Mock } from 'vitest';
|
||||
import { renderHook, act, waitFor } from '@testing-library/react';
|
||||
import { useConvertOperation } from '../../hooks/tools/convert/useConvertOperation';
|
||||
import { useConvertParameters } from '../../hooks/tools/convert/useConvertParameters';
|
||||
@@ -54,12 +54,12 @@ const TestWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => (
|
||||
);
|
||||
|
||||
describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
|
||||
|
||||
// Mock successful API response
|
||||
mockedAxios.post.mockResolvedValue({
|
||||
(mockedAxios.post as Mock).mockResolvedValue({
|
||||
data: new Blob(['fake converted content'], { type: 'application/pdf' })
|
||||
});
|
||||
});
|
||||
@@ -74,25 +74,25 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Create mock DOCX file
|
||||
const docxFile = new File(['docx content'], 'document.docx', { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
|
||||
|
||||
|
||||
// Test auto-detection
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes([docxFile]);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
expect(paramsResult.current.parameters.fromExtension).toBe('docx');
|
||||
expect(paramsResult.current.parameters.toExtension).toBe('pdf');
|
||||
expect(paramsResult.current.parameters.isSmartDetection).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
// Test conversion operation
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
@@ -100,7 +100,7 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
[docxFile]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/file/pdf', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
});
|
||||
@@ -110,25 +110,25 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Create mock unknown file
|
||||
const unknownFile = new File(['unknown content'], 'document.xyz', { type: 'application/octet-stream' });
|
||||
|
||||
|
||||
// Test auto-detection
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes([unknownFile]);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
expect(paramsResult.current.parameters.fromExtension).toBe('file-xyz');
|
||||
expect(paramsResult.current.parameters.toExtension).toBe('pdf'); // Fallback
|
||||
expect(paramsResult.current.parameters.isSmartDetection).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
// Test conversion operation
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
@@ -136,7 +136,7 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
[unknownFile]
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/file/pdf', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
});
|
||||
@@ -144,35 +144,35 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
});
|
||||
|
||||
describe('Multi-File Smart Detection Flow', () => {
|
||||
|
||||
|
||||
test('should detect all images and use img-to-pdf endpoint', async () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Create mock image files
|
||||
const imageFiles = [
|
||||
new File(['jpg content'], 'photo1.jpg', { type: 'image/jpeg' }),
|
||||
new File(['png content'], 'photo2.png', { type: 'image/png' }),
|
||||
new File(['gif content'], 'photo3.gif', { type: 'image/gif' })
|
||||
];
|
||||
|
||||
|
||||
// Test smart detection for all images
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(imageFiles);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
expect(paramsResult.current.parameters.fromExtension).toBe('image');
|
||||
expect(paramsResult.current.parameters.toExtension).toBe('pdf');
|
||||
expect(paramsResult.current.parameters.isSmartDetection).toBe(true);
|
||||
expect(paramsResult.current.parameters.smartDetectionType).toBe('images');
|
||||
});
|
||||
|
||||
|
||||
// Test conversion operation
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
@@ -180,13 +180,13 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
imageFiles
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/img/pdf', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
});
|
||||
|
||||
|
||||
// Should send all files in single request
|
||||
const formData = mockedAxios.post.mock.calls[0][1] as FormData;
|
||||
const formData = (mockedAxios.post as Mock).mock.calls[0][1] as FormData;
|
||||
const files = formData.getAll('fileInput');
|
||||
expect(files).toHaveLength(3);
|
||||
});
|
||||
@@ -195,30 +195,30 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Create mixed file types
|
||||
const mixedFiles = [
|
||||
new File(['pdf content'], 'document.pdf', { type: 'application/pdf' }),
|
||||
new File(['docx content'], 'spreadsheet.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }),
|
||||
new File(['pptx content'], 'presentation.pptx', { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' })
|
||||
];
|
||||
|
||||
|
||||
// Test smart detection for mixed types
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(mixedFiles);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
expect(paramsResult.current.parameters.fromExtension).toBe('any');
|
||||
expect(paramsResult.current.parameters.toExtension).toBe('pdf');
|
||||
expect(paramsResult.current.parameters.isSmartDetection).toBe(true);
|
||||
expect(paramsResult.current.parameters.smartDetectionType).toBe('mixed');
|
||||
});
|
||||
|
||||
|
||||
// Test conversion operation
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
@@ -226,7 +226,7 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
mixedFiles
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/file/pdf', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
});
|
||||
@@ -236,29 +236,29 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Create mock web files
|
||||
const webFiles = [
|
||||
new File(['<html>content</html>'], 'page1.html', { type: 'text/html' }),
|
||||
new File(['zip content'], 'site.zip', { type: 'application/zip' })
|
||||
];
|
||||
|
||||
|
||||
// Test smart detection for web files
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(webFiles);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
expect(paramsResult.current.parameters.fromExtension).toBe('html');
|
||||
expect(paramsResult.current.parameters.toExtension).toBe('pdf');
|
||||
expect(paramsResult.current.parameters.isSmartDetection).toBe(true);
|
||||
expect(paramsResult.current.parameters.smartDetectionType).toBe('web');
|
||||
});
|
||||
|
||||
|
||||
// Test conversion operation
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
@@ -266,29 +266,29 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
webFiles
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/html/pdf', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
});
|
||||
|
||||
|
||||
// Should process files separately for web files
|
||||
expect(mockedAxios.post).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Web and Email Conversion Options Integration', () => {
|
||||
|
||||
|
||||
test('should send correct HTML parameters for web-to-pdf conversion', async () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const htmlFile = new File(['<html>content</html>'], 'page.html', { type: 'text/html' });
|
||||
|
||||
|
||||
// Set up HTML conversion parameters
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes([htmlFile]);
|
||||
@@ -296,15 +296,15 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
zoomLevel: 1.5
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
[htmlFile]
|
||||
);
|
||||
});
|
||||
|
||||
const formData = mockedAxios.post.mock.calls[0][1] as FormData;
|
||||
|
||||
const formData = (mockedAxios.post as Mock).mock.calls[0][1] as FormData;
|
||||
expect(formData.get('zoom')).toBe('1.5');
|
||||
});
|
||||
|
||||
@@ -312,13 +312,13 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const emlFile = new File(['email content'], 'email.eml', { type: 'message/rfc822' });
|
||||
|
||||
|
||||
// Set up email conversion parameters
|
||||
act(() => {
|
||||
paramsResult.current.updateParameter('fromExtension', 'eml');
|
||||
@@ -330,15 +330,15 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
includeAllRecipients: true
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
[emlFile]
|
||||
);
|
||||
});
|
||||
|
||||
const formData = mockedAxios.post.mock.calls[0][1] as FormData;
|
||||
|
||||
const formData = (mockedAxios.post as Mock).mock.calls[0][1] as FormData;
|
||||
expect(formData.get('includeAttachments')).toBe('false');
|
||||
expect(formData.get('maxAttachmentSizeMB')).toBe('20');
|
||||
expect(formData.get('downloadHtml')).toBe('true');
|
||||
@@ -349,13 +349,13 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const pdfFile = new File(['pdf content'], 'document.pdf', { type: 'application/pdf' });
|
||||
|
||||
|
||||
// Set up PDF/A conversion parameters
|
||||
act(() => {
|
||||
paramsResult.current.updateParameter('fromExtension', 'pdf');
|
||||
@@ -364,15 +364,15 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
outputFormat: 'pdfa'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
[pdfFile]
|
||||
);
|
||||
});
|
||||
|
||||
const formData = mockedAxios.post.mock.calls[0][1] as FormData;
|
||||
|
||||
const formData = (mockedAxios.post as Mock).mock.calls[0][1] as FormData;
|
||||
expect(formData.get('outputFormat')).toBe('pdfa');
|
||||
expect(mockedAxios.post).toHaveBeenCalledWith('/api/v1/convert/pdf/pdfa', expect.any(FormData), {
|
||||
responseType: 'blob'
|
||||
@@ -381,21 +381,21 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
});
|
||||
|
||||
describe('Image Conversion Options Integration', () => {
|
||||
|
||||
|
||||
test('should send correct parameters for image-to-pdf conversion', async () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const imageFiles = [
|
||||
new File(['jpg1'], 'photo1.jpg', { type: 'image/jpeg' }),
|
||||
new File(['jpg2'], 'photo2.jpg', { type: 'image/jpeg' })
|
||||
];
|
||||
|
||||
|
||||
// Set up image conversion parameters
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(imageFiles);
|
||||
@@ -408,15 +408,15 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
combineImages: true
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
imageFiles
|
||||
);
|
||||
});
|
||||
|
||||
const formData = mockedAxios.post.mock.calls[0][1] as FormData;
|
||||
|
||||
const formData = (mockedAxios.post as Mock).mock.calls[0][1] as FormData;
|
||||
expect(formData.get('fitOption')).toBe('fitToPage');
|
||||
expect(formData.get('colorType')).toBe('grayscale');
|
||||
expect(formData.get('autoRotate')).toBe('false');
|
||||
@@ -426,16 +426,16 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const imageFiles = [
|
||||
new File(['jpg1'], 'photo1.jpg', { type: 'image/jpeg' }),
|
||||
new File(['jpg2'], 'photo2.jpg', { type: 'image/jpeg' })
|
||||
];
|
||||
|
||||
|
||||
// Set up for separate processing
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(imageFiles);
|
||||
@@ -444,55 +444,55 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
combineImages: false
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
imageFiles
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// Should make separate API calls for each file
|
||||
expect(mockedAxios.post).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Scenarios in Smart Detection', () => {
|
||||
|
||||
|
||||
|
||||
test('should handle partial failures in multi-file processing', async () => {
|
||||
const { result: paramsResult } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const { result: operationResult } = renderHook(() => useConvertOperation(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
// Mock one success, one failure
|
||||
mockedAxios.post
|
||||
(mockedAxios.post as Mock)
|
||||
.mockResolvedValueOnce({
|
||||
data: new Blob(['converted1'], { type: 'application/pdf' })
|
||||
})
|
||||
.mockRejectedValueOnce(new Error('File 2 failed'));
|
||||
|
||||
|
||||
const mixedFiles = [
|
||||
new File(['file1'], 'doc1.txt', { type: 'text/plain' }),
|
||||
new File(['file2'], 'doc2.xyz', { type: 'application/octet-stream' })
|
||||
];
|
||||
|
||||
|
||||
// Set up for separate processing (mixed smart detection)
|
||||
act(() => {
|
||||
paramsResult.current.analyzeFileTypes(mixedFiles);
|
||||
});
|
||||
|
||||
|
||||
await act(async () => {
|
||||
await operationResult.current.executeOperation(
|
||||
paramsResult.current.parameters,
|
||||
mixedFiles
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
await waitFor(() => {
|
||||
// Should have processed at least one file successfully
|
||||
expect(operationResult.current.files.length).toBeGreaterThan(0);
|
||||
@@ -502,12 +502,12 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
});
|
||||
|
||||
describe('Real File Extension Detection', () => {
|
||||
|
||||
|
||||
test('should correctly detect various file extensions', async () => {
|
||||
const { result } = renderHook(() => useConvertParameters(), {
|
||||
wrapper: TestWrapper
|
||||
});
|
||||
|
||||
|
||||
const testCases = [
|
||||
{ filename: 'document.PDF', expected: 'pdf' },
|
||||
{ filename: 'image.JPEG', expected: 'jpg' }, // JPEG should normalize to jpg
|
||||
@@ -517,11 +517,11 @@ describe('Convert Tool - Smart Detection Integration Tests', () => {
|
||||
{ filename: '.hidden', expected: 'hidden' },
|
||||
{ filename: 'noextension', expected: '' }
|
||||
];
|
||||
|
||||
|
||||
testCases.forEach(({ filename, expected }) => {
|
||||
const detected = detectFileExtension(filename);
|
||||
expect(detected).toBe(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user