Wednesday, 8 July 2026

Playwright TestNG Framework Setup Using Java (Step-by-Step Guide)

As automation projects grow, writing standalone Playwright scripts becomes difficult to maintain. Enterprise teams use testing frameworks like TestNG to organize test execution, manage test suites, perform assertions, generate reports, and execute tests in parallel.

In this guide, we'll build a Playwright TestNG framework from scratch using Java and follow industry best practices.


Why Use TestNG with Playwright?

TestNG offers several features that complement Playwright:

  • Test annotations (@Test, @BeforeMethod, @AfterMethod)
  • Test grouping
  • Parallel execution
  • Parameterized tests
  • Test dependencies
  • HTML reports
  • Easy integration with CI/CD tools

Combining Playwright with TestNG results in a scalable and maintainable automation framework.


Prerequisites

Before starting, ensure you have:

  • Java 17 or later
  • Maven installed
  • IntelliJ IDEA or Eclipse
  • Basic knowledge of Playwright
  • Browser binaries installed

Step 1: Create a Maven Project

Create a new Maven project in your IDE.

Suggested structure:

playwright-testng-framework
│
├── src
│   ├── main
│   │    └── java
│   │         ├── pages
│   │         ├── utils
│   │         └── base
│   │
│   └── test
│        └── java
│             └── tests
│
├── testng.xml
├── pom.xml
└── README.md

Step 2: Add Dependencies

Add the required dependencies to your pom.xml.

<dependencies>

    <dependency>
        <groupId>com.microsoft.playwright</groupId>
        <artifactId>playwright</artifactId>
        <version>1.55.0</version>
    </dependency>

    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>7.11.0</version>
        <scope>test</scope>
    </dependency>

</dependencies>

Refresh the Maven project after saving the file.


Step 3: Create the BaseTest Class

The BaseTest class is responsible for browser setup and cleanup.

public class BaseTest {

    protected Playwright playwright;
    protected Browser browser;
    protected BrowserContext context;
    protected Page page;

    @BeforeMethod
    public void setup() {

        playwright = Playwright.create();

        browser = playwright.chromium().launch(
                new BrowserType.LaunchOptions()
                        .setHeadless(false));

        context = browser.newContext();

        page = context.newPage();
    }

    @AfterMethod
    public void tearDown() {

        context.close();
        browser.close();
        playwright.close();
    }
}

This ensures every test starts with a fresh browser session.


Step 4: Create a Page Object

Example LoginPage.java.

public class LoginPage {

    private final Page page;

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

    public void login(String username, String password) {

        page.fill("#username", username);

        page.fill("#password", password);

        page.click("#loginButton");
    }
}

Keeping page interactions separate improves maintainability.


Step 5: Create Your First Test

Create a TestNG test class.

public class LoginTest extends BaseTest {

    @Test

    public void verifySuccessfulLogin() {

        page.navigate("https://example.com/login");

        LoginPage loginPage =
                new LoginPage(page);

        loginPage.login(
                "admin",
                "password123");

        assertThat(page)
                .hasTitle("Dashboard");
    }
}

Notice how the test focuses only on business logic while setup is handled by BaseTest.


Step 6: Create testng.xml

TestNG uses an XML file to define test suites.

<!DOCTYPE suite SYSTEM
"https://testng.org/testng-1.0.dtd">

<suite name="Playwright Suite">

    <test name="Smoke Tests">

        <classes>

            <class name="tests.LoginTest"/>

        </classes>

    </test>

</suite>

You can execute all tests by running this suite file.


Step 7: Execute Tests

You can run tests in several ways:

  • Directly from IntelliJ IDEA
  • Using Eclipse
  • From Maven
  • Through Jenkins or another CI/CD pipeline

Example Maven command:

mvn test

Parallel Execution

TestNG supports parallel execution through testng.xml.

Example:

<suite name="Playwright Suite"
       parallel="methods"
       thread-count="4">

</suite>

This executes four test methods simultaneously, reducing execution time.


Adding Groups

TestNG groups help organize test cases.

Example:

@Test(groups = {"Smoke"})
public void loginTest() {

}

You can create groups such as:

  • Smoke
  • Regression
  • Sanity
  • API
  • UI

Generating Reports

After execution, TestNG automatically creates reports inside the test-output folder.

Common reports include:

  • HTML report
  • Failed test report
  • Execution summary

These reports provide quick insight into test results.


Recommended Framework Structure

As your project grows, consider organizing it like this:

