arbisoft brand logo
arbisoft brand logo
Contact Us

Playwright + POM: A Complete Guide to Clean and Maintainable Tests

Muhammad 's profile picture
Muhammad HarisPosted on
7-8 Min Read Time

End-to-end (e2e) testing has become a critical part of modern web development. As applications grow more complex, test automation must evolve to stay reliable, readable, and easy to maintain. This is where Playwright and the Page Object Model (POM) come together as a powerful combination.

 

Playwright is a fast, modern automation framework built by Microsoft that supports multiple browsers and offers an excellent developer experience. The Page Object Model (POM), on the other hand, is a design pattern that helps organize test code in a clean and scalable manner.

 

In this blog, we are going to learn how to create a page object model (POM) design pattern or framework using Playwright. The POM is used in test automation. It helps QAs to organize automation tests or test code by separating page objects from the main test code.

 

In POM, we use a class to represent each web page, and the class contains the elements of the web page, like dropdowns, fields, buttons, and links, etc. It also has actions that are used to perform actions on the page elements, like entering data in a field, clicking on a button, etc. 

 

So, in simple terms, in POM, a test interacts with the respective page class instead of using locators/selectors directly.

 

In POM, we create one class for one web page. The page class contains locators and actions, whereas the test class uses page methods to perform actions. The test class also contains assertions. 

 

For example:

Without POM (Bad Practice) 

  • await page.fill('#username', 'Haris');
  • await page.fill('#password', '1234');
  • await page.click('#login-button');

 

With POM (Good Practice)

  • await loginPage.login('Haris', '1234');

 

Project Setup

Let’s start with creating a new folder on your MAC/Windows machine and renaming it, e.g., playwright_API_testing. Open the folder in your IDE, e.g., VS Code. Now, go to the terminal and run the following command:

 

 npm init -y 

 

It creates a package.json file and also initializes a Node project in the folder.

Now, we need a playwright, and I want to install the latest. Run the following command:

  • npm init playwright@latest
  • During setup, it asks for 
    • The language JavaScript/TypeScript?
    • Where do you want to put the tests?
    • Add a GitHub action workflow?
    • Install Playwright browsers?

 

After installation, you will see 

  • package.json file is created in the project folder
  • package-lock.json file is created in the node_modules

 

Creating a Test

Now, I am creating a login test. So, I have selected the tests folder. It has one sample test already created. I am adding a new file in the test folder, e.g., arbisoft_chat.spec.js. I am creating test code using codegen. You can also write code manually.

 

Codegen records over steps and converts them to code. Enter the command below in the terminal to open codegen.

npx playwright codegen

and hit enter.

 

It opens the browser and the test generator in two different tabs. 

Screenshot 2026-01-21 at 11.58.01 PM.png

 

The recording is on by default, and it will record everything that we do in the browser. I have entered a test URL, e.g., arbisoft.com. I am doing below steps.

  • Click customize cookie 
  • Click save and continue
  • Click to open “Arbisoft Assistant”
  • And clicking “Show me past projects”

 

unnamed (3).png

 

The recorder is still ON. Now, I am stopping the recorder and copying the code generated by codegen. Paste the code in your IDE.

 

Running the Generated Test

In your IDE, go to the terminal and type the following command

  • npx playwright test tests/arbisoft_chat.spec.js --project=chromium --headed
  • This runs the test on the Chromium browser only

 

Screenshot 2026-01-22 at 12.11.14 AM.png

 

Use Page Object Model (POM)

In the project folder, create a folder, e.g., page, and create a file, e.g., arbisoft_chat.js, within it.

I am creating a class for the chat_assistant. I have created variables for my steps.

  • Click customize cookie 
  • Click save and continue
  • Click to open “Arbisoft Assistant”
  • And clicking “Show me past projects”

 

As we need the chat_assistant object, I am creating a constructor and is passing chat_assistant into it. The constructor has:

  • this.page = page

 

I have defined all locators using this. 

I have created a method chat_assistant_Page to perform actions on these locators. You can create separate functions for them as well.

 

Now, I am importing the page class chat_assistant in my test file. I have used chat_assistant and chat_assistant_Page inside my test. Run the test again using the command below.

npx playwright test tests/arbisoft_chat.spec.js --project=chromium --headed

 

Screenshot 2026-01-22 at 12.29.22 AM.png

Screenshot 2026-01-22 at 12.31.54 AM.png

Screenshot 2026-01-22 at 12.33.02 AM.png

 

Best Practices for Playwright with Page Object Model

  • Keep page logic inside page objects
    • All page locators and actions should be inside a page class. In the example, the chat_assistant class handles cookies, opening the chat widget, and interacting with the page. This keeps test files simple and clean.
  • Define all locators in one Place
    • Locators are defined in the constructor of the page object. This makes updates easier when the UI changes, because you only need to update selectors in one file.
  • Use Playwright recommended selectors
    • Using selectors like getByRole and getByText makes tests more stable and closer to real user behavior. These selectors are easier to read and less likely to break.
  • Hide complex steps in Methods
    • Multiple UI actions are grouped into one method. This hides complexity and makes the test easy to understand. The test only calls one method instead of many UI steps.
  • Keep Tests short and clear
    • Tests should focus on what is being tested, not how it works. A good test creates a page object and calls its method. This improves readability and reduces duplication.
  • Handle iFrames inside page objects
    • Any iframe logic should stay inside the page object. This keeps test files clean and avoids repeated iframe handling code.
  • Rely on Playwright auto-waiting
    • Playwright automatically waits for elements to be ready. Avoid using fixed waits and let Playwright handle synchronization for faster and more reliable tests.

 

Benefits of POM

  • It makes your code clean 
  • It gives structure to your code
  • It reduces duplicates in your code
  • If UI has changed, it updates quickly, i.e. If a locator has changed, you will update it in one place.

 

Conclusion

The Page Object Model (POM) is very simple and the best way to build automation tests that are easily scalable and maintainable. By splitting the original code into test code and page code, our tests become simpler, and they become easy to read and update. POM helps us to reduce duplication and scale test automation with confidence.

The codegen feature of Playwright works very well with POM. In short, introducing POM with Playwright is the best way to build well-structured end-to-end (e2e) test automation frameworks. 

Playwright is one of the most powerful and modern automation frameworks available today, and when combined with the Page Object Model, it becomes a clean, scalable, and maintainable testing solution.

If your goal is to build a professional-grade test automation framework, Playwright + POM is a combination you can trust. Start simple, follow best practices, and refactor as your test suite grows.

Explore More

Have Questions? Let's Talk.

We have got the answers to your questions.