top of page

Welcome
to NumpyNinja Blogs

NumpyNinja: Blogs. Demystifying Tech,

One Blog at a Time.
Millions of views. 

Testing Web Apps Using Playwright: POM Structure and Key Commands Explained

In the previous blog Part 1, we discussed how to get started with Playwright. We covered:

  • Installing Node.js and Playwright

  • Understanding the basic project folder structure

  • Creating spec files for tests

  • Importing @playwright/test

  • Using the test block with async and await (used in every Playwright spec)

  • Running test cases with Playwright CLI commands


Now, in this part, we'll explore more features and how Playwright simplifies application validation compared to other tools like Selenium.


Understanding package.json in Playwright Projects

Every Node.js project, including Playwright-based automation frameworks, relies on a package.json file. This file serves as the blueprint of your project, defining dependencies, scripts, project metadata, and more.

  • It's used by npm to manage your packages.

  • It allows team members to run the same test commands across environments.

  • It simplifies CI/CD integration by providing standardized script hooks.

When you run npm install, Node looks at package.json and installs everything listed under dependencies and devDependencies.


Project Structure and Page Object Model

I have created a project named DSALGOPLAYWRIGHT. Here's how the structure looks:

  • tests/ folder contains:

    • registration.spec.js

    • login.spec.js

    • home.spec.js

  • pages/ folder contains Page Object Models:

    • registrationPage.js

    • loginPage.js

    • homePage.js


Just like Selenium, where we store the base URL in a config file, Playwright allows us to set the base URL in playwright.config.js.


Login Page: Page Object

In the loginPage.js file, we encapsulate all login-related interactions:


In the loginPage.js, all page interactions related to the login process are encapsulated. The constructor takes the page object (provided by Playwright's test runner) and initializes the page elements:

  • usernameField: Represents the username input field (selector: "#id_username")

  • passwordField: Represents the password input field (selector: "#id_password")

  • loginButton: Represents the login button (selector: input element with value 'Login')

page.locator()

  • A locator is used to find and interact with elements efficiently.

  • Locators are more powerful than page.$ because they automatically wait for elements to appear and be ready.

The fillLoginForm(username, password) method fills the login form using await, which ensures fields are ready before interaction. The submitLogin() method clicks the login button.

The line module.exports = LoginPage; is a Node.js syntax used to export the class so it can be reused in other files — just like making it public.


Validating Login(login.spec.js)


const { test, expect } = require('@playwright/test');
const LoginPage = require('../pages/loginPage');

test('User can log in successfully', async ({ page }) => {
    const loginPage = new LoginPage(page);
    await page.goto('/login');
    
    // Fill in the login form
    await loginPage.fillLoginForm('Ram@gmail.com', 'Tester123$');
    
    // Submit the login form
    await loginPage.submitLogin();
    
    // Validate successful redirection to the home page
    await expect(page).toHaveURL('/home');
});

We import Playwright testing functions (test, expect) and the LoginPage POM from the pages folder.


We define a test case "User can log in successfully":

  • page is injected by Playwright Test runner, giving a fresh browser tab.

  • An object of the LoginPage class is created using the page object.

  • page.goto('/login') navigates to the login page (relative to baseURL).

  • fillLoginForm() and submitLogin() methods are used from the LoginPage class.

  • Finally, expect(page).toHaveURL('/home') asserts that the user is redirected to the home page after successful login.

If the URL isn’t /home, Playwright will automatically retry for a few seconds — built-in smart waiting.


Okay now I want to do a comparison between selenium and playwright commands for important actions like finding elements, clicking, typing, waiting, and assertions.


Selenium vs Playwright: Command Comparison

Here’s a handy side-by-side comparison of common tasks in Selenium (Java) vs. Playwright (JavaScript):

Action

Selenium (Java)

Playwright (JS)

Launch page

driver.get("https://...")

await page.goto('https://...')

Find element

driver.findElement(By.id("user"))

page.locator('#user')

Type input

el.sendKeys("abc")

await locator.fill("abc")

Click button

e.click()

await locator.click()

Wait for element

WebDriverWait + ExpectedConditions

await locator.waitFor() (auto-wait built-in)

URL assertion

Assert.assertEquals(driver.getCurrentUrl(), "...")

await expect(page).toHaveURL('/home')

Text assertion

Assert.assertEquals(el.getText(), "...")

await expect(locator).toHaveText('...')

Playwright Command Cheat Sheet

Here's a Playwright Command Cheat Sheet covering the most commonly used and useful commands for web automation using JavaScript/TypeScript (@playwright/test framework): 


Navigation

await page.goto('https://example.com');     // Navigate to URL

await page.reload();                        // Reload the page

await page.goBack();                        // Go back in browser history

await page.goForward();                    //Go forward in browser history 

Element Selection

const locator = page.locator('selector');       // Create a locator

const button = page.locator('button#submit');   // Example locator

Input Actions

await locator.fill('value');                   // Clear + Type value

await locator.type('value');                   // Type value (no clear)

await locator.press('Enter');                  // Press a key

await locator.click();                         // Click an element

await locator.dblclick();                      // Double-click

await locator.check();                         // Check checkbox

await locator.uncheck();                       // Uncheck checkbox

await locator.selectOption('value');           // Select dropdown option

 Screenshots

await page.screenshot({ path: 'screenshot.png' });        // Full page

await locator.screenshot({ path: 'element.png' });         // Element only

Frames and IFrames

const frame = page.frame({ name: 'frameName' });           // By name

const frame = page.frameLocator('#frameID');               // By selector

await frame.locator('selector').click();               // Interact inside

 Assertions

await expect(page).toHaveURL('https://...');         // Assert page URL

await expect(locator).toHaveText('Hello');         // Assert text content

await expect(locator).toBeVisible();                 // Assert visibility

await expect(locator).toHaveValue('abc');            // Assert input value

await expect(locator).toHaveAttribute('type','submit');// Assert attribute 

Conclusion

Playwright simplifies end-to-end testing by reducing boilerplate code, handling automatic waits, and integrating powerful features like its own test runner, assertion library, and screenshot capabilities.

If you're already familiar with Selenium, transitioning to Playwright can significantly improve your test speed, stability, and maintainability, making it an ideal tool for modern web application validation.

"Validation is not just about checking if it works — it's about proving that it works every time. With Playwright, reliability meets simplicity in modern web testing."

 
 

+1 (302) 200-8320

NumPy_Ninja_Logo (1).png

Numpy Ninja Inc. 8 The Grn Ste A Dover, DE 19901

© Copyright 2025 by Numpy Ninja Inc.

  • Twitter
  • LinkedIn
bottom of page