src
├── main
│   ├── base
│   ├── pages
│   ├── utils
│   ├── constants
│   └── listeners
│
├── test
│   ├── tests
│   ├── testdata
│   └── resources
│
├── reports
├── screenshots
├── videos
└── testng.xml

This structure is easy to maintain and scales well for enterprise projects.


Best Practices

Keep Test Logic Separate

Business actions belong in page classes, not in test methods.


Reuse Browser Initialization

Initialize Playwright once in the base class instead of repeating code.


Use Assertions Wisely

Verify business outcomes rather than implementation details.

Examples:

  • User logged in successfully
  • Order created
  • Invoice downloaded

Capture Screenshots on Failure

Integrate screenshot capture inside the @AfterMethod hook for failed tests.


Store Test Data Separately

Avoid hardcoding values.

Instead, use:

  • JSON
  • Excel
  • CSV
  • Properties files

Common Interview Questions

Why combine Playwright with TestNG?

TestNG provides test lifecycle management, reporting, grouping, parameterization, and parallel execution, making Playwright projects easier to manage.


What is the purpose of @BeforeMethod?

It runs before every test method and is commonly used to initialize the browser and create a new page.


What is the role of BaseTest?

BaseTest centralizes browser setup and cleanup, reducing code duplication across test classes.


Can Playwright tests run in parallel with TestNG?

Yes. By configuring parallel and thread-count in testng.xml, multiple tests can run simultaneously.


Conclusion

Using Playwright with TestNG is an excellent choice for building robust and maintainable Java automation frameworks.

In this tutorial, you learned how to:

  • Create a Maven project
  • Add Playwright and TestNG dependencies
  • Build a reusable BaseTest
  • Implement the Page Object Model
  • Configure testng.xml
  • Execute tests
  • Enable parallel execution
  • Apply framework best practices

With this foundation, you're ready to build enterprise-grade automation frameworks that are scalable, reusable, and easy to integrate with CI/CD pipelines.

Tuesday, 7 July 2026

How to Perform API Testing in Playwright Using Java (Complete Guide with Examples)

Modern applications rely heavily on APIs to exchange data between frontend and backend systems. While Playwright is widely known for browser automation, it also provides powerful built-in support for API testing.

This means you can automate both UI tests and REST API tests using the same framework, reducing the need for separate tools in many automation projects.

In this tutorial, you'll learn how to perform API testing in Playwright using Java with practical examples.


Why Use Playwright for API Testing?

Playwright provides a built-in HTTP client that supports:

  • GET requests
  • POST requests
  • PUT requests
  • PATCH requests
  • DELETE requests
  • Authentication
  • Custom headers
  • Query parameters
  • Response validation

Using one framework for both UI and API testing simplifies project maintenance and reduces dependencies.


Creating an API Request Context

Playwright uses an APIRequestContext to send HTTP requests.

Example:

Playwright playwright = Playwright.create();

APIRequestContext request =
    playwright.request().newContext();

The request context acts as the client for all API operations.


Sending a GET Request

Let's retrieve a list of users.

APIResponse response =
    request.get("https://reqres.in/api/users?page=2");

You can verify the response status:

System.out.println(response.status());

Expected output:

200

Reading the Response Body

To print the response content:

String body = response.text();

System.out.println(body);

This returns the JSON response as a string.


Sending a POST Request

POST requests are commonly used to create resources.

Example:

String json = """
{
  "name":"John",
  "job":"QA Engineer"
}
""";

APIResponse response =
    request.post(
        "https://reqres.in/api/users",
        RequestOptions.create()
            .setData(json)
    );

Expected status:

201 Created

Sending a PUT Request

PUT requests update existing resources.

String updateJson = """
{
  "name":"John",
  "job":"Senior QA Engineer"
}
""";

APIResponse response =
    request.put(
        "https://reqres.in/api/users/2",
        RequestOptions.create()
            .setData(updateJson)
    );

Sending a DELETE Request

Deleting resources is equally simple.

APIResponse response =
    request.delete(
        "https://reqres.in/api/users/2"
    );

Expected response:

204 No Content

Adding Custom Headers

Many APIs require custom headers.

Example:

APIResponse response =
    request.get(
        "https://example.com/api/users",
        RequestOptions.create()
            .setHeader(
                "Authorization",
                "Bearer YOUR_TOKEN"
            )
            .setHeader(
                "Content-Type",
                "application/json"
            )
    );

Sending Query Parameters

Suppose the API accepts pagination.

APIResponse response =
    request.get(
        "https://reqres.in/api/users?page=2"
    );

Alternatively, build URLs dynamically for different test scenarios.


Validating the Response

