Parameterized Tests in Playwright Java using JUnit5

HOME

@ParameterizedTest
    @CsvSource({
            "admin123,admin123,Invalid credentials",
            "admin,admin12,Invalid credentials",
            "Admin,1234,Invalid credentials",
            "12345,%^$£56,Invalid credentials"
    })
    public void unsuccessfulLogin(String username, String password, String expectedErrorMessage) {

        LoginPage loginPage = new LoginPage(page);
        loginPage.login(username,password);
        String actualErrorMessage = loginPage.getErrorMessage();
        Assertions.assertEquals(expectedErrorMessage, actualErrorMessage, "");

   }

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>PageObjectModel_Playwright_JUnit5</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>PageObjectModel_Playwright_JUnit5</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <playwright.version>1.57.0</playwright.version>
    <junit.jupiter.engine.version>6.1.0-M1</junit.jupiter.engine.version>
    <junit.jupiter.api.version>6.1.0-M1</junit.jupiter.api.version>
    <junit.jupiter.params.version>6.1.0-M1</junit.jupiter.params.version>
    <maven.compiler.plugin.version>3.14.1</maven.compiler.plugin.version>
    <maven.compiler.source.version>17</maven.compiler.source.version>
    <maven.compiler.target.version>17</maven.compiler.target.version>
    <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <maven.site.plugin.version>4.0.0-M16</maven.site.plugin.version>
    <maven.surefire.report.plugin.version>3.5.4</maven.surefire.report.plugin.version>
  </properties>

  <dependencies>

    <dependency>
      <groupId>com.microsoft.playwright</groupId>
      <artifactId>playwright</artifactId>
      <version>${playwright.version}</version>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-engine</artifactId>
      <version>${junit.jupiter.engine.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>${junit.jupiter.api.version}</version>
      <scope>test</scope>
    </dependency>

    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-params</artifactId>
      <version>${junit.jupiter.params.version}</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven.compiler.plugin.version}</version>
        <configuration>
          <source>${maven.compiler.source.version}</source>
          <target>${maven.compiler.target.version}</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven.surefire.plugin.version}</version>
        <configuration>
          <testFailureIgnore>true</testFailureIgnore>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-site-plugin</artifactId>
        <version>${maven.site.plugin.version}</version>
      </plugin>
    </plugins>
  </build>

  <reporting>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-report-plugin</artifactId>
        <version>${maven.surefire.report.plugin.version}</version>
        <configuration>
          <outputName>JUnit5 Report</outputName>
        </configuration>
      </plugin>
    </plugins>
  </reporting>

</project>

import com.microsoft.playwright.Page;

public class LoginPage {

    private Page page;

    //Locators
    private final String usernameLocator = "input[name='username']";
    private final String passwordLocator = "input[name='password']";
    private final String submitButton = "button[type='submit']";
    private final String errorMessage = "//p[contains(@class, 'oxd-text oxd-text--p oxd-alert-content-text')]";

    //Constructor
    public LoginPage(Page page){
        this.page = page;
    }

    public void login(String username, String password) {
        page.fill(usernameLocator,username);
        page.fill(passwordLocator,password);
        page.click(submitButton);
    }

    public String getErrorMessage(){
        return page.textContent(errorMessage);
    }
}

package org.example.pages;

import com.microsoft.playwright.Page;

public class DashboardPage {

    private Page page;

    //Locators
    private final String dashboardHeading = "//h6[contains(@class, 'oxd-topbar-header-breadcrumb-module')]";

    //Constructor
    public DashboardPage(Page page) {
        this.page = page;
    }

    // Methods
    public String getHeading() {
        return page.textContent(dashboardHeading);
    }
}

package org.example.utils;
package com.example.utils;

import com.microsoft.playwright.*;
import org.junit.jupiter.api.*;

// Subclasses will inherit PER_CLASS behavior.
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class BaseTests {

    // Shared between all tests in the class.
    static Playwright playwright;
    static Browser browser;

    // New instance for each test method.
    BrowserContext context;
    protected Page page;

    @BeforeAll
    public static void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));

    }

    @AfterAll
    public static void closeBrowser() {
        playwright.close();
    }


    @BeforeEach
    public void createContextAndPage() {
        context = browser.newContext();
        page = context.newPage();
        page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }

    @AfterEach
    public void closeContext() {
        context.close();
    }
}
Playwright playwright;
Browser browser = null;
BrowserContext context;
Page page;
  @BeforeAll
    public void launchBrowser() {
        playwright = Playwright.create();
        browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    }

@BeforeMethod
void createContextAndPage() {
      context = browser.newContext();
      page = context.newPage();
      page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
}
@AfterAll
 public static void closeBrowser() {
        playwright.close();
 }
@AfterEach
   public void closeContext() {
        context.close();
}

package com.example.tests;

import com.example.pages.DashboardPage;
import com.example.pages.LoginPage;
import com.example.utils.BaseTests;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class LoginTests extends BaseTests {

    @ParameterizedTest
    @CsvSource({
            "admin123,admin123,Invalid credentials",
            "admin,admin12,Invalid credentials",
            "Admin,1234,Invalid credentials",
            "12345,%^$£56,Invalid credentials"
    })
    public void unsuccessfulLogin(String username, String password, String expectedErrorMessage) {

        LoginPage loginPage = new LoginPage(page);
        loginPage.login(username,password);
        String actualErrorMessage = loginPage.getErrorMessage();
        Assertions.assertEquals(expectedErrorMessage, actualErrorMessage, "");

   }

    @Test
    public void successfulLogin() {

        LoginPage loginPage = new LoginPage(page);
        loginPage.login("Admin","admin123");
        DashboardPage dashboardPage = new DashboardPage(page);
        String actualHeading = dashboardPage.getDashboardPageHeading();
        Assertions.assertEquals("Dashboard",actualHeading, "Unable to login to the application");

    }

}
@ParameterizedTest
    @CsvSource({
            "admin123,admin123,Invalid credentials",
            "admin,admin12,Invalid credentials",
            "Admin,1234,Invalid credentials",
            "12345,%^$£56,Invalid credentials"
    })

