Skip to main content

Creating fully functional page object model automation framework with Playwright in 1 hour

 We are back with another 1hour tutorial ๐Ÿ˜‡. This time we will be creating Playwright and Typescript page object model framework. For this we will be using Visual Studio Code editor. Hope you have a basic idea on Playwright. There are plenty of resources you can refer to get the basic idea of the Playwright. In this tutorial we will be focussing more on how to implement Page Object model in Playwright. So let's begin.







Before all of this, you must need to have node js installed. I hope you have already done that.



1. Download the relevant nodejs packages by using following command 

npm init playwright@latest

2. Lets create our project structure. Unlike Selenium 1 hour lesson for this we will be creating just two folders. To write page objects we use "pages" folder and to write tests we create "tests" folder. Just for now, run the default tests which Playwright automatically create with its installation.

use npx playwright test command in your CMD.


By default every tests run in headless mode. So if you want to run in head full mode, you have to change the playwright.config.ts  config file.

add headless: false

use: {
/* Base URL to use in actions like `await page.goto('/')`. */
// baseURL: 'http://127.0.0.1:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
/* Headful mode execution */
headless: false,
},

inside use: {}  playwright.config.ts file.

3. After step 2, you should have following like folder structure. Make sure to delete the tests/example.spec.ts file since we don't need it anymore.



4. For this lesson too, we are using https://www.saucedemo.com/ application. So now lets create page class inside pages folder.

import { expect,Page } from "@playwright/test";

export class LoginPage {
page: Page;


constructor(page: Page) {
this.page = page;
}

//locators
txtUsername = () => this.page.getByPlaceholder('Username');
txtPassword = () => this.page.getByPlaceholder('Password');
btnLogin = () => this.page.getByRole('button', { name: ' Login' });
lblInvalidLogin = () => this.page.getByText('Invalid credentials');

//actions
public async gotoLoginPage(){
await this.page.goto("https://www.saucedemo.com/");
}

public async enterUsername(){
await this.txtUsername().fill("Admin");
}

public async enterPassword(){
await this.txtPassword().fill("admin123");
}

public async clickLogin(){
await this.btnLogin().click();
}

//login to the application
public async logintoApp(username,password){
await this.txtUsername().fill(username);
await this.txtPassword().fill(password);
await this.btnLogin().click();
}

public async assertInvalidLogin(){
await expect(this.lblInvalidLogin()).toBeVisible();
}

}



So we include all of our locators as variables and its functional implementation in the bottom. Now you may be wondering unlike Selenium, Playwright locators are different. So how did i catch these locators ๐Ÿคจ. It's really simple.

There is an already inbuilt feature come with Playwright which allows us to record all the actions we do, this is really helpful for the users who do Web Scraping. So from that you can catch all the locators easily. I'll show you how,

first you need to run the following command.

npx playwright codegen

It will open a separate simple web browser with a widget, what you have to do is just enter your url and do all the operations. Then this small widget kind of application will record all your steps and gives you a script. 

This is one of the sample auto generated scripts


So I have used page.locator('[data-test="username"]') inside a variable. 

This is faster and much more easier than selenium right ๐Ÿค“

Same way we need to create a separate page class for the Dashboard page since we are independent from one class to another class. So  lets create it.

import { expect,Page } from "@playwright/test";

export class DashboardPage {
page: Page;


constructor(page: Page) {
this.page = page;
}

//locators
lblDashboard = () => this.page.getByText('Products');


//actions
public async assertValidLogin(){
await expect(this.lblDashboard()).toBeVisible();
}


}



5. Now lets create a tests file.

import {test,expect} from '@playwright/test';
import { LoginPage } from '../pages/loginpage';
import { DashboardPage } from '../pages/dashboardpage';

test('Test_01: Login with valid credentials', async({page}) =>{

const login = new LoginPage(page);
const dasboardpage = new DashboardPage(page);
await login.gotoLoginPage();
await login.logintoApp("standard_user","secret_sauce");
await dasboardpage.assertValidLogin();

});

