🎭 Page Assertions in Playwright: Your Website’s Checkpoint Inspectors
Imagine you’re a security guard at a magical theme park. Before guests enter different zones, you check their tickets and make sure they’re in the right place. That’s exactly what Page Assertions do in Playwright!
🌟 The Big Picture
When you test a website, you need to make sure users land on the right page, see the right title, and the page looks exactly how it should. Page Assertions are your trusty helpers that check these things automatically!
Think of them as three special inspectors:
- 🔗 URL Inspector - Checks if you’re at the right address
- 📝 Title Inspector - Checks if the page name is correct
- 📸 Screenshot Inspector - Checks if everything looks right
🔗 The toHaveURL Assertion
What Is It?
The URL is like your home address. When you tell a friend to visit your house, you give them the exact street and number. toHaveURL checks if Playwright arrived at the correct web address.
Simple Example
You want to make sure you’re on Google’s homepage:
// Go to Google
await page.goto('https://google.com');
// Check: Are we really at Google?
await expect(page).toHaveURL('https://google.com');
Real-Life Story 🏠
Imagine sending a delivery driver to “123 Main Street.” When they arrive, they look at the house number to confirm they’re at the right place. That’s toHaveURL!
Flexible Matching with Patterns
Sometimes the address has extra stuff at the end, like ?page=1. You can use patterns:
// Matches any URL containing "google"
await expect(page).toHaveURL(/google/);
// Matches URLs ending with "/search"
await expect(page).toHaveURL(/\/search$/);
// Exact match
await expect(page).toHaveURL('https://google.com/search');
When Does It Wait? ⏱️
Playwright is patient! It keeps checking the URL for a few seconds. This is helpful when:
- A page redirects you somewhere else
- The URL changes after you click a button
// Clicks login, then waits for URL to change
await page.click('#login-button');
await expect(page).toHaveURL('/dashboard');
📝 The toHaveTitle Assertion
What Is It?
Look at the tab in your browser right now. See the text? That’s the page title! toHaveTitle checks if this text is what you expect.
Simple Example
await page.goto('https://playwright.dev');
// Check the tab title
await expect(page).toHaveTitle('Playwright');
Real-Life Story 📚
When you pick up a book, you look at the cover title to make sure it’s the right book. The page title is like that book cover!
Flexible Matching
// Exact title
await expect(page).toHaveTitle('My Awesome App');
// Contains the word (using regex)
await expect(page).toHaveTitle(/Awesome/);
// Starts with something
await expect(page).toHaveTitle(/^Welcome/);
// Case insensitive match
await expect(page).toHaveTitle(/awesome/i);
Why Is Title Important? 🤔
- SEO: Search engines use titles to understand pages
- Accessibility: Screen readers announce titles
- User Experience: Users know which tab is which
// After login, title should change
await page.fill('#username', 'alice');
await page.fill('#password', 'secret');
await page.click('#login');
await expect(page).toHaveTitle('Dashboard - MyApp');
📸 The toHaveScreenshot Assertion
What Is It?
This is the visual detective! It takes a picture of your page and compares it to a saved picture. If they don’t match, something changed!
Simple Example
await page.goto('https://example.com');
// Take a screenshot and compare
await expect(page).toHaveScreenshot();
Real-Life Story 🖼️
Remember those “spot the difference” puzzles? Where you look at two pictures and find what changed? That’s exactly what toHaveScreenshot does!
First Time Running
The first time you run the test, Playwright saves a “golden” screenshot. This becomes the reference image.
test-results/
└── my-test-chromium/
└── my-test-1-actual.png ← Current screenshot
└── my-test-1-expected.png ← Reference image
Naming Your Screenshots
Give screenshots meaningful names:
// Creates "homepage.png" reference
await expect(page).toHaveScreenshot('homepage.png');
// Creates "login-form.png" reference
await expect(page).toHaveScreenshot('login-form.png');
Handling Small Differences
Sometimes tiny changes happen (like anti-aliasing). Allow some tolerance:
// Allow 5% pixel difference
await expect(page).toHaveScreenshot({
maxDiffPixelRatio: 0.05
});
// Allow up to 100 pixels to differ
await expect(page).toHaveScreenshot({
maxDiffPixels: 100
});
Screenshot Options
await expect(page).toHaveScreenshot('full-page.png', {
fullPage: true, // Capture entire page
animations: 'disabled', // Stop animations
mask: [page.locator('.ad-banner')], // Hide dynamic parts
});
When To Update Screenshots
Things change! When your design updates intentionally:
npx playwright test --update-snapshots
This creates new reference images.
🎯 Putting It All Together
Here’s a complete test using all three assertions:
import { test, expect } from '@playwright/test';
test('user can login successfully', async ({ page }) => {
// Go to login page
await page.goto('https://myapp.com/login');
// ✅ Check we're on login page
await expect(page).toHaveURL('/login');
await expect(page).toHaveTitle('Login - MyApp');
// 📸 Screenshot of login page
await expect(page).toHaveScreenshot('login-page.png');
// Fill login form
await page.fill('#email', 'user@test.com');
await page.fill('#password', 'secret123');
await page.click('button[type="submit"]');
// ✅ Check we landed on dashboard
await expect(page).toHaveURL('/dashboard');
await expect(page).toHaveTitle('Dashboard - MyApp');
// 📸 Screenshot of dashboard
await expect(page).toHaveScreenshot('dashboard.png');
});
🧠 Quick Comparison
| Assertion | What It Checks | Uses Pattern? |
|---|---|---|
toHaveURL |
Browser address bar | ✅ Yes |
toHaveTitle |
Browser tab text | ✅ Yes |
toHaveScreenshot |
Visual appearance | ❌ No |
💡 Pro Tips
Tip 1: Combine Assertions
// Both must pass
await expect(page).toHaveURL('/success');
await expect(page).toHaveTitle('Success!');
Tip 2: Use Regex for Dynamic URLs
// Matches /user/123 or /user/456
await expect(page).toHaveURL(/\/user\/\d+/);
Tip 3: Mask Dynamic Content
await expect(page).toHaveScreenshot({
mask: [
page.locator('.timestamp'),
page.locator('.random-ad'),
]
});
🎬 The Journey So Far
graph TD A["Start Test"] --> B["Navigate to Page"] B --> C{Check URL} C -->|toHaveURL| D{Check Title} D -->|toHaveTitle| E{Visual Check} E -->|toHaveScreenshot| F["✅ All Passed!"] C -->|❌ Wrong URL| G["Test Fails"] D -->|❌ Wrong Title| G E -->|❌ Visual Diff| G
🌈 Remember
toHaveURL= Are we at the right address? 🔗toHaveTitle= Does the tab say the right thing? 📝toHaveScreenshot= Does everything look correct? 📸
These three inspectors work together to make sure your website behaves exactly as expected. Like a team of friendly robots checking everything is perfect before your users see it!
🚀 You’re now ready to write confident page assertions! Go make those tests bulletproof!