A good API test should verify more than the status code.

Example:

assert response.status() == 200;

assert response.text().contains("Michael");

You can validate:

  • Status code
  • Response body
  • Headers
  • Response time
  • Business data

Authentication

Many enterprise APIs use Bearer tokens.

Example:

APIRequestContext request =
    playwright.request().newContext(
        new APIRequest.NewContextOptions()
            .setExtraHTTPHeaders(
                Map.of(
                    "Authorization",
                    "Bearer YOUR_ACCESS_TOKEN"
                )
            )
    );

This automatically sends the token with every request.


Complete Example

Playwright playwright = Playwright.create();

APIRequestContext request =
        playwright.request().newContext();

APIResponse response =
        request.get(
            "https://reqres.in/api/users?page=2"
        );

System.out.println(
        response.status()
);

System.out.println(
        response.text()
);

request.dispose();
playwright.close();

Best Practices

Reuse the API Request Context

Create one request context and reuse it throughout your test suite instead of creating a new one for every request.


Keep Test Data Separate

Store request payloads in JSON files instead of hardcoding them inside test classes.

Example:

testdata/
    createUser.json
    updateUser.json

Validate Business Responses

Don't verify only the status code.

Also validate:

  • Response fields
  • Error messages
  • IDs
  • Dates
  • Business rules

Use Environment Variables

Store:

  • Base URL
  • Tokens
  • Credentials

inside configuration files rather than directly in code.


Common Interview Questions

Can Playwright perform API testing?

Yes.

Playwright includes a built-in HTTP client through APIRequestContext.


Which HTTP methods does Playwright support?

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

Why use Playwright for API testing?

Because it allows teams to automate both UI and API tests using the same framework, improving consistency and reducing maintenance.


How do you authenticate API requests?

Use request headers with an Authorization token or configure default headers when creating the request context.


Conclusion

Playwright is much more than a browser automation framework. Its built-in API testing capabilities make it a powerful choice for modern automation engineers.

In this tutorial, you learned how to:

  • Create an API request context
  • Send GET, POST, PUT, and DELETE requests
  • Validate responses
  • Add authentication
  • Use headers and query parameters
  • Follow best practices for scalable API automation

By combining UI and API testing within the same Playwright project, you can build efficient, maintainable, and enterprise-ready automation frameworks.

Monday, 6 July 2026

How to Handle Multiple Browser Tabs and Windows in Playwright Using Java (Complete Guide)

Modern web applications often open new browser tabs or windows during user interactions. These may appear when users:

  • Download reports
  • Open help documentation
  • Sign in using Google or Microsoft
  • Complete online payments
  • View invoices
  • Open product details in a new tab

As an automation engineer, you need to switch between these tabs and windows seamlessly.

In this tutorial, we'll learn how to handle multiple browser tabs and windows in Playwright using Java.


Understanding Browser Tabs in Playwright

Unlike older automation frameworks, Playwright treats every browser tab as a Page object.

Whenever a new tab or popup opens, Playwright creates a new Page instance.

This makes switching between tabs much simpler.


Example Scenario

Imagine an e-commerce application.

  1. Open the home page.
  2. Click View Product.
  3. Product opens in a new tab.
  4. Verify the product title.
  5. Close the product tab.
  6. Continue testing on the original tab.

Let's automate this workflow.


Waiting for a New Browser Tab

Playwright provides the waitForPopup() method.

Page productPage = page.waitForPopup(() -> {
    page.locator("#viewProduct").click();
});

What happens here?

  • Playwright waits for a new tab.
  • The click action triggers the popup.
  • The new tab is returned as a Page object.

Verify the New Page

Once the new tab opens, you can interact with it just like the original page.

System.out.println(productPage.title());

productPage.locator("#addToCart").click();

No additional switching commands are required.


Getting the URL of the New Tab

System.out.println(productPage.url());

You can also verify it using assertions.

assertThat(productPage)
        .hasURL("https://example.com/product");

Closing the Popup Window

Once you're done with the popup:

productPage.close();

After closing, your original page remains active.


Working with Multiple Tabs

Suppose your application opens several tabs.

Example:

Page reportsPage = page.waitForPopup(() -> {
    page.locator("#reports").click();
});

Page invoicePage = page.waitForPopup(() -> {
    page.locator("#invoice").click();
});

Now you have two separate Page objects.

You can interact with each independently.


Managing All Open Pages

Playwright stores all open pages inside the browser context.

BrowserContext context = browser.newContext();

List<Page> pages = context.pages();

System.out.println(pages.size());

