Skip to main content
File flows break in subtle ways: invalid MIME handling, upload progress issues, parser errors, and corrupted downloads. This guide covers the highest-value Playwright checks.

Upload Test Pattern

Use deterministic fixture files and assert server-side result, not just UI success toasts.
tests/files/upload.spec.ts
import { test, expect } from '@playwright/test';
import path from 'path';

test('uploads CSV successfully', async ({ page }) => {
  await page.goto('/imports');
  const filePath = path.resolve(__dirname, '../fixtures/customers.csv');

  await page.getByLabel('Upload CSV').setInputFiles(filePath);
  await page.getByRole('button', { name: 'Import' }).click();

  await expect(page.getByText('Import complete')).toBeVisible();
  await expect(page.getByText('120 rows processed')).toBeVisible();
});

Download Test Pattern

Validate filename and file size to catch empty or malformed downloads.
tests/files/download.spec.ts
import { test, expect } from '@playwright/test';

test('exports report as CSV', async ({ page }) => {
  await page.goto('/reports');

  const [download] = await Promise.all([
    page.waitForEvent('download'),
    page.getByRole('button', { name: 'Export CSV' }).click(),
  ]);

  expect(download.suggestedFilename()).toContain('.csv');
  const filePath = await download.path();
  expect(filePath).toBeTruthy();
});

Validation Cases You Should Not Skip

  • Oversized files are rejected with clear error text.
  • Invalid type (.exe, wrong MIME) is blocked.
  • Malformed CSV or JSON shows row-level error details.
  • Duplicate uploads are idempotent or clearly prevented.
  • Upload cancellation leaves no partial server records.

Keep Upload Tests Stable

  • Avoid random fixture data unless uniqueness is required.
  • Use a small fixture for smoke tests and a large one for stress tests.
  • Clean up created records by exact IDs after test completion.

Stably Features to Use for File Workflows