Remove testing and fix some

This commit is contained in:
Connor Yoh
2025-10-25 14:48:00 +01:00
parent 986bb2bd6f
commit cf9d87a339
18 changed files with 18 additions and 600 deletions

View File

@@ -3103,6 +3103,9 @@
},
"results": {
"title": "Single Page Results"
},
"settings": {
"title": "Single page options"
}
},
"pageExtracter": {
@@ -3840,7 +3843,14 @@
"used": "used",
"available": "available",
"cancel": "Cancel",
"preview": "Preview"
"preview": "Preview",
"processingMode": {
"label": "Processing mode",
"backend": "Backend",
"frontend": "Browser",
"defaultFrontendDesc": "Process locally in your browser without uploading files.",
"defaultBackendDesc": "Use the server to process files."
}
},
"config": {
"account": {

View File

@@ -185,7 +185,7 @@ describe('ChangePermissionsSettings', () => {
const permissionKeys = Object.keys(defaultParameters) as Array<keyof ChangePermissionsParameters>;
permissionKeys.forEach(permission => {
expect(mockT).toHaveBeenCalledWith(`changePermissions.permissions.${permission}.label`, permission);
expect(mockT).toHaveBeenCalledWith(`changePermissions.permissions.${permission}.label`, { defaultValue: permission });
});
});

View File

@@ -38,8 +38,8 @@ describe('MergeSettings', () => {
</TestWrapper>
);
// Should render one checkbox for each parameter
const expectedCheckboxCount = Object.keys(defaultParameters).length;
// Should render one checkbox for each parameter (excluding processingMode which is a SegmentedControl)
const expectedCheckboxCount = Object.keys(defaultParameters).filter(k => k !== 'processingMode').length;
const checkboxes = screen.getAllByRole('checkbox');
expect(checkboxes).toHaveLength(expectedCheckboxCount);
});

View File

@@ -160,10 +160,10 @@ describe('SanitizeSettings', () => {
);
// 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));
expect(mockT).toHaveBeenCalledWith('sanitize.options.title', 'Sanitization Options');
expect(mockT).toHaveBeenCalledWith('sanitize.options.removeJavaScript', { defaultValue: 'removeJavaScript' });
expect(mockT).toHaveBeenCalledWith('sanitize.options.removeEmbeddedFiles', { defaultValue: 'removeEmbeddedFiles' });
expect(mockT).toHaveBeenCalledWith('sanitize.options.note', 'Select the elements you want to remove from the PDF. At least one option must be selected.');
});
test('should not call onParameterChange when disabled', () => {

View File

@@ -1,34 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { addPageNumbersClientSide } from './addPageNumbers';
import type { AddPageNumbersParameters } from '../../components/tools/addPageNumbers/useAddPageNumbersParameters';
async function createPdf(): Promise<File> {
const doc = await PDFDocument.create();
doc.addPage([300, 400]);
doc.addPage([300, 400]);
const bytes = await doc.save();
return new File([bytes as BlobPart], 'numbers.pdf', { type: 'application/pdf' });
}
describe('addPageNumbersClientSide', () => {
it('adds page numbers to selected pages', async () => {
const file = await createPdf();
const params = {
customMargin: 'medium',
position: 8,
fontSize: 12,
fontType: 'Times',
startingNumber: 1,
pagesToNumber: '1',
customText: '{n} of {total}',
processingMode: 'frontend'
} as AddPageNumbersParameters;
const [result] = await addPageNumbersClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
expect(doc.getPageCount()).toBe(2);
// ensure document saved successfully and filename includes suffix
expect(result.name).toContain('numbersAdded');
});
});

View File

@@ -1,40 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { addStampClientSide } from './addStamp';
import type { AddStampParameters } from '../../components/tools/addStamp/useAddStampParameters';
async function createPdf(): Promise<File> {
const pdf = await PDFDocument.create();
const page = pdf.addPage([300, 300]);
page.drawText('Page 1', { x: 20, y: 260, size: 18 });
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'stamp.pdf', { type: 'application/pdf' });
}
describe('addStampClientSide', () => {
it('stamps the requested page without removing pages', async () => {
const input = await createPdf();
const params: AddStampParameters = {
stampType: 'text',
stampText: 'Approved',
alphabet: 'roman',
fontSize: 36,
rotation: 0,
opacity: 50,
position: 5,
overrideX: -1,
overrideY: -1,
customMargin: 'medium',
customColor: '#ff0000',
pageNumbers: '1',
_activePill: 'fontSize',
processingMode: 'frontend',
};
const [output] = await addStampClientSide(params, [input]);
const doc = await PDFDocument.load(await output.arrayBuffer());
expect(doc.getPageCount()).toBe(1);
expect(output.name).toBe('stamp.pdf');
});
});

View File

@@ -1,37 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { addWatermarkClientSide } from './addWatermark';
import type { AddWatermarkParameters } from '../../hooks/tools/addWatermark/useAddWatermarkParameters';
async function createSamplePdf(): Promise<File> {
const pdf = await PDFDocument.create();
const page = pdf.addPage([400, 400]);
page.drawText('Sample content', { x: 50, y: 350, size: 18 });
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'sample.pdf', { type: 'application/pdf' });
}
describe('addWatermarkClientSide', () => {
it('returns a processed PDF with the same number of pages', async () => {
const input = await createSamplePdf();
const params: AddWatermarkParameters = {
watermarkType: 'text',
watermarkText: 'Watermark',
fontSize: 24,
rotation: 0,
opacity: 50,
widthSpacer: 40,
heightSpacer: 40,
alphabet: 'roman',
customColor: '#000000',
convertPDFToImage: false,
processingMode: 'frontend',
};
const [output] = await addWatermarkClientSide(params, [input]);
const resultDoc = await PDFDocument.load(await output.arrayBuffer());
expect(resultDoc.getPageCount()).toBe(1);
expect(output.type).toBe('application/pdf');
});
});

