Skip to Content
Course content

127: End-to-End Testing with Playwright or Cypress

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Should I go with Playwright or Cypress?

This is the debate of the year in the JS community. Honestly? Both are fantastic, but they approach the problem differently. Cypress runs directly inside the browser, which makes the developer experience incredible—you can see exactly what's happening in real-time. However, it has some limitations with things like multiple tabs or iframes because it's bound by the browser's security sandbox.

Playwright, on the other hand, uses the CDP (Chrome DevTools Protocol) to control the browser from the outside. I've found it's generally faster, handles multi-tab workflows much better, and has a more robust "auto-wait" system. If you're starting a project today, I usually lean toward Playwright. It feels more like how a real user interacts with a machine, and the ability to run tests across Chromium, Firefox, and WebKit simultaneously is a huge win.

What does a real E2E test actually look like in practice?

Stop thinking about testing individual functions; E2E is about testing the user's journey. Let's say you're building an e-commerce site. You don't care if the `addToCart` function works in isolation; you care that a user can find a product, click a button, and see that item in their cart. Here is how I'd write that using Playwright:

import { test, expect } from '@playwright/test';

test('user can add a limited edition sneaker to the cart', async ({ page }) => {
  // Navigate to the product page
  await page.goto('https://myshop.com/products/air-max-90');

  // Select a size and add to cart
  await page.selectOption('select#size', '10');
  await page.click('button#add-to-cart');

  // Go to the cart page
  await page.click('a#cart-icon');

  // Verify the item is actually there
  const cartItem = page.locator('.cart-item-title');
  await expect(cartItem).toContainText('Air Max 90');
  
  // Ensure the price is correct
  const totalPrice = page.locator('.total-price');
  await expect(totalPrice).toHaveText('$120.00');
});

How do I stop my tests from failing randomly (flakiness)?

Flakiness is the absolute worst part of E2E testing. You'll run a test ten times, and it fails on the eleventh for no apparent reason. This usually happens because the test is faster than your app. You're trying to click a button that hasn't finished rendering yet.

My biggest piece of advice: never use hard-coded sleeps (like await page.waitForTimeout(3000)). That's a lazy habit that slows down your CI pipeline and still doesn't guarantee the element is ready. Instead, rely on "web-first assertions." In the example above, await expect(cartItem).toContainText(...) doesn't just check the text once; it polls the page for a few seconds until the condition is met. If your app is slow, Playwright waits. If it's fast, the test moves on immediately. It's much more resilient.

Can I skip the login screen for every single test?

If you have 50 tests and each one starts by typing a username and password into a login form, your test suite is going to be painfully slow. It's also a waste of resources.

The professional way to handle this is through "Storage State." You essentially perform the login once in a global setup phase, save the cookies and local storage to a JSON file, and then tell your tests to load that state before they start. You're effectively "injecting" the session into the browser.

// playwright.config.ts
export default defineConfig({
  use: {
    // Tell all tests to use this saved authentication state
    storageState: 'auth.json',
  },
});

I usually set up a separate "auth" script that runs before the main test suite. It logs in, saves auth.json, and then the rest of your tests start already logged in. It saves minutes of execution time per run.




📋 Practical Task

Exercise: Automating the Guest Checkout Flow for the Shoe Store

Your task is to write a Playwright test script that validates the "Guest Checkout" experience. You should avoid using a logged-in state for this specific test, as you are simulating a first-time visitor.

Requirements:

  • Navigate to the /products/runner-pro page.
  • Select the "Blue" color option and "Size 11".
  • Click "Add to Cart" and navigate to the checkout page.
  • Fill out the guest checkout form with a dummy email (tester@example.com) and a shipping address.
  • Click "Place Order".
  • Assert that the final page contains a "Thank you for your order!" confirmation message.

Constraint: Do not use waitForTimeout(). Use Playwright's built-in assertions or locators to ensure the test is stable regardless of network latency.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.