This returns every open browser tab.


Switching Between Tabs

Switching is simple because each tab has its own Page reference.

Page homePage = pages.get(0);

Page reportsPage = pages.get(1);

Page invoicePage = pages.get(2);

Simply use the desired Page object.


Example: Google Login Popup

Many websites use OAuth authentication.

Example:

  1. Click Sign in with Google
  2. Google login opens in a new window.
  3. Enter credentials.
  4. Return to application.
Page googleLogin = page.waitForPopup(() -> {

    page.locator("#googleLogin").click();

});

googleLogin.locator("#identifierId")
           .fill("user@example.com");

This approach works for any external authentication window.


Handling Multiple Browser Windows

Playwright treats browser windows exactly like browser tabs.

No special API is required.

Whether the application opens:

  • A new tab
  • A new browser window

Playwright returns a Page object.


Best Practices

Always Use waitForPopup()

Avoid:

page.locator("#openReport").click();

Then trying to search for the new page afterwards.

Instead:

Page reportPage =
    page.waitForPopup(() -> {

        page.locator("#openReport").click();

    });

This prevents timing issues.


Store Page References

Use meaningful variable names.

Good:

loginPage

paymentPage

reportPage

invoicePage

Avoid:

page1

page2

page3

Close Unused Tabs

Leaving unnecessary tabs open can:

  • Consume memory
  • Slow down execution
  • Make debugging harder

Always close tabs when they are no longer needed.


Verify Navigation

After switching tabs, verify:

  • URL
  • Page title
  • Key elements

Example:

assertThat(productPage)
        .hasTitle("Laptop");

Common Mistakes

Mistake 1

Using the original page after opening a popup.

Incorrect:

page.locator("#checkout").click();

Correct:

checkoutPage.locator("#checkout").click();

Mistake 2

Using hard waits.

Avoid:

Thread.sleep(5000);

Playwright automatically waits for the popup.


Complete Example

BrowserContext context =
        browser.newContext();

Page page = context.newPage();

page.navigate("https://example.com");

Page popup =
        page.waitForPopup(() -> {

            page.locator("#openWindow").click();

        });

System.out.println(popup.title());

popup.locator("#continue")
     .click();

popup.close();

System.out.println(page.title());

Interview Questions

How does Playwright represent a browser tab?

Every browser tab or browser window is represented by a Page object.


Which method waits for a new browser tab?

waitForPopup()

How do you retrieve all open tabs?

context.pages()

Can Playwright automate multiple browser windows?

Yes.

Browser windows and tabs are handled in the same way using separate Page objects.


Conclusion

Handling multiple browser tabs and windows is an essential skill for automation engineers working on enterprise applications.

Playwright makes this process simple by representing each browser tab as a Page object and providing APIs like waitForPopup() and context.pages().

In this tutorial, you learned:

  • How to wait for new tabs
  • How to switch between browser windows
  • How to verify popup content
  • How to close windows
  • Best practices for multi-tab automation

With these techniques, you'll be able to automate payment gateways, report downloads, external authentication flows, and many other real-world scenarios confidently.

Saturday, 4 July 2026

How to Handle Frames and iFrames in Playwright Using Java

Modern web applications frequently use frames and iFrames to embed content from external or internal sources.

Common examples include:

  • Payment gateways
  • Advertisement sections
  • Chat widgets
  • Embedded videos
  • Document viewers
  • Third-party integrations

As automation engineers, we must know how to switch into these frames and interact with elements inside them.

In this article, we'll learn how to handle frames and iFrames in Playwright using Java.


What is an iFrame?

An iFrame (Inline Frame) is an HTML element that loads another webpage inside the current webpage.

Example:

<iframe id="paymentFrame" src="payment.html"></iframe>

Elements inside an iFrame are isolated from the parent page.

This means the following code will fail:

page.locator("#cardNumber").fill("1234567890123456");

Playwright cannot access elements inside an iFrame directly from the main page context.


How Playwright Handles Frames

Playwright provides the frameLocator() method to interact with frames easily.

Example:

FrameLocator paymentFrame =
        page.frameLocator("#paymentFrame");

paymentFrame
        .locator("#cardNumber")
        .fill("1234567890123456");

This automatically switches into the frame before performing the action.


Handling Frames Using Frame Locator

Consider the following HTML:

<iframe id="loginFrame"></iframe>

Automation example:

page.frameLocator("#loginFrame")
        .locator("#username")
        .fill("admin");

page.frameLocator("#loginFrame")
        .locator("#password")
        .fill("password");