View File

@@ -1,29 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { adjustPageScaleClientSide } from './adjustPageScale';
import type { AdjustPageScaleParameters } from '../../hooks/tools/adjustPageScale/useAdjustPageScaleParameters';
import { PageSize } from '../../hooks/tools/adjustPageScale/useAdjustPageScaleParameters';
async function createPdf(): Promise<File> {
const doc = await PDFDocument.create();
doc.addPage([300, 400]);
const bytes = await doc.save();
return new File([bytes as BlobPart], 'scale.pdf', { type: 'application/pdf' });
}
describe('adjustPageScaleClientSide', () => {
it('scales a page to the requested size', async () => {
const file = await createPdf();
const params = {
scaleFactor: 1,
pageSize: PageSize.A4,
processingMode: 'frontend'
} as AdjustPageScaleParameters;
const [result] = await adjustPageScaleClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
const page = doc.getPage(0);
expect(page.getWidth()).toBeCloseTo(595.28, 2);
expect(page.getHeight()).toBeCloseTo(841.89, 2);
});
});

View File

@@ -1,44 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument, PDFName, PDFDict } from 'pdf-lib';
import { changeMetadataClientSide } from './changeMetadata';
import type { ChangeMetadataParameters } from '../../hooks/tools/changeMetadata/useChangeMetadataParameters';
async function createEmptyPdf(): Promise<File> {
const pdf = await PDFDocument.create();
pdf.addPage([200, 200]);
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'sample.pdf', { type: 'application/pdf' });
}
describe('changeMetadataClientSide', () => {
it('applies standard metadata fields', async () => {
const file = await createEmptyPdf();
const params = {
title: 'Browser Title',
author: 'Frontend Author',
subject: 'Metadata Test',
keywords: 'stirling,pdf',
creator: 'Browser',
producer: 'Browser',
creationDate: new Date(Date.UTC(2024, 0, 1, 12, 0, 0)),
modificationDate: new Date(Date.UTC(2024, 0, 2, 12, 0, 0)),
trapped: 'True',
customMetadata: [{ id: '1', key: 'CustomKey', value: 'CustomValue' }],
deleteAll: false,
processingMode: 'frontend'
} as ChangeMetadataParameters;
const [result] = await changeMetadataClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
const infoRef = doc.context.trailerInfo.Info;
const info = infoRef ? (doc.context.lookup(infoRef, PDFDict) as PDFDict) : undefined;
expect(info).toBeDefined();
const titleObj = info?.get(PDFName.of('Title'));
expect((titleObj as any)?.decodeText()).toContain('Browser Title');
const authorObj = info?.get(PDFName.of('Author'));
expect((authorObj as any)?.decodeText()).toContain('Frontend Author');
const customKeyObj = info?.get(PDFName.of('CustomKey'));
expect((customKeyObj as any)?.decodeText()).toContain('CustomValue');
});
});

View File

