Playwright

Lesson 11 of 17

Lesson ยท 25 min

Page objects

The problem with copied steps

Imagine 40 tests for the shop. Each one adds a product with the same four lines of code. One day the developers change the button text from Add to cart to Buy. Now you must change 40 tests.

A page object solves this. It is a class that knows how to use one page. It holds the locators and the steps of the page in one place. The tests call the steps by name.

A page object in JavaScript

A page object is a plain class. It gets the page in its constructor, and it saves the locators in properties.

class ShopPage {
  constructor(page) {
    this.page = page;
    this.cards = page.getByTestId('product-card');
  }

  async addToCart(name) {
    const card = this.cards.filter({ hasText: name });
    await card.getByRole('button', { name: 'Add to cart' }).click();
  }
}

A test makes one for its own page, and calls the methods:

test('adds a product', async ({ page }) => {
  const shop = new ShopPage(page);
  await shop.open();
  await shop.addToCart('Blue Mug');
});

Now the test says what happens, and the class says how. When the button changes, you change one line in the class.

What belongs in a page object

  • Locators. Save the locators that the tests use often, as properties.
  • Steps. Add a method for each thing that a user does on the page: search(text), addToCart(name), openCart().
  • Waits. A step that changes the page should wait for its result, so that the next line of the test starts at a calm page. In addToCart, wait for the confirmation text.

What does not belong in a page object

Assertions about the behavior that a test checks. The test says what must be true. The page object says how to get there. If you hide the expect calls in the class, a reader cannot see what the test checks. Return a locator from the class, and let the test check it.

It is fine for a page object to wait with an assertion, as open() does when it waits for the six products. That wait is part of "the page is ready".

Several pages

A real app has many pages. Make one class for each page, or for each large part of a page, such as a header or a dialog. A test can use several of them together.

Your turn

The file has a start of ShopPage. Add the steps, and write three tests that use them. Each test names a bug that the tests must catch.

Tasks

3 to do

  1. Task 1, not checked yet. Add the method addToCart(name) to ShopPage. It finds the card of the product with that name, clicks Add to cart on it, and waits until the text Added <name> to your cart. is visible. Then add a test named shows the number of products in the cart. It uses ShopPage to open the shop, add Blue Mug and Notebook, and check that cartCount shows 1 and then 2.

  2. Task 2, not checked yet. Add the method search(text) to ShopPage. It fills the search box and presses Enter. Add a test named searches without caring about case that searches for LAMP and checks that there is one product card with the heading Desk Lamp.

  3. Task 3, not checked yet. Add the method openCart() to ShopPage. It clicks the link that has the text Cart. Add a test named ships for free over 50 dollars. Add the Backpack, open the cart, and check that the shipping is Free and the total is $59.00.

Task 1 of 3

Add the method addToCart(name) to ShopPage. It finds the card of the product with that name, clicks Add to cart on it, and waits until the text Added <name> to your cart. is visible. Then add a test named shows the number of products in the cart. It uses ShopPage to open the shop, add Blue Mug and Notebook, and check that cartCount shows 1 and then 2.

All tasks

example.spec.js

Ctrl+Enter runs your tests. Ctrl+Shift+Enter checks it. Press Esc, then Tab, to leave the editor.

Practice browser

The sample app is ready

The results of your tests show here. Press Run tests to watch them run in the practice browser.