test("Test_02: Check whether when user logged in with incorrect username and password it will show an error", async({page, baseURL}) => {
const login = new LoginPage(page);
await login.gotoLoginPage();
await login.logintoApp("Admin","123");
await login.assertInvalidLogin();
});





In here we have implemented two methods to check a happy path and a error scenario. Unlike Selenium we don't need any third party testing framework like Testng. It has it's own way to assert. You can learn more on Asserts with Playwright documentation.


Now for the moment go to your playwright.config.ts file and comment all the browsers other than chrome. Now when you run the Playwirght tests, it will only get executed in Chrome browser only. This is just to focus on one browser for now. If you want you can run on all these browsers. 

/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

// {
// name: 'firefox',
// use: { ...devices['Desktop Firefox'] },
// },

// {
// name: 'webkit',
// use: { ...devices['Desktop Safari'] },
// },

/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },

/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ..devices['Desktop Chrome'], channel: 'chrome' },
// },
],


Now lets run the tests by command npx playwright test in the terminal/cmd. 



There will be automatically generated report opened in your browser after the execution but we will add Allure report in few minutes.



Basically thats it. So guys. We have implemented our framework. 


Now lets focus on other inbuilt features which comes with Playwright.

  •  Taking screenshots.

    This is really easy to implement. Just put screenshot: "only-on-failure", inside use. You want to to get it on failure right? Then you have to use "only-on-failure".  There are other times you can use it, you can find them in the Playwright documentation.

    use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    // baseURL: 'http://127.0.0.1:3000',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
    /* Headful mode execution */
    headless: false,
    /* Taking screenshots on failure */
    screenshot: "only-on-failure",
    },

    Just test this out, by creating an assertion error by your self.

    As you can see, failed scenario will be saved in a screen shot under test-results folder.


        

  • Taking Video on failures.

    Unlike Selenium you can easily record the failures, having failures record like that makes easy to debug without even running the automation suite. 

    So lets implement that. This happens too in the playwright.config.ts file. You have to add video: "retain-on-failure" inside use. You don't want to record successful scenarios right? It will take so much space on your computer or server. So with this retain-on-failure it will just keep the recording only on failure.

    use: {
    /* Base URL to use in actions like `await page.goto('/')`. */
    // baseURL: 'http://127.0.0.1:3000',

    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
    trace: 'on-first-retry',
    /* Headful mode execution */
    headless: false,
    /* Taking screenshots on failure */
    screenshot: "only-on-failure",
    /*Saving video on failure */
    video: "retain-on-failure"
    },

           Lets try this also. just like you tested the failure on screenshot.



    

            Just like  you will able to see the failure recording on your automatically generated 
                 playwright report.


            So guys thats it for now, I will add more modifications in the future for this lesson.


            Github link : https://github.com/iroshanAV/simple-pom-pw








Comments

Popular posts from this blog

How to create Push Notification System for your Cordova app with OneSignal and Firebase

H ello Everyone, today i'm going to show you how to add push notification system for your Cordova mobile app with OneSignal. First let's talk little bit about OneSignal. OneSignal is a multi-platform push notification service, which gives you variety of features. It lets you to send push notifications to almost all current mobile Operating Systems. You can check out their documentation if you want or start straightly this tutorial. If you need to see the project structure  and stuff  go to github repo Lets begin our tutorial ๐Ÿ˜Ž๐Ÿ˜Ž๐Ÿ˜Ž First lets create a Cordova project. type following command in your CMD.    C:\Users\acer>cordova create push There will be a structure like this,      Now run android emulator, if you don't know how to run emulator from your CMD see this tutorial and do it exactly like that. Go to your project folder and then type the following command in your CMD  C:\Users\acer\push>cordova platfor...

How to deploy Android Emulator from CMD in Windows

First go to your C drive Then find Users folder and your Personal folder in my case acer Then go to .android folder Now first you have to check what are the available emulators first emulator -list-avds you will get some thing like this, if not you have to create emulator device first .  Now run following command by specifying which device you want. For me i will pick Nexus_5_API_24 emulator -avd Nexus_5_API_24 And your job is done.