Component Lab H · Safe uploads and downloads

Files Lab

Automate single, multiple, dropzone, image, CSV, progress, rejection, and download flows backed by a deliberately non-executable upload pipeline.

PRACTICE FIXTURE — intentionally built for automation practice

Single and multiple uploads

Native file inputs share the same server allowlist, storage quota, progress, and visible response.

0%

No files uploaded.

    File dropzone

    The shared dropzone accepts drag/drop and keyboard activation, then uses the same secure upload path.

    Drop safe files here or press Enter to choose

    Image and CSV previews

    Images preview from the local selection; CSV cells are parsed and inserted with textContent, never raw HTML.

    Select an image or CSV to preview it.

    Rejection paths

    Client guidance mirrors the authoritative server checks; renamed scripts, HTML, active SVG, traversal names, oversize files, and quota overflow are rejected.

    Allowed: PNG, JPEG, CSV, plain TXT, and PDF. Maximum size: 2 MiB each. The server returns a stable error code without storing rejected bytes.

    No rejected file observed.

    Static and dynamic downloads

    Each response sends attachment disposition with a deterministic suggested filename.

    Download after delay

    No API-triggered download requested.

    Passing examples

    Start with observable behavior

    These snippets match executable tests stored inexamples/playwright-ts/.

    Upload example
    await page.getByLabel('Single safe file').setInputFiles({
      name: 'people.csv',
      mimeType: 'text/csv',
      buffer: Buffer.from('name,team\nAsha,QA'),
    });
    await expect(page.getByTestId('upload-result')).toContainText('people.csv');
    Download example
    const downloadPromise = page.waitForEvent('download');
    await page.getByRole('link', { name: 'Download static TXT' }).click();
    const download = await downloadPromise;
    expect(download.suggestedFilename()).toBe('testheon-practice-notes.txt');