Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions e2e/pdf-splitter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { test, expect } from '@playwright/test';

test('pdf splitter: tool page loads with drop zone', async ({ page }) => {
await page.goto('/#/tools/pdf-splitter');
await expect(page.locator('.tool-layout')).toBeVisible();
await expect(page.locator('.pdf-drop-zone')).toBeVisible();
});

test('pdf splitter: drop zone contains upload hint text', async ({ page }) => {
await page.goto('/#/tools/pdf-splitter');
await expect(page.locator('.pdf-drop-zone')).toContainText('Drop a PDF here');
await expect(page.locator('.pdf-drop-zone')).toContainText('100% in-browser');
});

test('pdf splitter: appears on dev page', async ({ page }) => {
await page.goto('/#/dev');
await expect(page.getByText('PDF Page Splitter')).toBeVisible();
});

test('pdf splitter: shows error for non-PDF file', async ({ page }) => {
await page.goto('/#/tools/pdf-splitter');

// Inject a non-PDF file via the hidden file input.
const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles({
name: 'notes.txt',
mimeType: 'text/plain',
buffer: Buffer.from('hello world'),
});

await expect(page.locator('.tool-message--error')).toBeVisible();
await expect(page.locator('.tool-message--error')).toContainText(/pdf/i);
});

test('pdf splitter: processes a minimal valid PDF', async ({ page }) => {
await page.goto('/#/tools/pdf-splitter');

// Minimal valid 1-page PDF (uncompressed, hand-crafted).
const minimalPdf = `%PDF-1.4
1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj
2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj
3 0 obj<</Type/Page/MediaBox[0 0 612 792]/Parent 2 0 R/Resources<<>>>>endobj
xref
0 4
0000000000 65535 f
0000000009 00000 n
0000000058 00000 n
0000000115 00000 n
trailer<</Size 4/Root 1 0 R>>
startxref
217
%%EOF`;

const fileInput = page.locator('input[type="file"]');
await fileInput.setInputFiles({
name: 'test.pdf',
mimeType: 'application/pdf',
buffer: Buffer.from(minimalPdf),
});

// Should show at least one page card (the split result)
// The loading message or page grid should appear — wait for either the grid or an error.
await expect(
page.locator('.pdf-page-grid, .tool-message--error'),
).toBeVisible({ timeout: 15000 });
});
2 changes: 1 addition & 1 deletion e2e/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ test('search: Escape clears query and shows all tools', async ({ page }) => {
await page.locator(SEARCH).press('Escape');

await expect(page.locator(SEARCH)).toHaveValue('');
await expect(page.locator('.tool-card')).toHaveCount(15);
await expect(page.locator(".tool-card")).toHaveCount(10); // PAGE_SIZE
});

test('search: result count shown while filtering', async ({ page }) => {
Expand Down
12 changes: 12 additions & 0 deletions e2e/smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const TOOL_IDS = [
'music-box-designer',
'tuner',
'jsonpath',
'pdf-splitter',
];

test('home page loads and shows tool cards', async ({ page }) => {
Expand Down Expand Up @@ -244,6 +245,17 @@ test('music page shows tuner card', async ({ page }) => {
await expect(page.getByText('Tuner')).toBeVisible();
});

test('pdf splitter renders drop zone', async ({ page }) => {
await page.goto('/#/tools/pdf-splitter');
await expect(page.locator('.tool-layout')).toBeVisible();
await expect(page.locator('.pdf-drop-zone')).toBeVisible();
});

test('dev page shows pdf splitter card', async ({ page }) => {
await page.goto('/#/dev');
await expect(page.getByText('PDF Page Splitter')).toBeVisible();
});

for (const id of TOOL_IDS) {
test(`tool page loads: /tools/${id}`, async ({ page }) => {
// App uses HashRouter, so tool routes are under /#/tools/:id
Expand Down
Loading
Loading