Export buttons and report links need browser-level tests because the page often hands the file to the browser instead of leaving visible text in the DOM. A Playwright download assertion captures that handoff and checks the file name plus saved contents.
Playwright raises a download event when a click starts a transfer. Start page.waitForEvent('download') before clicking the control, then read download.suggestedFilename() and save the stream to a test-owned output path.
A deterministic CSV response keeps the first version independent of a backend report service. For a live application, keep the same capture and file assertions, but replace the mocked route and inline link with the real page navigation and export control.
Related: How to run Playwright tests
Related: How to set Playwright output directory
Steps to assert Playwright file downloads:
- Open the existing Playwright project.
$ cd ~/projects/playwright-demo
Install Playwright first when the project does not already have @playwright/test.
Related: How to install Playwright with npm - Create tests/download.spec.ts with a deterministic CSV response and file assertions.
- tests/download.spec.ts
import { test, expect } from '@playwright/test'; import fs from 'node:fs/promises'; test('download report', async ({ page }, testInfo) => { await page.route('**/reports/monthly.csv', async route => { await route.fulfill({ status: 200, headers: { 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="report.csv"', }, body: 'month,total\nJune,42\n', }); }); await page.setContent(` <a href="https://app.example.com/reports/monthly.csv"> Download report </a> `); const downloadPromise = page.waitForEvent('download'); await page.getByRole('link', { name: 'Download report' }).click(); const download = await downloadPromise; expect(download.suggestedFilename()).toBe('report.csv'); const savedPath = testInfo.outputPath('downloads', download.suggestedFilename()); await download.saveAs(savedPath); const contents = await fs.readFile(savedPath, 'utf8'); expect(contents).toContain('June,42'); });
The page.route() block supplies the CSV fixture for a self-contained test. Replace it with the real report page and export control when the application already serves the download.
Related: How to mock network responses in Playwright - Run the download spec.
$ npx playwright test tests/download.spec.ts --reporter=line Running 1 test using 1 worker [1/1] [chromium] › tests/download.spec.ts:4:5 › download report 1 passed (768ms)
Start the event waiter before the click so Playwright cannot miss a fast download event.
Related: How to run specific Playwright tests
- Confirm the saved artifact appears in the test output directory.
$ find test-results -name report.csv -print test-results/tests-download-download-report-chromium/downloads/report.csv
testInfo.outputPath() keeps downloaded files inside the test run output directory, which prevents parallel tests from writing to the same path.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.