page.frameLocator("#loginFrame")
        .locator("#loginButton")
        .click();

Storing Frame Reference

If multiple interactions occur inside the same frame, storing the frame reference improves readability.

Example:

FrameLocator loginFrame =
        page.frameLocator("#loginFrame");

loginFrame.locator("#username")
        .fill("admin");

loginFrame.locator("#password")
        .fill("password");

loginFrame.locator("#loginButton")
        .click();

Accessing Frames by Name

Some applications provide frame names instead of IDs.

Example:

Frame frame =
        page.frame("paymentFrame");

You can then interact with elements:

frame.locator("#cardNumber")
        .fill("1234567890123456");

Accessing Frames by URL

Sometimes frames don't have IDs or names.

Example:

Frame frame =
        page.frameByUrl("**/payment/**");

This is useful when working with third-party integrations.


Handling Nested Frames

Some applications contain frames inside other frames.

Example:

page.frameLocator("#parentFrame")
        .frameLocator("#childFrame")
        .locator("#submitButton")
        .click();

Playwright makes nested frame handling very simple compared to traditional automation frameworks.


Getting All Available Frames

You can retrieve all frames present on the page.

Example:

for (Frame frame : page.frames()) {
    System.out.println(frame.url());
}

This is useful during debugging.


Real World Example: Payment Gateway

Consider an online shopping application.

Steps:

  1. Open checkout page.
  2. Payment gateway opens inside an iFrame.
  3. Enter card details.
  4. Submit payment.

Example:

FrameLocator paymentFrame =
        page.frameLocator("#paymentFrame");

paymentFrame.locator("#cardNumber")
        .fill("4111111111111111");

paymentFrame.locator("#expiryDate")
        .fill("12/30");

paymentFrame.locator("#cvv")
        .fill("123");

paymentFrame.locator("#payNow")
        .click();

Common Mistakes

Using Page Locator Instead of Frame Locator

Incorrect:

page.locator("#cardNumber")
        .fill("4111111111111111");

Correct:

page.frameLocator("#paymentFrame")
        .locator("#cardNumber")
        .fill("4111111111111111");

Using Hardcoded Waits

Avoid:

Thread.sleep(5000);

Playwright automatically waits for frames and elements when using locators.


Best Practices

Prefer frameLocator()

frameLocator() is cleaner and easier to maintain than manual frame handling.


Store Frame References

When interacting multiple times with the same frame, store the reference in a variable.


Use Meaningful Variable Names

Good examples:

paymentFrame
loginFrame
chatWidgetFrame

Avoid:

frame1
frame2

Validate Frame Visibility

Before interacting with frames, verify they are loaded properly.

Example:

assertThat(
        page.locator("#paymentFrame")
).isVisible();

Interview Questions

What is the difference between a Frame and an iFrame?

An iFrame is an HTML element that embeds another document inside the current page.

In automation testing, both are generally handled similarly.


Which Playwright method is commonly used to handle iFrames?

frameLocator()

How do you handle nested frames?

Use chained frame locators:

frameLocator()
        .frameLocator()

How can you retrieve all frames available on a page?

page.frames();

Conclusion

Frames and iFrames are widely used in modern web applications, especially in enterprise systems and third-party integrations.

Fortunately, Playwright provides simple and powerful APIs to handle them efficiently.

In this article, you learned:

  • What frames and iFrames are
  • How to use frameLocator()
  • How to handle nested frames
  • How to retrieve frame information
  • Best practices for frame automation

Mastering frame handling will make your Playwright framework more robust and capable of handling real-world applications.

In the next article, we'll learn how to handle multiple browser tabs and windows in Playwright using Java.

Thursday, 2 July 2026

How to Upload and Download Files in Playwright Using Java

File upload and download functionality is common in modern web applications. Examples include:

  • Uploading profile pictures
  • Importing CSV files
  • Downloading invoices
  • Exporting reports
  • Uploading documents and attachments

As automation engineers, we must verify these workflows efficiently and reliably.

In this article, we'll learn how to handle file uploads and downloads in Playwright using Java.


Why Playwright Makes File Handling Easy

Traditional automation frameworks often require external tools or complex workarounds for handling native file dialogs.

Playwright provides built-in APIs that make file upload and download automation straightforward and reliable.


Uploading a Single File

Suppose an application contains the following HTML element:

<input type="file" id="uploadFile">

Uploading a file is simple:

page.setInputFiles(
    "#uploadFile",
    Paths.get("src/test/resources/sample.pdf")
);

Playwright automatically handles the file selection dialog behind the scenes.


Complete Example for File Upload

