VALIDATION LAB•FILE 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.
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.
123
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.
12
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
123456789101112131415161718192021
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.
file-download.spec.ts- Starting TXT download
- Saving artifact
- Starting PDF download
- Starting CSV download
- Asserting non-empty files