Blog # 18 :🎪 Playwright Hooks: Your Test Suite’s Best Friends!

Published on April 24, 2025

🎩 Why Hooks? The Magic Behind the Scenes

When writing automated tests, especially for web applications, repetitive tasks like logging in before each test or cleaning up after the test run can quickly clutter your code. If you've found yourself copying the same setup code into multiple tests, you're not alone!

Luckily, Playwright offers a powerful feature to solve this — hooks.

Imagine you’re hosting a party 🥳. You wouldn’t clean the house after every guest leaves, right? Instead, you’d:

🏗️ Setup once (decorate, cook food) → beforeAll

🗑️ Clean as you go (refill snacks, wipe spills) → beforeEach/afterEach

💣Nuclear cleanup after everyone leaves → afterAll

In testing terms: Hooks automate repetitive tasks so your tests can focus on what matters.

🔮 Meet the 4 Hooks


🚀 Your Code in Action: Login/Logout Flow

Let’s automate a shopping site test (your code!).

Step 1: beforeEach – The “Welcome Mat”

Why it rocks: Every test starts fresh, logged in, and cookie-free!

test.beforeEach(async ({ page }) => {  
  // 🎯 Navigate to login  
  await page.goto('https://www.automationexercise.com/login');  
  // 🍪 Crush cookies (popup)  
  await page.locator('p.fc-button-label').nth(0).click();  
  // 🔑 Login steps  
  await page.locator('[data-qa="login-email"]').fill('[email protected]');  
  await page.getByPlaceholder('Password').fill('password01');  
  await page.getByRole('button', { name: 'Login' }).click();  
  // ✅ Verify login success  
  await expect(page).toHaveURL('https://www.automationexercise.com/');  
});  

Step 2: afterEach – The “Goodbye Kiss”

test.afterEach(async ({ page }) => {  
  // 👋 Logout after every test  
  await page.locator('[href="/logout"]').click();  
});  

Why it matters: No test messes with another’s session!

Step 3: Tests – Lean & Mean!

// 🏡 Test 1: Check homepage content  
test('validate home content after login', async ({ page }) => {  
  await expect(page.locator('div.features_items')).toBeVisible();  
  await expect(page.locator('h2:has-text("Features Items")')).toBeVisible();  
});  

// 🛒 Test 2: Add to cart  
test('Add product to the cart', async ({ page }) => {  
  await page.locator('div.productinfo a').first().click();  
  await page.locator('[data-dismiss="modal"]').click();  
});  

No login code! Hooks handle it all. 🎉

📹 Watch the Code in Action!



🤔 Quiz Time! Which Hook Would You Use?

Seed a database before all tests → beforeAll

Reset a form after each test → afterEach

Close all browser tabs after the entire suite → afterAll

(How’d you do? Comment below! 💬)

💡 Pro Tips for Hook Masters

Avoid waitForTimeout: Use waitForLoadState or assertions instead.

Group hooks with test.describe: Scope hooks to specific test groups.

Use beforeAll sparingly: Shared state can cause test pollution!

🏁 Conclusion: Hooked Yet?

Hooks turn chaotic test suites into well-oiled machines. Start with beforeEach/afterEach, then explore beforeAll/afterAll for big setups.


Your code already nails the essentials – now go automate all the things!