page.navigate("https://example.com/upload");

page.setInputFiles(
    "#uploadFile",
    Paths.get("src/test/resources/resume.pdf")
);

page.locator("#submitButton").click();

This uploads the file and submits the form.


Uploading Multiple Files

Many applications allow users to upload multiple files simultaneously.

Example:

page.setInputFiles(
    "#documents",
    new Path[] {
        Paths.get("invoice.pdf"),
        Paths.get("contract.pdf"),
        Paths.get("report.xlsx")
    }
);

This uploads all three files in a single operation.


Removing Uploaded Files

Sometimes tests need to verify the remove or clear functionality.

Example:

page.setInputFiles(
    "#uploadFile",
    new Path[] {}
);

This clears the selected files.


Waiting for File Downloads

Downloads require a slightly different approach.

Playwright provides the waitForDownload() method.

Example:

Download download =
    page.waitForDownload(() -> {
        page.locator("#downloadReport").click();
    });

Playwright waits until the file download begins and returns a download object.


Getting the Downloaded File Name

Example:

System.out.println(
    download.suggestedFilename()
);

Output:

SalesReport_2026.xlsx

Saving Downloaded Files

By default, Playwright stores downloads in a temporary location.

To save them permanently:

download.saveAs(
    Paths.get(
        "downloads/" +
        download.suggestedFilename()
    )
);

This saves the file inside the downloads folder.


Complete Download Example

Download download =
    page.waitForDownload(() -> {
        page.locator("#downloadInvoice").click();
    });

download.saveAs(
    Paths.get(
        "downloads/invoice.pdf"
    )
);

Recommended Folder Structure

A clean project structure helps maintain large automation frameworks.

Example:

project
├── downloads
│   ├── invoice.pdf
│   └── report.xlsx
│
├── uploads
│   ├── sample.pdf
│   └── employee.csv
│
└── src

Keeping test files organized improves maintainability.


Verifying Download Success

You can verify whether the file exists after downloading.

Example:

Path filePath =
    Paths.get(
        "downloads/invoice.pdf"
    );

assertTrue(
    Files.exists(filePath)
);

This confirms that the download completed successfully.


Common File Upload Issues

File Not Found Exception

Cause:

  • Incorrect file path
  • Missing test resource

Solution:

Paths.get(
    "src/test/resources/sample.pdf"
);

Use relative paths whenever possible.


Download Does Not Start

Possible reasons:

  • Click event not triggered
  • Browser blocked the download
  • Incorrect locator

Always wrap the click action inside waitForDownload().


Best Practices

Store Test Files in Resources Folder

Recommended location:

src/test/resources

This ensures files are available across different environments.


Use Meaningful File Names

Good examples:

employee_data.csv
invoice_2026.pdf
profile_picture.png

Avoid:

test1.pdf
abc.csv
file.png

Clean Download Folder Regularly

Old files can cause false positives during validation.

Delete old downloads before executing tests.


Validate Business Outcomes

Instead of only checking that a file exists, verify:

  • File name
  • File type
  • File size
  • File contents

This provides stronger test coverage.


Interview Questions

How do you upload a file in Playwright?

Use:

page.setInputFiles();

How do you download files in Playwright?

Use:

page.waitForDownload();

Can Playwright upload multiple files?

Yes.

Pass multiple file paths inside a Path[] array.


Where are downloads stored by default?

Playwright stores downloads in a temporary folder unless you explicitly save them using saveAs().


Conclusion

File upload and download functionality is a critical part of enterprise automation projects.

Playwright simplifies these workflows with built-in APIs that are easy to use and highly reliable.

In this article, you learned:

  • How to upload a single file
  • How to upload multiple files
  • How to remove uploaded files
  • How to handle downloads
  • How to save downloaded files
  • Best practices for production frameworks

Mastering these techniques will help you automate document management systems, financial applications, HR portals, and many other enterprise applications with confidence.

In the next article, we will learn how to handle Frames and iFrames in Playwright using Java.

Wednesday, 1 July 2026

How to Handle Alerts, Confirmations, and Browser Popups in Playwright Using Java

Modern web applications frequently use JavaScript dialogs and browser popups to interact with users. These include alert messages, confirmation dialogs, prompt windows, and new browser tabs.

Handling these correctly is essential for building reliable automation frameworks.

In this article, we will learn how to handle alerts, confirmations, and browser popups in Playwright using Java.


Types of Dialogs in Web Applications

The most common dialog types are:

  • Alert Dialog
  • Confirmation Dialog
  • Prompt Dialog
  • Browser Popup Window