@@ -1,28 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { cropPdfClientSide } from './crop';
import type { CropParameters } from '../../hooks/tools/crop/useCropParameters';
async function createPdf(width: number, height: number): Promise<File> {
const pdf = await PDFDocument.create();
pdf.addPage([width, height]);
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'crop.pdf', { type: 'application/pdf' });
}
describe('cropPdfClientSide', () => {
it('crops the page to the requested dimensions', async () => {
const input = await createPdf(400, 400);
const params: CropParameters = {
cropArea: { x: 50, y: 60, width: 200, height: 150 },
processingMode: 'frontend',
};
const [output] = await cropPdfClientSide(params, [input]);
const doc = await PDFDocument.load(await output.arrayBuffer());
const [page] = doc.getPages();
expect(page.getWidth()).toBeCloseTo(200, 3);
expect(page.getHeight()).toBeCloseTo(150, 3);
});
});

View File

@@ -1,28 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { flattenPdfClientSide } from './flatten';
import type { FlattenParameters } from '../../hooks/tools/flatten/useFlattenParameters';
async function createFormPdf(): Promise<File> {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([200, 200]);
const form = pdfDoc.getForm();
const textField = form.createTextField('name');
textField.setText('Stirling');
textField.addToPage(page, { x: 20, y: 120, width: 160, height: 24 });
const bytes = await pdfDoc.save();
return new File([bytes as BlobPart], 'form.pdf', { type: 'application/pdf' });
}
describe('flattenPdfClientSide', () => {
it('flattens interactive form fields', async () => {
const file = await createFormPdf();
const params = { flattenOnlyForms: true, processingMode: 'frontend' } as FlattenParameters;
const [flattened] = await flattenPdfClientSide(params, [file]);
const doc = await PDFDocument.load(await flattened.arrayBuffer());
const form = doc.getForm();
expect(form.getFields().length).toBe(0);
});
});

View File

@@ -1,81 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { mergePdfClientSide } from './merge';
import type { MergeParameters } from '../../hooks/tools/merge/useMergeParameters';
async function createPdf(pages: number, contentPrefix: string): Promise<File> {
const doc = await PDFDocument.create();
for (let i = 0; i < pages; i += 1) {
const page = doc.addPage([200, 200]);
page.moveTo(50, 150);
page.drawText(`${contentPrefix} Page ${i + 1}`);
}
const bytes = await doc.save();
return new File([bytes as BlobPart], `${contentPrefix}.pdf`, { type: 'application/pdf' });
}
describe('mergePdfClientSide', () => {
it('merges multiple PDFs into a single file', async () => {
const file1 = await createPdf(3, 'Doc1');
const file2 = await createPdf(2, 'Doc2');
const file3 = await createPdf(4, 'Doc3');
const params: MergeParameters = {
removeDigitalSignature: false,
generateTableOfContents: false,
processingMode: 'frontend'
};
const results = await mergePdfClientSide(params, [file1, file2, file3]);
// Should return a single merged PDF
expect(results).toHaveLength(1);
// Verify the merged PDF has all pages
const mergedDoc = await PDFDocument.load(await results[0].arrayBuffer());
expect(mergedDoc.getPageCount()).toBe(9); // 3 + 2 + 4
});
it('merges PDFs in the correct order', async () => {
const file1 = await createPdf(2, 'First');
const file2 = await createPdf(2, 'Second');
const params: MergeParameters = {
removeDigitalSignature: false,
generateTableOfContents: false,
processingMode: 'frontend'
};
const results = await mergePdfClientSide(params, [file1, file2]);
const mergedDoc = await PDFDocument.load(await results[0].arrayBuffer());
expect(mergedDoc.getPageCount()).toBe(4);
});
it('handles a single PDF file', async () => {
const file = await createPdf(5, 'Single');
const params: MergeParameters = {
removeDigitalSignature: false,
generateTableOfContents: false,
processingMode: 'frontend'
};
const results = await mergePdfClientSide(params, [file]);
expect(results).toHaveLength(1);
const doc = await PDFDocument.load(await results[0].arrayBuffer());
expect(doc.getPageCount()).toBe(5);
});
it('throws error when no files provided', async () => {
const params: MergeParameters = {
removeDigitalSignature: false,
generateTableOfContents: false,
processingMode: 'frontend'
};
await expect(mergePdfClientSide(params, [])).rejects.toThrow('No files provided');
});
});

View File

