VALIDATION LABFILE DOWNLOAD

Date & Files

File Download

Download TXT, PDF, and CSV files and assert that the browser download event, suggested filename, and saved artifact are correct.

Intermediate

Scenario

Exports, invoices, reports, and audit files are common production surfaces. QA must prove the file actually downloads, not just that the button was clicked.

Trigger browser downloads and validate the Playwright download event.

No download yet.

Live widget · interact freely

Manual test checklist

  • 1Download the TXT file and confirm the filename ends in .txt
  • 2Download the PDF file and confirm the file is not empty
  • 3Download the CSV file and confirm headers are present
  • 4Repeat download quickly to verify no disabled or stale state remains
  • 5Confirm the result panel reports the latest filename and byte count

Expected result

Clicking each download button starts a Playwright download with the expected extension and a non-empty saved file.

Automation challenge

Use `const download = await page.waitForEvent('download')` around the click, then `await download.saveAs(...)` and assert the saved file exists with non-zero size.

Stable selectors

  • Download TXT[data-testid="download-txt"]
  • Download PDF[data-testid="download-pdf"]
  • Download CSV[data-testid="download-csv"]
  • Download result[data-testid="download-result"]

Locator strategy

Three levels from simple IDs to scoped Playwright locators. IDs and names are easy to learn but are not always the best long-term choice when labels change or components repeat.

Use simple IDs and names to understand how locating elements works. Start with one stable download button id.

1
2
3
await page.goto('https://lab.hakdogan.com/practice/file-download');

await page.locator('#download-txt').click();

Avoid as primary strategies

XPath (unless there is no alternative), long CSS chains, Tailwind-style utility class selectors, generated or unstable IDs, and volatile framework internals break when layout, styling, or DOM structure shifts.

1
2
await page.locator('.w-full.rounded-xl.border.bg-blue-500').fill('demo@example.com');
await page.locator('//div[2]/form/div[1]/input').fill('demo@example.com');

Reference Playwright spec

file-download.spec.ts
ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { test, expect } from '@playwright/test';
import { stat } from 'node:fs/promises';

test('download txt, pdf, and csv files', async ({ page }, testInfo) => {
  await page.goto('https://lab.hakdogan.com/practice/file-download');

  for (const [testId, extension] of [
    ['download-txt', '.txt'],
    ['download-pdf', '.pdf'],
    ['download-csv', '.csv'],
  ] as const) {
    const downloadPromise = page.waitForEvent('download');
    await page.getByTestId(testId).click();
    const download = await downloadPromise;

    expect(download.suggestedFilename()).toContain(extension);
    const target = testInfo.outputPath(download.suggestedFilename());
    await download.saveAs(target);
    expect((await stat(target)).size).toBeGreaterThan(0);
  }
});

Headed Test Playback

Simulated headed-browser flow — no real browser is launched.

Automation-style playback (Playwright-shaped logs). No real browser; no commands run on your machine.

Idlefile-download.spec.ts
Failure demos
https://lab.hakdogan.com/practice/file-download
playwright · headed · chromium0.00s
# awaiting Run Test · terminal scrolls automatically
Steps
  1. Starting TXT download
  2. Saving artifact
  3. Starting PDF download
  4. Starting CSV download
  5. Asserting non-empty files
StatusIdle
BrowserChromium
FrameworkPlaywright + TypeScript
Elapsed (live)--
Specfile-download.spec.ts