Talking About TestingATT</>
Advanced Playwright Web Testing

Score 100% on the quiz to continue

Lesson
Free Preview

Intercepting network requests with page.route()

Observe and take control of the network with page.route() to test independently from the backend.

Most web apps are only as reliable as the backend they talk to. When your tests depend on a real API, they become slow and flaky: the server can be down, the data can change, and error or edge-case scenarios are hard to reproduce on demand.

Playwright lets you take control of that network traffic. With page.route() you register a handler for requests that match a URL pattern, and inside that handler you decide what to do: let the request through (route.continue()), respond with your own data (route.fulfill()), or fail it (route.abort()).

In this first lesson, we start gently: we observe the GET /customers request that EngageSphere makes and let it continue to the real server, so we can see exactly what the app asks for as the user paginates and filters.

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

test('loads the customers table', async ({ page }) => {
  await page.route('**/customers*', async (route) => {
    console.log('Request URL:', route.request().url())
    await route.continue()
  })

  await page.goto('/')

  await expect(page.getByRole('table')).toBeVisible()
})

Commands overview 📖

test.describe

Groups related test cases under a shared title, which keeps the suite organized and the report easier to read.

Syntax:

test.describe(title, () => { /* tests */ })

Example:

test.describe('EngageSphere', () => {
  // hooks and tests go here
})

test.beforeEach

Registers a hook that runs before each test in its scope. It is ideal for setup steps every test shares, such as registering a route and navigating to the page under test.

Syntax:

test.beforeEach(async ({ page }) => { /* ... */ })

Example:

test.beforeEach(async ({ page }) => {
  await page.goto('/')
})

test

Declares a single test case. It receives a title and an async callback, and Playwright injects its fixtures (such as page) as the callback's argument.

Syntax:

test(title, async ({ page }) => { /* ... */ })

Example:

test('loads the customers table', async ({ page }) => {
  // arrange, act, and assert here
})

page.route()

Registers a handler for every request whose URL matches the given pattern (a glob string, a regular expression, or a predicate function). The handler receives the route and can inspect route.request().

Syntax:

await page.route(urlPattern, handler)

Example:

await page.route('**/customers*', async (route) => {
  await route.continue()
})
👨‍🏫 Register the route before navigating or triggering the request, otherwise the request may fire before the handler exists.

route.continue()

Sends the intercepted request on to the real server unchanged. Use it when you only want to observe (or slightly tweak) a request rather than mock it.

Syntax:

await route.continue()

Example:

await page.route('**/customers*', async (route) => {
  expect(route.request().method()).toBe('GET')
  await route.continue()
})
👨‍🏫 route.request() exposes the url(), method(), headers(), and postData() of the intercepted request, which is handy for assertions.

route.request()

Returns the Request object for the intercepted request, so you can assert on its details, such as the HTTP method.

Syntax:

route.request()

Example:

await page.route('**/customers*', async (route) => {
  expect(route.request().method()).toBe('GET')
  await route.continue()
})

Suggested content 📚

Exercise 🎯

Write a test that visits EngageSphere, intercepts the GET /customers request with page.route(), and lets it continue to the real server. Assert that the customers table becomes visible. Inside the route handler, assert that the request method is GET, and log its URL so you can see how the query string changes.

🙊 Use the glob pattern '**/customers*' so the route matches regardless of the exact host or path segment used by the deployed app.

👨‍🏫 Wrap your tests in a test.describe block (for example, titled EngageSphere), and use a test.beforeEach hook to register the route and navigate to the app before each test, so every test starts from the same setup.

Run the test in headed mode with npx playwright test --headed and watch the table load, then check your terminal for the logged request URL.

Show the world what you learned 🌎

To show your professional network what you learned in this lesson, post the following on LinkedIn.

I am taking the "Advanced Playwright Web Testing" course by @Walmyr Lima e Silva Filho at the @Talking About Testing school, where I learned how to intercept and observe network requests with Playwright's page.route(). #TalkingAboutTesting #TATSchool #AdvancedPlaywrightWebTesting #Playwright

👨‍🏫 Remember to tag me in your post. Here is my LinkedIn profile.

Quiz

Question 1 of 2
Score: 0

What does `page.route()` let you do?

Score 100% on the quiz to continue