Wednesday, March 5, 2025

Dynamic POM spec using typescript

Dynamic Page Object Model (POM) is a design pattern used in test automation to create reusable and maintainable code for interacting with web pages. Using Playwright with TypeScript, you can create a dynamic POM structure that adapts to different pages or components dynamically.


Here’s how you can create a Dynamic POM using TypeScript in Playwright:


## **1. Project Setup**

1. **Initialize a Playwright project**:

       npm init playwright@latest

   Choose TypeScript as the language during setup.


2. **Install dependencies**:

   Playwright is already installed, but ensure TypeScript and related tools are installed:

       npm install --save-dev typescript @playwright/test


3. **Folder structure**:

   Create a folder structure for your POM:


   my-playwright-project/

   ├── pages/                # Page Object files

   │   ├── BasePage.ts       # Base class for all pages

   │   ├── HomePage.ts       # Example page object

   │   └── LoginPage.ts      # Example page object

   ├── tests/                # Test files

   │   └── example.spec.ts   # Example test

   ├── playwright.config.ts  # Playwright configuration

   └── tsconfig.json         # TypeScript configuration



## **2. Create a Base Page Class**

The `BasePage` class will contain common methods and properties that all pages can inherit.


import { Page } from '@playwright/test';


export class BasePage {

  protected page: Page;


  constructor(page: Page) {

    this.page = page;

  }


  // Navigate to a URL

  async navigateTo(url: string): Promise<void> {

    await this.page.goto(url);

  }


  // Generic method to click an element

  async click(selector: string): Promise<void> {

    await this.page.click(selector);

  }


  // Generic method to type into an input field

  async type(selector: string, text: string): Promise<void> {

    await this.page.fill(selector, text);

  }


  // Generic method to get text from an element

  async getText(selector: string): Promise<string> {

    return await this.page.textContent(selector) || '';

  }


  // Generic method to check if an element is visible

  async isVisible(selector: string): Promise<boolean> {

    return await this.page.isVisible(selector);

  }

}



## **3. Create Specific Page Classes**

Extend the `BasePage` class to create specific page objects for different pages.


### **HomePage.ts**


import { BasePage } from './BasePage';


export class HomePage extends BasePage {

  // Selectors for elements on the home page

  private readonly headerSelector = 'h1';

  private readonly loginButtonSelector = 'text=Login';


  // Get the header text

  async getHeaderText(): Promise<string> {

    return await this.getText(this.headerSelector);

  }


  // Click the login button

  async clickLoginButton(): Promise<void> {

    await this.click(this.loginButtonSelector);

  }

}



### **LoginPage.ts**


import { BasePage } from './BasePage';


export class LoginPage extends BasePage {

  // Selectors for elements on the login page

  private readonly usernameInput = '#username';

  private readonly passwordInput = '#password';

  private readonly submitButton = 'button[type="submit"]';


  // Log in with username and password

  async login(username: string, password: string): Promise<void> {

    await this.type(this.usernameInput, username);

    await this.type(this.passwordInput, password);

    await this.click(this.submitButton);

  }

}


## **4. Write a Test Using Dynamic POM**

Now, you can use the page objects in your test files.


### **example.spec.ts**

```typescript

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

import { HomePage } from '../pages/HomePage';

import { LoginPage } from '../pages/LoginPage';


test('Dynamic POM example', async ({ page }) => {

  // Create instances of page objects

  const homePage = new HomePage(page);

  const loginPage = new LoginPage(page);


  // Navigate to the home page

  await homePage.navigateTo('https://example.com');


  // Verify the header text

  const headerText = await homePage.getHeaderText();

  expect(headerText).toBe('Example Domain');


  // Click the login button

  await homePage.clickLoginButton();


  // Log in with credentials

  await loginPage.login('testuser', 'password123');


  // Verify successful login (example)

  const isLoggedIn = await loginPage.isVisible('text=Welcome, testuser');

  expect(isLoggedIn).toBeTruthy();

});


## **5. Run the Test**

Run the test using the Playwright CLI:

    npx playwright test


## **6. Advantages of Dynamic POM**

- **Reusability**: Common methods are defined in the `BasePage` class, reducing code duplication.

- **Maintainability**: Changes to selectors or methods are isolated to specific page objects.

- **Scalability**: Easily add new page objects for additional pages or components.


## **7. Tips for Dynamic POM**

- Use **TypeScript interfaces** or types to define reusable data structures.

- Use **Playwright locators** for better performance and readability:

  ```typescript

  async click(locator: Locator): Promise<void> {

    await locator.click();

  }


