VALIDATION LABPDF DOWNLOAD

Date & Files

PDF Download

Validate a dedicated sample PDF export: the download starts, the filename ends with .pdf, and the saved file is not empty.

Intermediate

Scenario

PDF exports often render server-side and can silently fail into empty files. A real download assertion catches broken report generation early.

Dedicated PDF download surface for filename and non-empty file checks.

No PDF download yet.

Live widget · interact freely

Manual test checklist

  • 1Click Download sample PDF
  • 2Confirm the browser starts a file download
  • 3Confirm the filename uses the .pdf extension
  • 4Open or inspect the file and confirm it is not empty
  • 5Repeat once to verify the button remains usable

Expected result

Download sample PDF emits a browser download named sample-validation-report.pdf and the saved file has bytes.

Automation challenge

Wrap the click with `page.waitForEvent('download')`, assert `download.suggestedFilename().endsWith('.pdf')`, save it, then assert file size > 0.

Stable selectors

  • Download sample PDF[data-testid="pdf-download-button"]
  • PDF result[data-testid="pdf-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.

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

await page.locator('#pdf-download-button').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

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

test('sample pdf download is non-empty', async ({ page }, testInfo) => {
  await page.goto('https://lab.hakdogan.com/practice/pdf-download');

  const downloadPromise = page.waitForEvent('download');
  await page.getByTestId('pdf-download-button').click();
  const download = await downloadPromise;

  expect(download.suggestedFilename()).toMatch(/\.pdf$/);
  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.

Idlepdf-download.spec.ts
Failure demos
https://lab.hakdogan.com/practice/pdf-download
playwright · headed · chromium0.00s
# awaiting Run Test · terminal scrolls automatically
Steps
  1. Clicking PDF download
  2. Awaiting download event
  3. Asserting .pdf filename
  4. Asserting non-empty artifact
StatusIdle
BrowserChromium
FrameworkPlaywright + TypeScript
Elapsed (live)--
Specpdf-download.spec.ts