Download a file

Accept downloads, trigger the file action, and keep the file evidence deterministic.

Downloads cross three boundaries: browser events, filesystem paths, and the application state that tells the user the export is ready.

Handle them deliberately: accept downloads on the context, register evidence before the click, trigger the action, then assert the user-visible result.

Accept downloads on the context

Set acceptDownloads so the browser lets the download proceed instead of blocking it.

php
$context = Playwright::chromium([
    'context' => ['acceptDownloads' => true],
]);

$page = $context->newPage();

If your project uses the builder API, configure a known download directory there instead of relying on browser defaults.

Trigger the download and assert the result

Click the control that starts the download, then assert the state the user sees.

php
$page->goto('https://app.example.test/reports');

$page->getByRole('link', ['name' => 'Export CSV'])->click();

expect($page->getByText('Your export is ready'))->toBeVisible();

This proves the application accepted the request. If the file contents are part of the contract, capture or save the file as a separate assertion.

Capture file evidence

When the file is served by a URL, register response evidence before the click:

php
$fileUrl = null;
$status = null;

$page->events()->onResponse(static function ($response) use (&$fileUrl, &$status): void {
    if (str_contains($response->url(), '/export.csv')) {
        $fileUrl = $response->url();
        $status = $response->status();
    }
});

$page->getByRole('link', ['name' => 'Export CSV'])->click();

self::assertSame(200, $status);

Some integrations may surface a DownloadInterface. When they do, use its saveAs() method to copy the file into your own artifact directory. This recipe stays on the core-safe path: response evidence plus user-visible assertions.

Expected result

The page shows the export success state, and the file evidence points to the expected export URL, status, or saved artifact.

Pitfalls

  • Register download or response evidence before the click, or you can miss the event.
  • Do not rely on browser temporary download paths in CI.
  • Do not compare generated files byte-for-byte unless the generator is deterministic.
  • Do not skip the UI assertion; a file response alone does not prove the user flow succeeded.

Go next

← All recipes