ADDITIONAL NOTE: Use Playwright's **test fixtures** to initialize page objects dynamically.


By following this structure, you can create a robust and scalable test automation framework using Playwright and TypeScript. 🎉

Getting Started with Playwright for Beginners

Playwright is a powerful end-to-end testing framework for web applications, developed by Microsoft. It allows you to automate browsers like Chrome, Firefox, and Safari, and is a great tool for testing modern web applications. If you're a beginner, here's a guide to get started with Playwright:

For more details visit: https://playwright.dev/docs/intro

1. Prerequisites

Before you start, ensure you have the following:

      Node.js installed (version 12 or higher). You can download it from Node.js official website.

      A basic understanding of JavaScript or TypeScript.

 

2. Install Playwright

1.               Open your terminal or command prompt.

2.               Run the following command to install Playwright:

npm init playwright@latest

3.               This command will:

      Create a new project folder.

      Install Playwright and its dependencies.

      Set up a basic configuration for you.

4.               Follow the prompts to configure your project. You can choose the language (JavaScript or TypeScript) and the browsers you want to test (Chromium, Firefox, WebKit).

 

3. Project Structure

After installation, your project will have the following structure:

my-playwright-project/ 

├── tests/                # Folder for your test files 

├── playwright.config.js  # Configuration file 

├── package.json          # Project metadata and dependencies 

└── node_modules/         # Installed dependencies

 

4. Writing Your First Test

  •  Create a new test file in the tests folder, e.g., example.spec.js.
  • Add the following code to test a simple webpage:

const { test, expect } = require('@playwright/test');  

test('basic test', async ({ page }) => {    

// Navigate to a website     

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

// Check if the title contains "Example Domain"     

const title = await page.title();     

expect(title).toBe('Example Domain');      

// Take a screenshot     

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

});

 

5. Running Your Test

  •  Run the following command in your terminal:

                npx playwright test

  •  Playwright will execute your test and display the results in the terminal.

 

6. Playwright Features to Explore

      Auto-waiting: Playwright automatically waits for elements to be ready before interacting with them.

      Cross-browser testing: Test your app on Chromium, Firefox, and WebKit.

      Headless mode: Run tests without opening a browser window (default).

      Trace Viewer: Debug your tests with detailed traces.

 

7. Debugging Tests

      Run tests in headed mode (with a visible browser):

                npx playwright test --headed

      Use the --debug flag to pause and inspect:

                npx playwright test --debug

 

8. Playwright Test Generator

Playwright has a built-in code generator to help you write tests:

  • Run the following command:

            npx playwright codegen

  •  A browser window will open. Interact with the page, and Playwright will generate the code for you.

 

9. Playwright Configuration

The playwright.config.js file allows you to customize settings like:

      Default browser

      Test timeout

      Base URL

      Screenshot and video recording options

Example configuration:

const { defineConfig } = require('@playwright/test');  

module.exports = defineConfig({   

use: {     headless: true, // Run tests in headless mode     

screenshot: 'on', // Take screenshots on failure     

video: 'retain-on-failure', // Record video on failure   

}, });

 

10. Learning Resources

      Playwright Official Documentation

      Playwright GitHub Repository

      Tutorials and guides on YouTube or blogs.

 

Next Steps

Once you're comfortable with the basics, explore advanced features like:

      Parallel test execution

      API testing

      Custom test fixtures

      CI/CD integration

Playwright is a beginner-friendly yet powerful tool for web testing. Happy testing! 🚀