@@ -1,30 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { pageLayoutClientSide } from './pageLayout';
import type { PageLayoutParameters } from '../../hooks/tools/pageLayout/usePageLayoutParameters';
async function createPdf(pages: number): Promise<File> {
const doc = await PDFDocument.create();
for (let i = 0; i < pages; i += 1) {
doc.addPage([200, 200]);
}
const bytes = await doc.save();
return new File([bytes as BlobPart], 'layout.pdf', { type: 'application/pdf' });
}
describe('pageLayoutClientSide', () => {
it('creates an A4 page with multiple pages per sheet', async () => {
const file = await createPdf(2);
const params = {
pagesPerSheet: 2,
addBorder: true,
processingMode: 'frontend'
} as PageLayoutParameters;
const [result] = await pageLayoutClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
const page = doc.getPage(0);
expect(page.getWidth()).toBeCloseTo(595.28, 2);
expect(page.getHeight()).toBeCloseTo(841.89, 2);
});
});

View File

@@ -1,29 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { removePagesClientSide } from './removePages';
import type { RemovePagesParameters } from '../../hooks/tools/removePages/useRemovePagesParameters';
async function createPdf(pages: number): Promise<File> {
const pdf = await PDFDocument.create();
for (let i = 0; i < pages; i += 1) {
const page = pdf.addPage([300, 300]);
page.drawText(`Page ${i + 1}`, { x: 20, y: 260, size: 12 });
}
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'remove.pdf', { type: 'application/pdf' });
}
describe('removePagesClientSide', () => {
it('removes selected pages', async () => {
const input = await createPdf(3);
const params: RemovePagesParameters = {
pageNumbers: '2',
processingMode: 'frontend',
};
const [output] = await removePagesClientSide(params, [input]);
const doc = await PDFDocument.load(await output.arrayBuffer());
expect(doc.getPageCount()).toBe(2);
});
});

View File

@@ -1,42 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { reorganizePagesClientSide } from './reorganizePages';
import type { ReorganizePagesParameters } from '../../hooks/tools/reorganizePages/useReorganizePagesParameters';
async function createPdf(pages: number): Promise<File> {
const doc = await PDFDocument.create();
for (let i = 0; i < pages; i += 1) {
doc.addPage([200 + i * 20, 200]);
}
const bytes = await doc.save();
return new File([bytes as BlobPart], 'reorder.pdf', { type: 'application/pdf' });
}
describe('reorganizePagesClientSide', () => {
it('reorders pages using a custom order', async () => {
const file = await createPdf(3);
const params = {
customMode: '',
pageNumbers: '3,1,2',
processingMode: 'frontend'
} as ReorganizePagesParameters;
const [result] = await reorganizePagesClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
expect(doc.getPageCount()).toBe(3);
expect(doc.getPage(0).getWidth()).toBeCloseTo(200 + 2 * 20);
});
it('supports reverse order mode', async () => {
const file = await createPdf(2);
const params = {
customMode: 'REVERSE_ORDER',
pageNumbers: '',
processingMode: 'frontend'
} as ReorganizePagesParameters;
const [result] = await reorganizePagesClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
expect(doc.getPageCount()).toBe(2);
});
});

View File

@@ -1,37 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument, degrees } from 'pdf-lib';
import { rotatePdfClientSide } from './rotate';
import type { RotateParameters } from '../../hooks/tools/rotate/useRotateParameters';
async function createSamplePdf(rotation: number = 0): Promise<File> {
const pdf = await PDFDocument.create();
const page = pdf.addPage([200, 200]);
page.setRotation(degrees(rotation));
const bytes = await pdf.save();
return new File([bytes as BlobPart], 'sample.pdf', { type: 'application/pdf' });
}
describe('rotatePdfClientSide', () => {
it('rotates pages by the requested angle', async () => {
const input = await createSamplePdf(0);
const params = { angle: 90, processingMode: 'frontend' } as RotateParameters;
const [rotated] = await rotatePdfClientSide(params, [input]);
const resultDoc = await PDFDocument.load(await rotated.arrayBuffer());
const [page] = resultDoc.getPages();
expect(page.getRotation().angle).toBe(90);
});
it('returns copies when no rotation requested', async () => {
const input = await createSamplePdf(180);
const params = { angle: 360, processingMode: 'frontend' } as RotateParameters;
const [rotated] = await rotatePdfClientSide(params, [input]);
const resultDoc = await PDFDocument.load(await rotated.arrayBuffer());
const [page] = resultDoc.getPages();
expect(page.getRotation().angle).toBe(180);
expect(rotated.name).toBe(input.name);
});
});

View File