mvn clean test site

    Playwright Tutorials – TypeScript

    HOME

    Integration of Playwright with Java, Cucumber and JUnit5

    HOME

    Benefits of Using Cucumber with Playwright

    <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>17</java.version>
            <cucumber.version>7.33.0</cucumber.version>
            <playwright.version>1.57.0</playwright.version>
            <lombok.version>1.18.30</lombok.version>
            <junit.jupiter.engine.version>6.1.0-M1</junit.jupiter.engine.version>
            <junit.jupiter.version>6.1.0-M1</junit.jupiter.version>
            <maven.compiler.plugin.version>3.14.1</maven.compiler.plugin.version>
            <maven.compiler.source.version>17</maven.compiler.source.version>
            <maven.compiler.target.version>17</maven.compiler.target.version>
            <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <maven.site.plugin.version>4.0.0-M16</maven.site.plugin.version>
            <maven.surefire.report.plugin.version>3.5.4</maven.surefire.report.plugin.version>
            <cucumber.junit.platform.engine>7.14.0</cucumber.junit.platform.engine>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.microsoft.playwright</groupId>
                <artifactId>playwright</artifactId>
                <version>${playwright.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-engine</artifactId>
                <version>${junit.jupiter.engine.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-api</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-params</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!-- Cucumber with Java -->
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-java</artifactId>
                <version>${cucumber.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!-- Cucumber with Junit5 -->
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-junit-platform-engine</artifactId>
                <version>${cucumber.junit.platform.engine}</version>
            </dependency>
    
            <!-- JUnit Platform -->
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-suite</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
        </dependencies>
    
    

     <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven.compiler.plugin.version}</version>
                    <configuration>
                        <source>${maven.compiler.source.version}</source>
                        <target>${maven.compiler.target.version}</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven.surefire.plugin.version}</version>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                    </configuration>
                </plugin>
    
            </plugins>
        </build>
    
    <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-site-plugin</artifactId>
            <version>${maven.site.plugin.version}</version>
    </plugin>
    
    <reporting>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-report-plugin</artifactId>
                    <version>${maven.surefire.report.plugin.version}</version>
                    <configuration>
                        <outputName>JUnit5 Report</outputName>
                    </configuration>
                </plugin>
            </plugins>
        </reporting>
    

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>Cucumber_Playwright_JUnit5</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>Cucumber_Playwright_JUnit5</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.version>17</java.version>
            <cucumber.version>7.33.0</cucumber.version>
            <playwright.version>1.57.0</playwright.version>
            <lombok.version>1.18.30</lombok.version>
            <junit.jupiter.engine.version>6.1.0-M1</junit.jupiter.engine.version>
            <junit.jupiter.version>6.1.0-M1</junit.jupiter.version>
            <maven.compiler.plugin.version>3.14.1</maven.compiler.plugin.version>
            <maven.compiler.source.version>17</maven.compiler.source.version>
            <maven.compiler.target.version>17</maven.compiler.target.version>
            <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
            <maven.compiler.source>17</maven.compiler.source>
            <maven.compiler.target>17</maven.compiler.target>
            <maven.site.plugin.version>4.0.0-M16</maven.site.plugin.version>
            <maven.surefire.report.plugin.version>3.5.4</maven.surefire.report.plugin.version>
            <cucumber.junit.platform.engine>7.14.0</cucumber.junit.platform.engine>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.microsoft.playwright</groupId>
                <artifactId>playwright</artifactId>
                <version>${playwright.version}</version>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-engine</artifactId>
                <version>${junit.jupiter.engine.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-api</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.junit.jupiter</groupId>
                <artifactId>junit-jupiter-params</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!-- Cucumber with Java -->
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-java</artifactId>
                <version>${cucumber.version}</version>
                <scope>test</scope>
            </dependency>
    
            <!-- Cucumber with Junit5 -->
            <dependency>
                <groupId>io.cucumber</groupId>
                <artifactId>cucumber-junit-platform-engine</artifactId>
                <version>${cucumber.junit.platform.engine}</version>
            </dependency>
    
            <!-- JUnit Platform -->
            <dependency>
                <groupId>org.junit.platform</groupId>
                <artifactId>junit-platform-suite</artifactId>
                <version>${junit.jupiter.version}</version>
                <scope>test</scope>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven.compiler.plugin.version}</version>
                    <configuration>
                        <source>${maven.compiler.source.version}</source>
                        <target>${maven.compiler.target.version}</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>${maven.surefire.plugin.version}</version>
                    <configuration>
                        <testFailureIgnore>true</testFailureIgnore>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>${maven.site.plugin.version}</version>
                </plugin>
            </plugins>
        </build>
    
        <reporting>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-report-plugin</artifactId>
                    <version>${maven.surefire.report.plugin.version}</version>
                    <configuration>
                        <outputName>JUnit5 Report</outputName>
                    </configuration>
                </plugin>
            </plugins>
        </reporting>
    </project>
    

    Feature: Login to HRM Application
    
      Background:
        Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
    
      @ValidCredentials
      Scenario: Login with valid credentials
    
        When User enters username as "Admin" and password as "admin123"
        Then User should be able to login successfully and new page opens with heading "Dashboard"
    
      @InvalidCredentials
      Scenario Outline: Login with invalid credentials
    
        When User enters username as "<username>" and password as "<password>"
        Then User should be able to see error message "<errorMessage>"
    
        Examples:
          | username   | password  | errorMessage           |
          | Admin      | admin12$$ | Invalid credentials    |
          | admin$$    | admin123  | Invalid credentials    |
          | abc123     | xyz$$     | Invalid credentials    |
    
      @MissingUsername 
      Scenario: Login with blank username
    
        When User enters username as " " and password as "admin123"
        Then User should be able to see a message "Required" below Username
    

    package com.example.utils;
    
    import com.microsoft.playwright.*;
    
    public class PlaywrightFactory {
    
        private static Playwright playwright;
        private static Browser browser;
        private static BrowserContext context;
        private static Page page;
    
        public static void initBrowser() {
    
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
            context = browser.newContext();
            page = context.newPage();
        }
    
        public static Page getPage() {
            return page;
        }
    
        public static void closeBrowser() {
            if (page != null) page.close();
            if (context != null) context.close();
            if (browser != null) browser.close();
            if (playwright != null) playwright.close();
        }
    }
    
    

    package com.example.hooks;
    
    import com.example.utils.PlaywrightFactory;
    import com.microsoft.playwright.*;
    import io.cucumber.java.After;
    import io.cucumber.java.Before;
    import io.cucumber.java.Scenario;
    
    public class Hooks {
    
        @Before
        public void beforeScenario(Scenario scenario) {
            System.out.println("Starting scenario: " + scenario.getName());
            PlaywrightFactory.initBrowser();
        }
    
        @After
        public void afterScenario(Scenario scenario) {
            Page page = PlaywrightFactory.getPage();
            if (page != null && scenario.isFailed()) {
                scenario.attach(page.screenshot(), "image/png", scenario.getName());
            }
            PlaywrightFactory.closeBrowser();  
            System.out.println("Finished scenario: " + scenario.getName());
        }
    }
    
    
    
    package com.example.pages;
    
    import com.microsoft.playwright.*;
    
    public class LoginPage {
    
        private Page page;
    
        // Locators
        private final Locator usernameLocator;
        private final Locator passwordLocator;
        private final Locator submitLocator;
        private final Locator invalidCredentialsLocator;
        private final Locator missingUsernameLocator;
    
        public LoginPage(Page page) {
            this.page = page;
            this.usernameLocator = page.locator("input[name='username']");
            this.passwordLocator = page.locator("input[name='password']");
            this.submitLocator = page.locator("button[type='submit']");
            this.invalidCredentialsLocator = page.locator("//p[contains(@class, "oxd-text oxd-text--p oxd-alert-content-text")]");
            this.missingUsernameLocator = page.locator("//span[contains(@class, 'oxd-text oxd-text--span oxd-input-field-error-message oxd-input-group__message')]");
        }
    
        public void login(String user, String pass){
            usernameLocator.fill(user);
            passwordLocator.fill(pass);
            submitLocator.click();
        }
    
        public void getUrl(String url){
            page.navigate(url);
        }
    
        public String getMissingUsernameErrorMessage() {
            return missingUsernameLocator.textContent();
        }
    
        public String getErrorMessage () {
            return invalidCredentialsLocator.textContent();
        }
    }
    
    
    package com.example.pages;
    
    import com.microsoft.playwright.Locator;
    import com.microsoft.playwright.Page;
    
    public class DashboardPage {
    
        private Page page;
    
        private final Locator headingLocator;
    
        public DashboardPage(Page page){
            this.page = page;
            this.headingLocator = page.locator("//h6[contains(@class, "oxd-topbar-header-breadcrumb-module")]");
        }
    
        public String getDashboardPageHeading() {
            return headingLocator.textContent();
        }
    
    }
    
    
    package com.example.steps;
    
    import com.example.utils.PlaywrightFactory;
    import com.microsoft.playwright.Page;
    
    public class BaseStep {
    
        protected Page getPage() {
            Page page = PlaywrightFactory.getPage();
            if (page == null) {
                throw new RuntimeException(
                        "Page is NULL. Ensure @Before hook ran and glue includes hooks package."
                );
            }
            return page;
        }
    }
    
    

    package com.example.definitions;
    
    import com.example.pages.DashboardPage;
    import com.example.pages.LoginPage;
    import com.example.steps.BaseStep;
    import io.cucumber.java.en.Given;
    import io.cucumber.java.en.Then;
    import io.cucumber.java.en.When;
    import org.junit.jupiter.api.Assertions;
    
    
    public class LoginPageDefinitions extends BaseStep {
    
        private LoginPage loginPage;
        private DashboardPage dashboardPage;
    
        @Given("User is on HRMLogin page {string}")
        public void userIsOnHRMLoginPage(String baseUrl) {
            loginPage = new LoginPage(getPage());
            loginPage.getUrl(baseUrl);
        }
    
        @When("User enters username as {string} and password as {string}")
        public void userEntersUsernameAsAndPasswordAs(String username, String password) {
            loginPage.login(username, password);
        }
    
        @Then("User should be able to see error message {string}")
        public void userShouldBeAbleToSeeErrorMessage(String expectedErrorMessage) {
            Assertions.assertEquals(expectedErrorMessage, loginPage.getErrorMessage());
        }
    
        @Then("User should be able to see a message {string} below Username")
        public void userShouldBeAbleToSeeAMessageBelowUsername(String expectedErrorMessage) {
            Assertions.assertEquals(expectedErrorMessage, loginPage.getMissingUsernameErrorMessage());
        }
    
        @Then("User should be able to login successfully and new page opens with heading {string}")
        public void userShouldBeAbleToLoginSuccessfullyAndNewPageOpen(String expectedHeading) {
            dashboardPage = new DashboardPage(getPage());
            Assertions.assertEquals(expectedHeading, dashboardPage.getDashboardPageHeading());
    
        }
    
    }
    

    package com.example.runner;
    
    import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
    import org.junit.platform.suite.api.ConfigurationParameter;
    import org.junit.platform.suite.api.IncludeEngines;
    import org.junit.platform.suite.api.SelectClasspathResource;
    import org.junit.platform.suite.api.Suite;
    
    @Suite
    @IncludeEngines("cucumber")
    @SelectClasspathResource("features")
    @ConfigurationParameter(
            key = GLUE_PROPERTY_NAME, value = "com.example"
    )
    
    public class RunnerTests {
    }
    
    
    mvn clean site test
    

    cucumber.publish.enabled=true
    

    • Hooks: Hooks manage browser setup, teardown, and failure handling

    Integration of Playwright with Java, Cucumber and TestNG

    HOME

    Benefits of Using Cucumber with Playwright

    <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.version>7.33.0</cucumber.version>
        <testng.version>7.12.0</testng.version>
        <playwright.version>1.57.0</playwright.version>
        <maven.compiler.version>3.14.1</maven.compiler.version>
        <maven.surefire.version>3.5.4</maven.surefire.version>
        <maven.failsafe.version>3.5.4</maven.failsafe.version>
        <lombok.version>1.18.30</lombok.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>
    
    <dependencies>
    
        <!-- Cucumber with Java -->
        <dependency>
          <groupId>io.cucumber</groupId>
          <artifactId>cucumber-java</artifactId>
          <version>${cucumber.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- Cucumber with TestNG -->
        <dependency>
          <groupId>io.cucumber</groupId>
          <artifactId>cucumber-testng</artifactId>
          <version>${cucumber.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- TestNG -->
        <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>${testng.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- Playwright -->
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
    </dependencies>
    
    

     <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.version}</version>
            <configuration>
              <source>${maven.compiler.source}</source>
              <target>${maven.compiler.target}</target>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.version}</version>
            <configuration>
              <testFailureIgnore>true</testFailureIgnore>
              <includes>
                <include>**/*RunnerTests.java</include>
              </includes>
            </configuration>
          </plugin>
          
        </plugins>
      </build>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>Cucumber_Playwright_TestNG</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>Cucumber_Playwright_TestNG</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <java.version>17</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <cucumber.version>7.33.0</cucumber.version>
        <testng.version>7.12.0</testng.version>
        <playwright.version>1.57.0</playwright.version>
        <maven.compiler.version>3.14.1</maven.compiler.version>
        <maven.surefire.version>3.5.4</maven.surefire.version>
        <maven.failsafe.version>3.5.4</maven.failsafe.version>
        <lombok.version>1.18.30</lombok.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
      </properties>
    
      <dependencies>
    
        <!-- Cucumber with Java -->
        <dependency>
          <groupId>io.cucumber</groupId>
          <artifactId>cucumber-java</artifactId>
          <version>${cucumber.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- Cucumber with TestNG -->
        <dependency>
          <groupId>io.cucumber</groupId>
          <artifactId>cucumber-testng</artifactId>
          <version>${cucumber.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- TestNG -->
        <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>${testng.version}</version>
          <scope>test</scope>
        </dependency>
    
        <!-- Playwright -->
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
      </dependencies>
     
     <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.version}</version>
            <configuration>
              <source>${maven.compiler.source}</source>
              <target>${maven.compiler.target}</target>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.version}</version>
            <configuration>
              <testFailureIgnore>true</testFailureIgnore>
              <includes>
                <include>**/*RunnerTests.java</include>
              </includes>
            </configuration>
          </plugin>
          
        </plugins>
      </build>
    </project>
    

    Feature: Login to HRM Application
    
      Background:
        Given User is on HRMLogin page "https://opensource-demo.orangehrmlive.com/"
    
      @ValidCredentials
      Scenario: Login with valid credentials
    
        When User enters username as "Admin" and password as "admin123"
        Then User should be able to login successfully and new page opens with heading "Dashboard"
    
      @InvalidCredentials
      Scenario Outline: Login with invalid credentials
    
        When User enters username as "<username>" and password as "<password>"
        Then User should be able to see error message "<errorMessage>"
    
        Examples:
          | username   | password  | errorMessage           |
          | Admin      | admin12$$ | Invalid credentials    |
          | admin$$    | admin123  | Invalid credentials    |
          | abc123     | xyz$$     | Invalid credentials    |
    
      @MissingUsername 
      Scenario: Login with blank username
    
        When User enters username as " " and password as "admin123"
        Then User should be able to see a message "Required1" below Username
    

    package com.example.utils;
    
    import com.microsoft.playwright.*;
    
    public class PlaywrightFactory {
    
        private static Playwright playwright;
        private static Browser browser;
        private static BrowserContext context;
        private static Page page;
    
        public static void initBrowser() {
    
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
            context = browser.newContext();
            page = context.newPage();
        }
    
        public static Page getPage() {
            return page;
        }
    
        public static void closeBrowser() {
            if (page != null) page.close();
            if (context != null) context.close();
            if (browser != null) browser.close();
            if (playwright != null) playwright.close();
        }
    }
    
    

    package com.example.hooks;
    
    import com.example.utils.PlaywrightFactory;
    import com.microsoft.playwright.*;
    import io.cucumber.java.After;
    import io.cucumber.java.Before;
    import io.cucumber.java.Scenario;
    
    public class Hooks {
    
        @Before
        public void beforeScenario(Scenario scenario) {
            System.out.println("Starting scenario: " + scenario.getName());
            PlaywrightFactory.initBrowser();
        }
    
        @After
        public void afterScenario(Scenario scenario) {
            Page page = PlaywrightFactory.getPage();
            if (page != null && scenario.isFailed()) {
                scenario.attach(page.screenshot(), "image/png", scenario.getName());
            }
            PlaywrightFactory.closeBrowser();  
            System.out.println("Finished scenario: " + scenario.getName());
        }
    }
    
    
    
    package com.example.pages;
    
    import com.microsoft.playwright.*;
    
    public class LoginPage {
    
        private Page page;
    
        // Locators
        private final Locator usernameLocator;
        private final Locator passwordLocator;
        private final Locator submitLocator;
        private final Locator invalidCredentialsLocator;
        private final Locator missingUsernameLocator;
    
        public LoginPage(Page page) {
            this.page = page;
            this.usernameLocator = page.locator("input[name='username']");
            this.passwordLocator = page.locator("input[name='password']");
            this.submitLocator = page.locator("button[type='submit']");
            this.invalidCredentialsLocator = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]");
            this.missingUsernameLocator = page.locator("//span[contains(@class, 'oxd-text oxd-text--span oxd-input-field-error-message oxd-input-group__message')]");
        }
    
        public void login(String user, String pass){
            usernameLocator.fill(user);
            passwordLocator.fill(pass);
            submitLocator.click();
        }
    
        public void getUrl(String url){
            page.navigate(url);
        }
    
        public String getMissingUsernameErrorMessage() {
            return missingUsernameLocator.textContent();
        }
    
        public String getErrorMessage () {
            return invalidCredentialsLocator.textContent();
        }
    }
    
    
    package com.example.pages;
    
    import com.microsoft.playwright.Locator;
    import com.microsoft.playwright.Page;
    
    public class DashboardPage {
    
        private Page page;
    
        private final Locator headingLocator;
    
        public DashboardPage(Page page){
            this.page = page;
            this.headingLocator = page.locator("//h6[contains(@class, \"oxd-topbar-header-breadcrumb-module\")]");
        }
    
        public String getDashboardPageHeading() {
            return headingLocator.textContent();
        }
    
    }
    
    
    package com.example.steps;
    
    import com.example.utils.PlaywrightFactory;
    import com.microsoft.playwright.Page;
    
    public class BaseStep {
    
        protected Page getPage() {
            Page page = PlaywrightFactory.getPage();
            if (page == null) {
                throw new RuntimeException(
                        "Page is NULL. Ensure @Before hook ran and glue includes hooks package."
                );
            }
            return page;
        }
    }
    
    

    package com.example.definitions;
    
    import com.example.steps.BaseStep;
    import com.example.pages.DashboardPage;
    import com.example.pages.LoginPage;
    import io.cucumber.java.en.Given;
    import io.cucumber.java.en.Then;
    import io.cucumber.java.en.When;
    import org.testng.Assert;
    
    public class LoginPageDefinitions extends BaseStep {
        
        private LoginPage loginPage;
        private DashboardPage dashboardPage;
    
        @Given("User is on HRMLogin page {string}")
        public void userIsOnHRMLoginPage(String baseUrl) {
            loginPage = new LoginPage(getPage());
            loginPage.getUrl(baseUrl);
        }
    
        @When("User enters username as {string} and password as {string}")
        public void userEntersUsernameAsAndPasswordAs(String username, String password) {
            loginPage.login(username, password);
        }
    
        @Then("User should be able to see error message {string}")
        public void userShouldBeAbleToSeeErrorMessage(String expectedErrorMessage) {
            Assert.assertEquals(loginPage.getErrorMessage(), expectedErrorMessage);
        }
    
        @Then("User should be able to see a message {string} below Username")
        public void userShouldBeAbleToSeeAMessageBelowUsername(String expectedErrorMessage) {
            Assert.assertEquals(loginPage.getMissingUsernameErrorMessage(), expectedErrorMessage);
        }
    
        @Then("User should be able to login successfully and new page opens with heading {string}")
        public void userShouldBeAbleToLoginSuccessfullyAndNewPageOpen(String expectedHeading) {
            dashboardPage = new DashboardPage(getPage());
            Assert.assertEquals(dashboardPage.getDashboardPageHeading(), expectedHeading);
    
        }
    
    }
    

    package com.example.runner;
    
    import io.cucumber.testng.AbstractTestNGCucumberTests;
    import io.cucumber.testng.CucumberOptions;
    
    @CucumberOptions(features = "src/test/resources/features/LoginPage.feature",
            glue = {"com.example.hooks","com.example.definitions"},
            plugin = {
                    "pretty",
            }
    )
    
    public class RunnerTests extends AbstractTestNGCucumberTests {
    
    }
    

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Playwright test suite" thread-count="3">
        <test name="Chromium Tests">
            <classes>
                <class name="com.example.runner.RunnerTests"/>
            </classes>
        </test>
    </suite>
    

    mvn clean test
    

    cucumber.publish.enabled=true
    

    • Hooks: Hooks manage browser setup, teardown, and failure handling

    Setting Up Page Object Model with Playwright and JUnit5

    HOME

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>PageObjectModel_Playwright_JUnit5</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>PageObjectModel_Playwright_JUnit5</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <junit.jupiter.engine.version>6.1.0-M1</junit.jupiter.engine.version>
        <junit.jupiter.api.version>6.1.0-M1</junit.jupiter.api.version>
        <junit.jupiter.params.version>6.1.0-M1</junit.jupiter.params.version>
        <maven.compiler.plugin.version>3.14.1</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.site.plugin.version>4.0.0-M16</maven.site.plugin.version>
        <maven.surefire.report.plugin.version>3.5.4</maven.surefire.report.plugin.version>
      </properties>
    
      <dependencies>
    
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-engine</artifactId>
          <version>${junit.jupiter.engine.version}</version>
          <scope>test</scope>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-api</artifactId>
          <version>${junit.jupiter.api.version}</version>
          <scope>test</scope>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-params</artifactId>
          <version>${junit.jupiter.params.version}</version>
          <scope>test</scope>
        </dependency>
    
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
              <source>${maven.compiler.source.version}</source>
              <target>${maven.compiler.target.version}</target>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.plugin.version}</version>
            <configuration>
              <testFailureIgnore>true</testFailureIgnore>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-site-plugin</artifactId>
            <version>${maven.site.plugin.version}</version>
          </plugin>
        </plugins>
      </build>
    
      <reporting>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin.version}</version>
            <configuration>
              <outputName>JUnit5 Report</outputName>
            </configuration>
          </plugin>
        </plugins>
      </reporting>
    
    </project>
    
    

    import com.microsoft.playwright.Page;
    
    public class LoginPage {
    
        private Page page;
    
        //Locators
        private final String usernameLocator = "input[name='username']";
        private final String passwordLocator = "input[name='password']";
        private final String submitButton = "button[type='submit']";
        private final String errorMessage = "//p[contains(@class, 'oxd-text oxd-text--p oxd-alert-content-text')]";
    
        //Constructor
        public LoginPage(Page page){
            this.page = page;
        }
    
        public void login(String username, String password) {
            page.fill(usernameLocator,username);
            page.fill(passwordLocator,password);
            page.click(submitButton);
        }
    
        public String getErrorMessage(){
            return page.textContent(errorMessage);
        }
    }
    

    package org.example.pages;
    
    import com.microsoft.playwright.Page;
    
    public class DashboardPage {
    
        private Page page;
    
        //Locators
        private final String dashboardHeading = "//h6[contains(@class, 'oxd-topbar-header-breadcrumb-module')]";
    
        //Constructor
        public DashboardPage(Page page) {
            this.page = page;
        }
    
        // Methods
        public String getHeading() {
            return page.textContent(dashboardHeading);
        }
    }
    

    package org.example.utils;
    package com.example.utils;
    
    import com.microsoft.playwright.*;
    import org.junit.jupiter.api.*;
    
    // Subclasses will inherit PER_CLASS behavior.
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class BaseTests {
    
        // Shared between all tests in the class.
        static Playwright playwright;
        static Browser browser;
    
        // New instance for each test method.
        BrowserContext context;
        protected Page page;
    
        @BeforeAll
        public static void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    
        }
    
        @AfterAll
        public static void closeBrowser() {
            playwright.close();
        }
    
    
        @BeforeEach
        public void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
        @AfterEach
        public void closeContext() {
            context.close();
        }
    }
    
    Playwright playwright;
    Browser browser = null;
    
    BrowserContext context;
    Page page;
    
      @BeforeAll
        public void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        }
    

    @BeforeMethod
    void createContextAndPage() {
          context = browser.newContext();
          page = context.newPage();
          page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }
    
    @AfterAll
     public static void closeBrowser() {
            playwright.close();
     }
    
    @AfterEach
       public void closeContext() {
            context.close();
    }
    

    package com.example.tests;
    
    import com.example.pages.DashboardPage;
    import com.example.pages.LoginPage;
    import com.example.utils.BaseTests;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    
    public class LoginTests extends BaseTests {
    
        @Test
        public void unsuccessfulLogin() {
    
            LoginPage loginPage = new LoginPage(page);
            loginPage.login("abc","abc");
            String actualErrorMessage = loginPage.getErrorMessage();
            Assertions.assertEquals("Invalid credentials", actualErrorMessage, "");
    
       }
    
        @Test
        public void successfulLogin() {
    
            LoginPage loginPage = new LoginPage(page);
            loginPage.login("Admin","admin123");
            DashboardPage dashboardPage = new DashboardPage(page);
            String actualHeading = dashboardPage.getDashboardPageHeading();
            Assertions.assertEquals("Dashboard",actualHeading, "Unable to login to the application");
    
        }
    
    }
    

    mvn clean test site
    

    Mastering Page Object Model for Playwright with Java and TestNG

    HOME

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>Playwright_TestNG_Demo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>Playwright_TestNG_Demo</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
      </properties>
    
      <dependencies>
    
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>${testng.version}</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
              <source>${maven.compiler.source.version}</source>
              <target>${maven.compiler.target.version}</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.plugin.version}</version>
            <configuration>
              <suiteXmlFiles>
                <suiteXmlFile>testng.xml</suiteXmlFile>
              </suiteXmlFiles>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

    import com.microsoft.playwright.Page;
    
    public class LoginPage {
    
        private Page page;
    
        //Locators
        private final String usernameLocator = "input[name='username']";
        private final String passwordLocator = "input[name='password']";
        private final String submitButton = "button[type='submit']";
        private final String errorMessage = "//p[contains(@class, 'oxd-text oxd-text--p oxd-alert-content-text')]";
    
        //Constructor
        public LoginPage(Page page){
            this.page = page;
        }
    
        public void login(String username, String password) {
            page.fill(usernameLocator,username);
            page.fill(passwordLocator,password);
            page.click(submitButton);
        }
    
        public String getErrorMessage(){
            return page.textContent(errorMessage);
        }
    }
    

    package org.example.pages;
    
    import com.microsoft.playwright.Page;
    
    public class DashboardPage {
    
        private Page page;
    
        //Locators
        private final String dashboardHeading = "//h6[contains(@class, 'oxd-topbar-header-breadcrumb-module')]";
    
        //Constructor
        public DashboardPage(Page page) {
            this.page = page;
        }
    
        // Methods
        public String getHeading() {
            return page.textContent(dashboardHeading);
        }
    }
    

    package org.example.utils;
    
    import com.microsoft.playwright.*;
    import org.testng.annotations.AfterClass;
    import org.testng.annotations.AfterMethod;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.BeforeMethod;
    
    public class BaseTests {
    
        // Shared between all tests in this class.
        protected Playwright playwright;
        protected Browser browser;
    
        // New instance for each test method.
        protected BrowserContext context;
        protected Page page;
    
        @BeforeClass
        public void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
        }
    
        @BeforeMethod
        public void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
        @AfterMethod
        public void closeContext() {
            context.close();
        }
    
        @AfterClass
        public void closeBrowser() {
            playwright.close();
        }
    }
    
    Playwright playwright;
    Browser browser = null;
    
    BrowserContext context;
    Page page;
    
    @BeforeClass
    public void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    }
    

    @BeforeMethod
    void createContextAndPage() {
          context = browser.newContext();
          page = context.newPage();
          page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }
    
    @AfterMethod
    void closeContext() {
           context.close();
    }
    
    @AfterClass
    void closeBrowser() {
          playwright.close();
    }
    

    package org.example.tests;
    
    import org.example.pages.DashboardPage;
    import org.example.pages.LoginPage;
    import org.example.utils.BaseTests;
    import org.testng.Assert;
    import org.testng.annotations.Test;
    
    public class LoginTests extends BaseTests {
    
        @Test
        public void loginToApplication(){
            LoginPage loginPage = new LoginPage(page);
            loginPage.login("Admin","admin123");
            DashboardPage dashboardPage = new DashboardPage(page);
            String actualHeading = dashboardPage.getHeading();
            Assert.assertEquals(actualHeading,"Dashboard", "Unable to login to the application");
        }
    
        @Test
        public void invalidCredentials() {
            LoginPage loginPage = new LoginPage(page);
            loginPage.login("Playwright","test");
            Assert.assertEquals(loginPage.getErrorMessage(), "Invalid credentials" ,"Incorrect Error Message is displayed");
    
        }
    }
    

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Page Object Model Playwright test suite">
        <test name="Chrome Test">
            <parameter name="browser" value="chromium" />
            <classes>
                <class name="org.example.tests.LoginTests"/>
            </classes>
        </test>
    </suite>    
    

    Cross Browser Testing with Playwright and Java

    HOME

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>Playwright_TestNG_Demo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>Playwright_TestNG_Demo</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
      </properties>
    
      <dependencies>
    
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>${testng.version}</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
              <source>${maven.compiler.source.version}</source>
              <target>${maven.compiler.target.version}</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.plugin.version}</version>
            <configuration>
              <suiteXmlFiles>
                <suiteXmlFile>testng.xml</suiteXmlFile>
              </suiteXmlFiles>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

    package com.example;
    
    import com.microsoft.playwright.*;
    import org.testng.annotations.*;
    
    public class BaseClass {
    
        // Shared between all tests in this class.
        Playwright playwright;
        Browser browser = null;
    
        // New instance for each test method.
        BrowserContext context;
        Page page;
    
        @BeforeClass
        @Parameters("browser")
        void launchBrowser(String browserName) {
    
            playwright = Playwright.create();
            BrowserType browserType = null;
    
            if (browserName.equals("chromium")) {
                browserType = playwright.chromium();
            } else if (browserName.equals("firefox")) {
                browserType = playwright.firefox();
            } else if (browserName.equals("webkit")) {
                browserType = playwright.webkit();
            }
    
            browser = browserType.launch(new BrowserType.LaunchOptions().setHeadless(false));
        }
    
        @BeforeMethod
        void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
        @AfterMethod
        void closeContext() {
            context.close();
        }
    
        @AfterClass
        void closeBrowser() {
            playwright.close();
        }
    }
    

    Playwright playwright;
    Browser browser = null;
    
    BrowserContext context;
    Page page;
    
    @BeforeClass
        @Parameters("browser")
        void launchBrowser(String browserName) {
    
            playwright = Playwright.create();
            BrowserType browserType = null;
    
            if (browserName.equals("chromium")) {
                browserType = playwright.chromium();
            } else if (browserName.equals("firefox")) {
                browserType = playwright.firefox();
            } else if (browserName.equals("webkit")) {
                browserType = playwright.webkit();
            }
    
            browser = browserType.launch(new BrowserType.LaunchOptions().setHeadless(false));
        }
    

    @BeforeMethod
    void createContextAndPage() {
          context = browser.newContext();
          page = context.newPage();
          page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }
    
    @AfterMethod
       void closeContext() {
           context.close();
    }
    
    @AfterClass
    void closeBrowser() {
          playwright.close();
    }
    

    package com.example;
    
    import org.testng.annotations.*;
    
    import static org.testng.Assert.assertEquals;
    
    public class CrossBrowserTests extends BaseClass{
    
        @Test
        void verifyPageTitle() {
            System.out.println("Page Title :" + page.title());
            assertEquals("OrangeHRM", page.title());
        }
    
        @Test
        void verifyInvalidCredentials() {
            page.locator("input[name='username']").fill("Playwright");
            page.locator("input[name='password']").fill("admin123");
            page.locator("button[type='submit']").click();
            String expectedValue = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]").textContent();
            assertEquals(expectedValue,"Invalid credentials");
        }
        
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Playwright test suite">
        <test name="Chrome Test">
            <parameter name="browser" value="chromium" />
            <classes>
               <class name="com.example.CrossBrowserTests"/>
        </classes>
        </test>
        <test name="firefox Test">
            <parameter name="browser" value="firefox" />
            <classes>
                <class name="com.example.CrossBrowserTests"/>
            </classes>
        </test> <!-- Test -->
    
        <test name="WebKit Test">
            <parameter name="browser" value="webkit" />
            <classes>
                <class name="com.example.CrossBrowserTests"/>
            </classes>
        </test> <!-- Test -->
    </suite>
    

    void launchBrowser(@Optional ("chromium")  String browserName) 
    

    This will run the tests in all 3 browsers as mentioned in the .xml file.

    Setup Playwright Java with JUnit5: A Comprehensive Guide

    HOME

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>Playwright_Junit5_Demo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>Playwright_Junit5_Demo</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <junit.jupiter.engine.version>5.11.0-M2</junit.jupiter.engine.version>
        <junit.jupiter.api.version>5.11.0-M2</junit.jupiter.api.version>
        <junit.jupiter.params.version>5.11.0-M2</junit.jupiter.params.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.2.5</maven.surefire.plugin.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.site.plugin.version>4.0.0-M16</maven.site.plugin.version>
        <maven.surefire.report.plugin.version>3.5.4</maven.surefire.report.plugin.version>
      </properties>
    
      <dependencies>
    
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-engine</artifactId>
          <version>${junit.jupiter.engine.version}</version>
          <scope>test</scope>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-api</artifactId>
          <version>${junit.jupiter.api.version}</version>
          <scope>test</scope>
        </dependency>
    
        <dependency>
          <groupId>org.junit.jupiter</groupId>
          <artifactId>junit-jupiter-params</artifactId>
          <version>${junit.jupiter.params.version}</version>
          <scope>test</scope>
        </dependency>
    
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
              <source>${maven.compiler.source.version}</source>
              <target>${maven.compiler.target.version}</target>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.plugin.version}</version>
            <configuration>
              <testFailureIgnore>true</testFailureIgnore>
            </configuration>
          </plugin>
    
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-site-plugin</artifactId>
            <version>${maven.site.plugin.version}</version>
          </plugin>
        </plugins>
      </build>
    
      <reporting>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin.version}</version>
            <configuration>
              <outputName>JUnit5 Report</outputName>
            </configuration>
          </plugin>
        </plugins>
      </reporting>
    
    </project>
    

    <reporting>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-report-plugin</artifactId>
            <version>${maven.surefire.report.plugin.version}</version>
            <configuration>
              <outputName>JUnit5 Report</outputName>
            </configuration>
          </plugin>
        </plugins>
      </reporting>
    
    

    package com.example;
    
    import com.microsoft.playwright.Browser;
    import com.microsoft.playwright.BrowserContext;
    import com.microsoft.playwright.Page;
    import com.microsoft.playwright.Playwright;
    import org.junit.jupiter.api.*;
    
    // Subclasses will inherit PER_CLASS behavior.
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)
    public class BaseClass {
    
        // Shared between all tests in the class.
        Playwright playwright;
        Browser browser;
    
        @BeforeAll
        void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch();
    
        }
    
        @AfterAll
        void closeBrowser() {
            playwright.close();
        }
    
        // New instance for each test method.
        BrowserContext context;
        Page page;
    
        @BeforeEach
        void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
        @AfterEach
        void closeContext() {
            context.close();
        }
    }
    

    Playwright playwright;
    Browser browser;
    
    BrowserContext context;
    Page page;
    
    @BeforeEach
        void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
    @AfterEach
        void closeContext() {
            context.close();
        }
    
    @AfterAll
        void closeBrowser() {
            playwright.close();
        }
    

    package com.example;
    
    import org.junit.jupiter.api.Test;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    
    public class PlaywrightTests extends BaseClass{
    
        @Test
        void verifyPageTitle() {
            System.out.println("Page Title :" + page.title());
            assertEquals("OrangeHRM", page.title());
        }
    
        @Test
        void verifyLogin() {
            page.locator("input[name='username']").fill("Admin");
            page.locator("input[name='password']").fill("admin123");
            page.locator("button[type='submit']").click();
            String expectedValue = page.locator("//h6[contains(@class, \"oxd-topbar-header-breadcrumb-module\")]").textContent();
            assertEquals(expectedValue,"Dashboard");
        }
    
        @Test
        void verifyInvalidCredentials() {
            page.locator("input[name='username']").fill("Playwright");
            page.locator("input[name='password']").fill("admin123");
            page.locator("button[type='submit']").click();
            String expectedValue = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]").textContent();
            assertEquals(expectedValue,"Invalid credentials");
        }
    }
    
    

    mvn clean test site
    

    Integration of Playwright Java with TestNG

    HOME

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.example</groupId>
      <artifactId>Playwright_TestNG_Demo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>jar</packaging>
    
      <name>Playwright_TestNG_Demo</name>
      <url>http://maven.apache.org</url>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <playwright.version>1.57.0</playwright.version>
        <testng.version>7.11.0</testng.version>
        <maven.compiler.plugin.version>3.13.0</maven.compiler.plugin.version>
        <maven.compiler.source.version>17</maven.compiler.source.version>
        <maven.compiler.target.version>17</maven.compiler.target.version>
        <maven.surefire.plugin.version>3.5.4</maven.surefire.plugin.version>
      </properties>
    
      <dependencies>
    
        <dependency>
          <groupId>com.microsoft.playwright</groupId>
          <artifactId>playwright</artifactId>
          <version>${playwright.version}</version>
        </dependency>
    
        <dependency>
          <groupId>org.testng</groupId>
          <artifactId>testng</artifactId>
          <version>${testng.version}</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.plugin.version}</version>
            <configuration>
              <source>${maven.compiler.source.version}</source>
              <target>${maven.compiler.target.version}</target>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.plugin.version}</version>
            <configuration>
              <suiteXmlFiles>
                <suiteXmlFile>testng.xml</suiteXmlFile>
              </suiteXmlFiles>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
    <suite name="Playwright test suite">
        <test name="Integration of Playwright Java with TestNG">
        <classes>
            <class name="com.example.TestNG_Demo_Tests">
            </class>
        </classes>
        </test>
    </suite>
    

    package com.example;
    
    import com.microsoft.playwright.*;
    import org.testng.annotations.*;
    
    import static org.testng.Assert.assertEquals;
    
    
    public class TestNG_Demo_Tests {
    
        // Shared between all tests in this class.
        Playwright playwright;
        Browser browser;
    
        // New instance for each test method.
        BrowserContext context;
        Page page;
    
        @BeforeClass
        void launchBrowser() {
            playwright = Playwright.create();
            browser = playwright.chromium().launch();
        }
    
        @BeforeMethod
        void createContextAndPage() {
            context = browser.newContext();
            page = context.newPage();
            page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
        }
    
        @Test
        void verifyPageTitle() {
            System.out.println("Page Title :" + page.title());
            assertEquals("OrangeHRM", page.title());
        }
    
        @Test
        void verifyLogin() {
            page.locator("input[name='username']").fill("Admin");
            page.locator("input[name='password']").fill("admin123");
            page.locator("button[type='submit']").click();
            String expectedValue = page.locator("//h6[contains(@class, \"oxd-topbar-header-breadcrumb-module\")]").textContent();
            assertEquals(expectedValue,"Dashboard");
        }
    
        @Test
        void verifyInvalidCredentials() {
            page.locator("input[name='username']").fill("Playwright");
            page.locator("input[name='password']").fill("admin123");
            page.locator("button[type='submit']").click();
            String expectedValue = page.locator("//p[contains(@class, \"oxd-text oxd-text--p oxd-alert-content-text\")]").textContent();
            assertEquals(expectedValue,"Invalid credentials");
        }
    
        @AfterMethod
        void closeContext() {
            context.close();
        }
    
        @AfterClass
        void closeBrowser() {
            playwright.close();
        }
    }
    
    Playwright playwright;
    Browser browser = null;
    
    BrowserContext context;
    Page page;
    

    This method is annotated with @BeforeClass, indicating it runs once before any test methods in the current class.

    The browser is launched in Chromium and non-headless mode (setHeadless(false)), meaning an actual browser window is opened.

    @BeforeMethod
    void createContextAndPage() {
          context = browser.newContext();
          page = context.newPage();
          page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    }
    
    @AfterMethod
       void closeContext() {
           context.close();
    }
    
    @AfterClass
    void closeBrowser() {
          playwright.close();
    }
    

    Run Playwright Java tests in headed mode

    HOME

    launch(new BrowserType.LaunchOptions().setHeadless(false));
    

    import com.microsoft.playwright.Browser;
    import com.microsoft.playwright.BrowserType;
    import com.microsoft.playwright.Page;
    import com.microsoft.playwright.Playwright;
    
    import java.util.regex.Pattern;
    
    import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
    
    public class PlaywrightDemo {
    
        public static void main(String[] args) {
    
            try (Playwright playwright = Playwright.create()) {
    
                Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
                Page page = browser.newPage();
                page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
                page.waitForTimeout(2000);
                System.out.println("Title :" + page.title());
                assertThat(page).hasTitle(Pattern.compile("OrangeHRM"));
            }
        }
    }
    

    (Playwright playwright = Playwright.create()) 
    
    Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setHeadless(false));
    
    Page page = browser.newPage();
    
    page.navigate("https://opensource-demo.orangehrmlive.com/web/index.php/auth/login");
    
    page.waitForTimeout(2000);
    
    System.out.println("Title :" + page.title());
    
    assertThat(page).hasTitle(Pattern.compile("OrangeHRM"));