Let's explore each one with examples.


Handling JavaScript Alert Dialogs

Alert dialogs display information to users and usually contain only an OK button.

Example:

page.onDialog(dialog -> {
    System.out.println(dialog.message());
    dialog.accept();
});

page.locator("#showAlert").click();

Output:

Operation completed successfully.

The accept() method clicks the OK button automatically.


Handling Confirmation Dialogs

Confirmation dialogs usually provide two options:

  • OK
  • Cancel

Example:

page.onDialog(dialog -> {
    System.out.println(dialog.message());
    dialog.accept();
});

page.locator("#deleteButton").click();

This accepts the confirmation and proceeds with the action.


Dismissing Confirmation Dialogs

Sometimes your test needs to verify the Cancel flow.

Example:

page.onDialog(dialog -> {
    dialog.dismiss();
});

page.locator("#deleteButton").click();

The dismiss() method clicks the Cancel button.


Handling Prompt Dialogs

Prompt dialogs allow users to enter input values.

Example:

page.onDialog(dialog -> {
    dialog.accept("Gnanendra");
});

page.locator("#promptButton").click();

This enters the value "Gnanendra" and clicks OK.


Reading Dialog Messages

Validating dialog messages is a common testing requirement.

Example:

page.onDialog(dialog -> {

    String actualMessage = dialog.message();

    System.out.println(actualMessage);

    dialog.accept();
});

You can compare the message with the expected value using assertions.


Handling Browser Popups

Many applications open new windows for:

  • Payment gateways
  • Reports
  • Help pages
  • External authentication providers

Playwright provides built-in support for popup windows.

Example:

Page popupPage = page.waitForPopup(() -> {
    page.locator("#openReport").click();
});

System.out.println(popupPage.title());

This waits for the new browser window to appear and captures its reference.


Working with Multiple Browser Tabs

Once the popup is captured, you can interact with it like any other page.

Example:

popupPage.locator("#downloadButton").click();

popupPage.close();

This allows automation across multiple browser windows.


Handling Authentication Popups

Some applications display browser authentication dialogs.

Playwright supports HTTP authentication using browser context options.

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setHttpCredentials(
                "admin",
                "password123"
            )
    );

This automatically handles authentication challenges.


Common Mistake: Clicking Before Registering the Listener

Incorrect approach:

page.locator("#alertButton").click();

page.onDialog(dialog -> {
    dialog.accept();
});

The dialog appears before Playwright starts listening.

Correct approach:

page.onDialog(dialog -> {
    dialog.accept();
});

page.locator("#alertButton").click();

Always register the dialog listener first.


Best Practices

Register listeners before actions

Always attach the dialog handler before triggering the dialog.


Validate dialog messages

Verify business messages whenever possible.

Examples:

  • "Order placed successfully"
  • "Are you sure you want to delete?"
  • "Payment completed"

Use popup references carefully

Avoid using the parent page reference after switching to popup windows.


Close unnecessary windows

Closing popup windows prevents resource leaks during long test executions.


Complete Example

page.onDialog(dialog -> {

    System.out.println(
        "Dialog Message: " +
        dialog.message()
    );

    dialog.accept();
});

page.locator("#submitOrder").click();

Page popup =
    page.waitForPopup(() -> {
        page.locator("#viewReceipt").click();
    });

System.out.println(
    popup.title()
);

popup.close();

This example handles both dialogs and popup windows in the same test.


Interview Questions

What is the difference between accept() and dismiss()?

  • accept() clicks OK.
  • dismiss() clicks Cancel.

How do you enter text into a prompt dialog?

Use:

dialog.accept("text value");

How do you handle multiple browser windows in Playwright?

Use:

page.waitForPopup()

to capture the new window reference.


Conclusion

Handling alerts and popups is an essential skill for every automation engineer.

Playwright simplifies these operations through built-in APIs and event listeners.

In this article, you learned:

  • How to handle alerts
  • How to handle confirmations
  • How to handle prompt dialogs
  • How to work with browser popups
  • Best practices for dialog handling

Mastering these techniques will make your Playwright automation framework more robust and production-ready.

In the next article, we will learn how to upload and download files in Playwright using Java.

Tuesday, 30 June 2026

How to Capture Screenshots and Videos in Playwright Using Java

Debugging failed automation tests can be time-consuming, especially when tests run in CI/CD pipelines or on remote environments.

Playwright makes debugging easier by providing built-in support for:

  • Screenshots
  • Video recording
  • Execution traces

In this article, we'll learn how to capture screenshots and record videos in Playwright using Java.