@@ -1,25 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { singleLargePageClientSide } from './singleLargePage';
import type { SingleLargePageParameters } from '../../hooks/tools/singleLargePage/useSingleLargePageParameters';
async function createPdf(): Promise<File> {
const doc = await PDFDocument.create();
doc.addPage([200, 300]);
doc.addPage([200, 400]);
const bytes = await doc.save();
return new File([bytes as BlobPart], 'multi.pdf', { type: 'application/pdf' });
}
describe('singleLargePageClientSide', () => {
it('stacks pages vertically into one page', async () => {
const file = await createPdf();
const params = { processingMode: 'frontend' } as SingleLargePageParameters;
const [result] = await singleLargePageClientSide(params, [file]);
const doc = await PDFDocument.load(await result.arrayBuffer());
const page = doc.getPage(0);
expect(page.getHeight()).toBeCloseTo(700);
expect(page.getWidth()).toBeCloseTo(200);
});
});

View File

@@ -1,108 +0,0 @@
import { describe, expect, it } from 'vitest';
import { PDFDocument } from 'pdf-lib';
import { splitPdfClientSide } from './split';
import type { SplitParameters } from '../../hooks/tools/split/useSplitParameters';
import { SPLIT_METHODS } from '../../constants/splitConstants';
async function createPdf(pages: number): Promise<File> {
const doc = await PDFDocument.create();
for (let i = 0; i < pages; i += 1) {
const page = doc.addPage([200, 200]);
page.moveTo(50, 150);
page.drawText(`Page ${i + 1}`);
}
const bytes = await doc.save();
return new File([bytes as BlobPart], 'split.pdf', { type: 'application/pdf' });
}
describe('splitPdfClientSide', () => {
it('splits pages into separate files based on page list', async () => {
const file = await createPdf(4);
const params = {
method: SPLIT_METHODS.BY_PAGES,
pages: '1,2,4',
processingMode: 'frontend'
} as SplitParameters;
const outputs = await splitPdfClientSide(params, [file]);
expect(outputs).toHaveLength(3);
const first = await PDFDocument.load(await outputs[0].arrayBuffer());
expect(first.getPageCount()).toBe(1);
const last = await PDFDocument.load(await outputs[2].arrayBuffer());
expect(last.getPageCount()).toBe(1);
});
it('splits by page count (every N pages)', async () => {
const file = await createPdf(10);
const params = {
method: SPLIT_METHODS.BY_PAGE_COUNT,
splitValue: '3',
processingMode: 'frontend'
} as SplitParameters;
const outputs = await splitPdfClientSide(params, [file]);
// 10 pages split every 3 = 4 documents (3+3+3+1)
expect(outputs).toHaveLength(4);
const doc1 = await PDFDocument.load(await outputs[0].arrayBuffer());
expect(doc1.getPageCount()).toBe(3);
const doc2 = await PDFDocument.load(await outputs[1].arrayBuffer());
expect(doc2.getPageCount()).toBe(3);
const doc3 = await PDFDocument.load(await outputs[2].arrayBuffer());
expect(doc3.getPageCount()).toBe(3);
const doc4 = await PDFDocument.load(await outputs[3].arrayBuffer());
expect(doc4.getPageCount()).toBe(1);
});
it('splits by document count (into N equal parts)', async () => {
const file = await createPdf(10);
const params = {
method: SPLIT_METHODS.BY_DOC_COUNT,
splitValue: '3',
processingMode: 'frontend'
} as SplitParameters;
const outputs = await splitPdfClientSide(params, [file]);
// 10 pages split into 3 docs = 4+4+2 pages (or 4+3+3)
expect(outputs).toHaveLength(3);
const totalPages = outputs.reduce(async (sum, output) => {
const doc = await PDFDocument.load(await output.arrayBuffer());
return (await sum) + doc.getPageCount();
}, Promise.resolve(0));
expect(await totalPages).toBe(10);
});
it('splits by size (file size threshold)', async () => {
const file = await createPdf(10);
// Create a small size threshold that will force multiple splits
// Approximate size: a minimal PDF is ~1-2KB per page, so 5KB should split
const params = {
method: SPLIT_METHODS.BY_SIZE,
splitValue: '5000', // 5KB
processingMode: 'frontend'
} as SplitParameters;
const outputs = await splitPdfClientSide(params, [file]);
// Should have multiple output files
expect(outputs.length).toBeGreaterThan(1);
// Verify each output is under or near the threshold (with some tolerance for PDF structure)
for (const output of outputs) {
const size = output.size;
// Allow some overhead for PDF structure, but it shouldn't be massively over
expect(size).toBeLessThan(10000); // 10KB max with overhead
}
// Verify total page count is preserved
const totalPages = await outputs.reduce(async (sum, output) => {
const doc = await PDFDocument.load(await output.arrayBuffer());
return (await sum) + doc.getPageCount();
}, Promise.resolve(0));
expect(totalPages).toBe(10);
});
});