Why Capture Screenshots and Videos?

Screenshots and videos help automation teams:

  • Investigate failures quickly
  • Share evidence with developers
  • Improve defect reports
  • Reduce debugging time
  • Analyze intermittent issues

Many organizations automatically attach screenshots and videos to test reports.


Taking a Basic Screenshot

Capturing a screenshot in Playwright is straightforward.

page.screenshot(
    new Page.ScreenshotOptions()
        .setPath(Paths.get("homepage.png"))
);

This captures the currently visible portion of the page.

Output:

homepage.png

Capturing a Full Page Screenshot

Sometimes the page extends beyond the visible browser window.

Playwright allows capturing the entire page.

page.screenshot(
    new Page.ScreenshotOptions()
        .setFullPage(true)
        .setPath(Paths.get("fullpage.png"))
);

This captures the complete page from top to bottom.


Capturing an Element Screenshot

You can capture screenshots of individual elements.

Example:

Locator loginButton = page.locator("#loginButton");

loginButton.screenshot(
    new Locator.ScreenshotOptions()
        .setPath(Paths.get("loginButton.png"))
);

This is useful for:

  • Logo verification
  • UI validation
  • Visual testing

Capturing Screenshots on Test Failure

A common framework practice is to capture screenshots only when tests fail.

Example:

try {
    assertThat(page).hasTitle("Dashboard");
}
catch (Exception e) {

    page.screenshot(
        new Page.ScreenshotOptions()
            .setPath(Paths.get("failure.png"))
    );

    throw e;
}

This helps teams analyze failures quickly.


Recording Videos in Playwright

Playwright can automatically record browser sessions.

To enable video recording, configure the browser context.

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setRecordVideoDir(
                Paths.get("videos/")
            )
    );

Playwright will save videos automatically after execution.


Creating Pages Using Video Enabled Context

Page page = context.newPage();

page.navigate(
    "https://www.google.com"
);

Once the test completes, the video file will be generated.

Example output:

videos/
 └── 3c84b7d2.webm

Saving Videos After Execution

Videos are saved after the browser context closes.

Example:

context.close();
browser.close();

If the context is not closed properly, videos may not be generated.


Recording Videos Only for Failed Tests

In large frameworks, recording every test can consume significant storage.

Many teams use one of these approaches:

  • Record videos only for failed tests.
  • Delete videos for successful tests.
  • Retain videos only in CI/CD environments.

Recommended Folder Structure

Example project structure:

project
├── screenshots
│   ├── login_failure.png
│   └── dashboard.png
│
├── videos
│   ├── test1.webm
│   └── test2.webm
│
└── src

Keeping artifacts organized simplifies debugging.


Complete Example

try (Playwright playwright = Playwright.create()) {

    Browser browser =
        playwright.chromium().launch(
            new BrowserType.LaunchOptions()
                .setHeadless(false)
        );

    BrowserContext context =
        browser.newContext(
            new Browser.NewContextOptions()
                .setRecordVideoDir(
                    Paths.get("videos/")
                )
        );

    Page page = context.newPage();

    page.navigate("https://www.google.com");

    page.screenshot(
        new Page.ScreenshotOptions()
            .setFullPage(true)
            .setPath(Paths.get("google.png"))
    );

    context.close();
    browser.close();
}

This example records a video and captures a full-page screenshot.


Best Practices

Use descriptive filenames

Good examples:

LoginFailure_20260630.png
CheckoutPage.png
PaymentError.png

Avoid generic names like:

image1.png
test.png

Capture screenshots only when necessary

Excessive screenshots can increase storage usage.

Capture:

  • Failures
  • Important business checkpoints
  • Critical workflows

Store artifacts in CI/CD pipelines

Screenshots and videos are especially useful in:

  • Jenkins
  • GitHub Actions
  • Azure DevOps
  • GitLab CI

Screenshot vs Video

FeatureScreenshotVideo
Storage UsageLowHigh
Debugging DetailMediumHigh
Execution ImpactMinimalSlight
Best Use CaseFailure EvidenceComplex Flow Analysis

Conclusion

Screenshots and videos are essential tools for modern automation frameworks.

Playwright makes capturing these artifacts extremely simple through built-in APIs.

In this article, you learned:

  • How to capture screenshots
  • How to capture full-page screenshots
  • How to capture element screenshots
  • How to enable video recording
  • Best practices for artifact management

These capabilities significantly improve debugging and make automation failures easier to analyze.

In the next article, we will explore how to handle alerts, confirmations, and browser popups in Playwright using Java.