Monday, August 3, 2026

Playwright Browser Contexts in Java (Complete Guide)

Introduction

One of the biggest advantages of Playwright over traditional browser automation tools is its Browser Context architecture.

Instead of opening a completely new browser process for every test, Playwright creates lightweight, isolated browser contexts within the same browser instance. Each context behaves like a brand-new browser profile with its own cookies, local storage, session storage, cache, and permissions.

This approach makes tests faster, more reliable, and ideal for parallel execution.

In this guide, you'll learn how Browser Contexts work, why they're important, and how to use them effectively in Playwright with Java.


What is a Browser Context?

A Browser Context is an isolated browser session.

Each context has its own:

  • Cookies
  • Local Storage
  • Session Storage
  • Permissions
  • Cache
  • Authentication State

Think of a Browser Context as an "Incognito Window" inside the browser.

Each context is completely independent of the others.


Browser vs Browser Context

Many beginners confuse these concepts.

BrowserBrowser Context
Browser processIsolated browser session
HeavyweightLightweight
Can contain multiple contextsContains one or more pages
Shared executableSeparate storage and cookies

Typically, you launch one browser and create multiple browser contexts.


Creating a Browser Context

Example:

Playwright playwright = Playwright.create();

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

BrowserContext context =
    browser.newContext();

Page page = context.newPage();

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

This creates a new isolated session.


Creating Multiple Browser Contexts

You can create multiple independent users inside the same browser.

BrowserContext adminContext =
    browser.newContext();

BrowserContext customerContext =
    browser.newContext();

Page adminPage =
    adminContext.newPage();

Page customerPage =
    customerContext.newPage();

The two users do not share any data.


Why Browser Contexts Matter

Without Browser Contexts:

  • Sessions interfere with each other.
  • Cookies are shared.
  • Authentication conflicts occur.
  • Parallel execution becomes unreliable.

Browser Contexts solve these problems by providing complete isolation.


Cookie Isolation

Suppose User A logs into an application.

Their cookies remain inside their Browser Context.

User B opens another Browser Context.

User B starts with a completely clean session.

No cookies are shared.

This behaviour makes parallel testing reliable.


Local Storage Isolation

Local Storage is also isolated.

Example:

Context A

theme = dark

Context B

theme = light

Each context maintains its own storage.


Session Storage Isolation

Session Storage exists only within its Browser Context.

Closing the context removes all session data.

This closely matches real browser behaviour.


Reusing Authentication

Instead of logging in repeatedly, save the authenticated state.

context.storageState(
    new BrowserContext.StorageStateOptions()
        .setPath(Paths.get("storageState.json"))
);

Later, create a new context using the saved authentication.

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setStorageStatePath(
                Paths.get("storageState.json")
            )
    );

This significantly reduces test execution time.


Multi-User Testing

Many enterprise applications involve interactions between multiple users.

Example:

  • Administrator approves a request.
  • Manager reviews the request.
  • Employee views the approved status.

Each user can run in a separate Browser Context.

BrowserContext admin =
    browser.newContext();

BrowserContext manager =
    browser.newContext();

BrowserContext employee =
    browser.newContext();

This allows realistic end-to-end workflow testing.


Parallel Execution

Browser Contexts are lightweight and well suited for parallel testing.

Benefits include:

  • Faster execution
  • Better resource utilization
  • Independent sessions
  • Reduced setup time

Closing Browser Contexts

Always close contexts after execution.

context.close();

Finally, close the browser.

browser.close();

Proper cleanup prevents resource leaks.


Browser Context Options

When creating a context, you can configure:

  • Viewport size
  • Locale
  • Time zone
  • Geolocation
  • Permissions
  • HTTP credentials
  • Color scheme
  • User agent

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setViewportSize(1366, 768)
            .setLocale("en-US")
            .setTimezoneId("Asia/Kolkata")
    );

This makes testing different environments simple.


Real-World Enterprise Example

Consider an e-commerce platform.

Scenario:

  1. Customer places an order.
  2. Warehouse user processes the order.
  3. Administrator verifies the shipment.

Each role runs in its own Browser Context.

All three users interact with the same application simultaneously without affecting one another.


Common Mistakes

Reusing the Same Context for Every Test

This can cause cookies and session data to leak between tests.

Create a fresh Browser Context whenever practical.


Forgetting to Close Contexts

Unused contexts consume memory.

Always close them after the test finishes.


Sharing Authentication Across Unrelated Tests

Keep authentication states separate unless sharing is intentional.

This improves test independence.


Best Practices

Create One Context Per Test

This ensures isolation and reduces flaky tests.


Save Authentication State

Reuse authenticated sessions for faster execution.


Keep Tests Independent

Avoid dependencies between contexts or test cases.


Use Contexts for Parallel Users

Model real-world workflows with separate contexts for different user roles.


Clean Up Resources

Always close pages, contexts, and browsers when execution completes.


Common Interview Questions

What is a Browser Context?

A Browser Context is an isolated browser session with its own cookies, storage, cache, and permissions.


Why are Browser Contexts important?

They allow isolated sessions, faster execution, reliable parallel testing, and multi-user automation.


Are Browser Contexts the same as browser windows?

No. Multiple Browser Contexts can exist within a single browser process, each behaving like an independent browser profile.


Can Browser Contexts share cookies?

No. Cookies are isolated unless explicitly imported or exported.


Why is Playwright faster than launching multiple browsers?

Creating Browser Contexts is significantly lighter than starting separate browser processes, reducing execution time and resource usage.


Conclusion

Browser Contexts are one of Playwright's most powerful features and the foundation of scalable automation frameworks.

They provide secure session isolation, simplify multi-user testing, improve parallel execution, and reduce overall test runtime.

In this guide, you learned how to:

  • Understand Browser Context architecture
  • Create isolated browser sessions
  • Manage cookies and storage
  • Reuse authentication state
  • Test multiple users simultaneously
  • Configure context options
  • Apply enterprise best practices

Mastering Browser Contexts will help you build faster, cleaner, and more reliable Playwright automation frameworks suitable for enterprise-scale applications.

Thursday, July 30, 2026

Playwright Mobile & Device Emulation Using Java (Complete Guide)

Introduction

Today, users access applications from desktops, laptops, tablets, and smartphones with different screen sizes and operating systems. A page that looks perfect on a desktop can become unusable on a mobile device if responsive design is not implemented correctly.

Testing every physical device is expensive and time-consuming. Playwright solves this challenge through powerful device emulation, allowing automation engineers to simulate mobile devices directly within the browser.

In this guide, you'll learn how to configure mobile testing, emulate devices, validate responsive layouts, and apply enterprise best practices using Playwright with Java.


What is Device Emulation?

Device emulation simulates the behaviour of a mobile or tablet device inside the browser.

Playwright can emulate:

  • Screen resolution
  • Viewport size
  • Touch interactions
  • Mobile user agent
  • Device scale factor
  • Orientation

This enables responsive UI testing without requiring physical devices.


Why Mobile Testing Matters

Mobile users now account for a significant portion of web traffic.

Common issues found during mobile testing include:

  • Overlapping text
  • Hidden buttons
  • Broken navigation menus
  • Horizontal scrolling
  • Incorrect font sizes
  • Touch targets that are too small

Automated mobile testing helps detect these problems early.


Creating a Mobile Browser Context

Create a browser context with a mobile-sized viewport.

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setViewportSize(390, 844)
            .setIsMobile(true)
            .setHasTouch(true)
    );

Page page = context.newPage();

This creates a browser session that behaves like a mobile device.


Setting a Custom Viewport

Different applications may require testing with specific screen sizes.

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setViewportSize(768, 1024)
    );

Common viewport sizes:

DeviceResolution
iPhone 14390 × 844
Pixel 7412 × 915
iPad768 × 1024
Desktop1920 × 1080

Emulating Touch Support

Touch gestures behave differently from mouse clicks.

Enable touch support:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setHasTouch(true)
            .setIsMobile(true)
    );

This allows Playwright to simulate touch-based interactions.


Emulating Screen Orientation

Applications should work in both portrait and landscape modes.

Portrait example:

.setViewportSize(390, 844)

Landscape example:

.setViewportSize(844, 390)

Testing both orientations helps identify layout issues.


Responsive Navigation Testing

Many applications replace the desktop navigation bar with a hamburger menu.

Example:

page.locator(".menu-icon").click();

page.getByRole(
        AriaRole.LINK,
        new Page.GetByRoleOptions()
            .setName("Products"))
    .click();

Always verify that mobile navigation remains usable.


Validating Responsive Layout

Use assertions to confirm that important elements remain visible.

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

This ensures essential functionality is available on smaller screens.


Capturing Mobile Screenshots

Screenshots are useful for responsive regression testing.

page.screenshot(
    new Page.ScreenshotOptions()
        .setPath(Paths.get("screenshots/mobile-homepage.png"))
);

Store screenshots as part of your regression suite.


Testing Different User Agents

Some websites display different content based on the browser's user agent.

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setUserAgent(
                "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)"
            )
    );

This helps validate device-specific behaviour.


Combining Device Emulation with Geolocation

Many mobile applications use location services.

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setGeolocation(12.9716, 77.5946)
            .setPermissions(List.of("geolocation"))
    );

This allows testing of location-aware features.


Testing Mobile Forms

Mobile keyboards and screen sizes can expose usability issues.

Verify:

  • Input fields remain visible.
  • Labels are readable.
  • Buttons are easy to tap.
  • Validation messages display correctly.

Organising Mobile Test Suites

Recommended project structure:

src

└── test

    ├── desktop

    ├── mobile

    └── tablet

This separation improves maintainability.


Best Practices

Test Multiple Viewports

Do not assume one mobile resolution is sufficient.

Include:

  • Small phones
  • Large phones
  • Tablets
  • Desktop

Avoid Pixel-Perfect Assertions

Minor rendering differences are normal.

Validate behaviour and layout rather than exact pixel positions.


Use Accessible Locators

Prefer:

  • getByRole()
  • getByLabel()
  • getByPlaceholder()
  • getByTestId()

These are more stable than long CSS selectors.


Combine with Visual Testing

Capture screenshots on different devices to detect responsive regressions.


Execute in CI/CD

Run mobile tests alongside desktop tests in Jenkins, GitHub Actions, or Azure DevOps to ensure consistent quality across devices.


Common Challenges

Hidden Elements

Some controls appear only on mobile.

Ensure your tests account for responsive UI changes.


Sticky Headers

Sticky navigation bars may hide content during scrolling.

Validate scrolling behaviour carefully.


Touch vs Mouse

Touch interactions can differ from desktop mouse behaviour.

Always enable touch when testing mobile-specific features.


Slow Mobile Networks

Consider combining device emulation with network throttling to evaluate application performance under slower connections.


Real-World Enterprise Example

An online banking application works correctly on desktop.

However, on mobile:

  • The Transfer Funds button is pushed below the visible area.
  • Customers cannot complete transfers without scrolling unexpectedly.

A Playwright mobile test detects the issue before release, preventing customer frustration and production defects.


Common Interview Questions

What is device emulation in Playwright?

Device emulation simulates a mobile or tablet environment by configuring viewport size, touch support, user agent, and other device characteristics.


Does Playwright require physical devices?

No. Most responsive testing can be performed using Playwright's browser-based emulation. Physical devices are still valuable for final validation.


Why enable hasTouch?

It allows Playwright to simulate touch interactions that behave differently from mouse events.


Can Playwright test responsive layouts?

Yes. By changing viewport sizes and validating element visibility, Playwright can verify responsive behaviour across different screen sizes.


Should mobile tests replace desktop tests?

No. Both desktop and mobile experiences should be validated because users access applications from multiple device types.


Conclusion

Responsive design is essential for modern web applications, and Playwright provides an efficient way to automate mobile and tablet testing without relying on physical hardware.

In this guide, you learned how to:

  • Configure mobile browser contexts
  • Set custom viewports
  • Enable touch support
  • Test portrait and landscape orientations
  • Validate responsive layouts
  • Capture mobile screenshots
  • Test with custom user agents
  • Combine mobile testing with geolocation
  • Apply enterprise best practices

By incorporating device emulation into your automation framework, you'll improve application quality across desktops, tablets, and smartphones while reducing the cost and complexity of cross-device testing.

Tuesday, July 28, 2026

Playwright Visual Testing Using Java (Screenshot Comparison & UI Regression Testing)

Introduction

Functional testing verifies whether an application behaves correctly, but it cannot detect visual issues such as broken layouts, overlapping text, incorrect colours, missing icons, or unexpected UI changes.

Visual Testing addresses this gap by comparing screenshots of the application against previously approved baseline images. If any unexpected visual differences are detected, the test fails, helping teams identify UI regressions before they reach production.

Playwright includes built-in support for screenshot capture and comparison, making visual regression testing simple and reliable.

In this guide, you'll learn how to implement visual testing using Playwright with Java.


What is Visual Testing?

Visual Testing is the process of comparing the current appearance of an application with a known baseline image.

Instead of validating only HTML elements, visual testing verifies:

  • Layout
  • Colours
  • Fonts
  • Images
  • Buttons
  • Icons
  • Spacing
  • Alignment
  • Responsive design

Why Visual Testing is Important

Visual bugs often escape traditional automation because the page is technically functional.

Examples include:

  • Button shifted outside the screen
  • Text overlapping an image
  • Missing company logo
  • Incorrect font size
  • Broken navigation menu
  • Hidden labels
  • Responsive layout issues

Visual testing helps detect these problems automatically.


When Should You Use Visual Testing?

Visual testing is particularly useful for:

  • Home pages
  • Dashboards
  • Checkout pages
  • Reports
  • Responsive layouts
  • Marketing pages
  • Admin portals

Avoid relying solely on visual tests for pages with highly dynamic content unless that content can be controlled.


Types of Screenshots in Playwright

Playwright supports several screenshot strategies.

Page Screenshot

Capture the visible portion of the page.

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

Full Page Screenshot

Capture the entire page, including content below the fold.

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

This is ideal for validating long pages.


Element Screenshot

Capture only a specific component.

page.locator("#loginForm")
    .screenshot(
        new Locator.ScreenshotOptions()
            .setPath(Paths.get("screenshots/loginForm.png"))
    );

This reduces maintenance because only the target component is compared.


Creating Baseline Images

The first successful execution establishes the approved UI.

Example:

baseline/

├── homepage.png

├── login.png

├── dashboard.png

Future executions compare the latest screenshots against these baseline images.


Comparing Screenshots

Typical visual testing workflow:

  1. Capture the current screenshot.
  2. Load the baseline image.
  3. Compare both images.
  4. Generate a difference image if changes exist.
  5. Fail the test when differences exceed the accepted threshold.

Handling Dynamic Content

Some page elements change every time.

Examples:

  • Current date
  • Current time
  • Advertisements
  • User avatars
  • Rotating banners
  • Notifications

These should not cause test failures.


Mask Dynamic Elements

Mask unstable regions before capturing screenshots.

Example:

page.locator(".notification")
    .screenshot(
        new Locator.ScreenshotOptions()
            .setMask(List.of(page.locator(".timestamp")))
            .setPath(Paths.get("screenshots/notification.png"))
    );

This helps eliminate false positives.


Responsive UI Testing

Validate multiple viewport sizes.

Example:

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setViewportSize(390, 844)
    );

Capture screenshots for:

  • Mobile
  • Tablet
  • Desktop

This ensures the application renders correctly across devices.


Organising Screenshot Files

Recommended project structure:

src

└── test

    ├── baseline

    ├── actual

    ├── diff

    └── reports

Keeping these directories separate makes reviewing results easier.


Running Visual Tests in CI/CD

Visual regression testing integrates well with:

  • Jenkins
  • GitHub Actions
  • Azure DevOps
  • GitLab CI

Typical workflow:

  1. Build application.
  2. Execute Playwright tests.
  3. Capture screenshots.
  4. Compare against baseline.
  5. Publish reports.
  6. Fail the build if unexpected visual changes are detected.

Best Practices

Use Stable Test Data

Ensure the application displays predictable data before taking screenshots.


Test Individual Components

Prefer component-level screenshots over full-page screenshots where possible.

Component comparisons are faster and easier to maintain.


Control Browser Environment

Keep the following consistent:

  • Browser version
  • Viewport size
  • Font availability
  • Operating system
  • Zoom level

Consistency reduces false failures.


Review Baseline Changes Carefully

Update baseline images only when UI changes are intentional and approved.

Treat baseline updates as part of your code review process.


Avoid Visual Tests for Highly Dynamic Pages

Pages with constantly changing content may require masking or alternative validation strategies.


Common Challenges

Different Fonts

Missing fonts can cause text rendering differences.

Install the same fonts across all environments.


Animation Effects

Animations can produce inconsistent screenshots.

Disable animations during testing whenever possible.


Dynamic Advertisements

Mask or disable advertisement sections to improve stability.


Browser Differences

Small rendering differences may exist between Chromium, Firefox and WebKit.

Maintain separate baselines if cross-browser visual validation is required.


Common Interview Questions

What is visual regression testing?

Visual regression testing compares the current appearance of an application with a baseline image to detect unintended UI changes.


Why can't functional tests detect visual bugs?

Functional tests verify behaviour, not appearance. They may pass even when the UI layout is broken.


What is a baseline image?

A baseline image is the approved screenshot used as the reference for future comparisons.


How do you handle dynamic elements in visual testing?

Mask dynamic regions, use stable test data, or exclude changing content from comparisons.


Should visual testing replace functional testing?

No. Visual testing complements functional automation by validating appearance, while functional tests verify business behaviour.


Real-World Enterprise Example

Imagine an online shopping application.

After a CSS update:

  • The Add to Cart button becomes partially hidden.
  • Functional automation still clicks the button successfully.
  • Customers on smaller screens cannot see the button.

A visual regression test immediately highlights the layout difference, allowing the issue to be fixed before release.


Conclusion

Visual testing is an essential addition to any modern automation framework.

Playwright's screenshot capabilities make it easy to detect unintended UI changes, improve application quality, and reduce production defects.

In this guide, you learned how to:

  • Capture page, full-page, and element screenshots
  • Create and maintain baseline images
  • Compare screenshots
  • Handle dynamic content
  • Test responsive layouts
  • Integrate visual testing into CI/CD
  • Apply enterprise best practices

By incorporating visual regression testing into your Playwright framework, you'll catch UI issues that traditional functional tests often miss, delivering a more polished and reliable user experience.

Monday, July 27, 2026

Playwright Shadow DOM Handling Using Java (Complete Guide)

Introduction

Modern web applications increasingly use Web Components to build reusable, encapsulated UI elements. Frameworks such as SAP Fiori Web Components, Salesforce Lightning, Ionic, Material UI (selected components), Adobe Spectrum, and many custom enterprise applications rely on Shadow DOM to isolate styles and behaviour.

For automation engineers, Shadow DOM introduces a new challenge. Elements that appear visible in the browser cannot always be located using traditional selectors because they exist inside a shadow tree.

Fortunately, Playwright has native Shadow DOM support, making automation much simpler than with many traditional automation tools.

In this guide, you'll learn how to locate, inspect, and automate Shadow DOM elements using Playwright with Java.


What is Shadow DOM?

Shadow DOM is a browser technology that allows developers to encapsulate HTML, CSS and JavaScript inside an isolated component.

This isolation prevents:

  • CSS conflicts
  • JavaScript conflicts
  • Accidental DOM manipulation
  • Style leakage

Think of a Web Component as a small application with its own private DOM.


Why Do Developers Use Shadow DOM?

Developers use Shadow DOM because it provides:

  • Component reusability
  • Encapsulated styling
  • Better maintainability
  • Improved modularity
  • Protection from external CSS

For example, a company may create a reusable custom button component that behaves identically across hundreds of pages.


Understanding Shadow DOM Structure

Example HTML:

<user-card>

    #shadow-root (open)

        <div class="profile">

            <button>View Profile</button>

        </div>

</user-card>

The View Profile button exists inside the shadow root rather than the main document.

Traditional automation tools often struggle to locate such elements.


Types of Shadow DOM

There are two types of Shadow DOM.

Open Shadow DOM

Open Shadow DOM exposes its shadow root to JavaScript.

Example:

element.shadowRoot

Playwright can automatically locate elements inside an open Shadow DOM.


Closed Shadow DOM

Closed Shadow DOM hides its internal structure.

Example:

element.shadowRoot

returns:

null

Closed Shadow DOM is intentionally inaccessible.

No browser automation framework, including Playwright, can directly inspect or interact with elements inside a truly closed Shadow DOM unless the application provides another mechanism.


Why Playwright Excels with Shadow DOM

Unlike Selenium, Playwright automatically traverses open Shadow DOM boundaries.

This means your locators work naturally without requiring custom JavaScript.

Benefits include:

  • Less code
  • Better readability
  • Improved reliability
  • Easier maintenance

Example Application

Suppose the page contains:

<login-component>

    #shadow-root (open)

        <input id="username">

        <input id="password">

        <button>Login</button>

</login-component>

The inputs exist inside the shadow root.


Locating Shadow DOM Elements

Playwright automatically searches inside open shadow roots.

Example:

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

page.locator("#password")
        .fill("Password123");

page.getByRole(
        AriaRole.BUTTON,
        new Page.GetByRoleOptions()
                .setName("Login"))
    .click();

No additional APIs are required.


Using CSS Selectors

You can also use standard CSS selectors.

page.locator("input[type='email']")
        .fill("user@example.com");

Playwright searches across open shadow boundaries automatically.


Using Accessible Locators

Role-based locators are highly recommended.

page.getByRole(
        AriaRole.BUTTON,
        new Page.GetByRoleOptions()
                .setName("Submit"))
    .click();

These locators are resilient to UI changes and improve test readability.


Handling Nested Shadow DOM

Some applications contain multiple nested shadow roots.

Example:

app-root

└── #shadow-root

    └── login-panel

        └── #shadow-root

            └── login-form

                └── #shadow-root

                    └── Login Button

Even with multiple levels, Playwright automatically pierces open shadow roots when resolving locators.


Waiting for Shadow Elements

Playwright's auto-waiting works inside Shadow DOM.

Example:

page.getByText("Dashboard")
        .waitFor();

The test waits until the element is visible and ready for interaction.


Assertions Inside Shadow DOM

Assertions work exactly the same.

assertThat(
    page.getByText("Welcome")
).isVisible();

No special handling is required.


Debugging Shadow DOM

Use browser developer tools:

  1. Open DevTools.
  2. Inspect the component.
  3. Expand the #shadow-root node.
  4. Identify unique attributes or accessible roles.
  5. Build your Playwright locator.

This approach helps create stable selectors.


Common Challenges

Duplicate Elements

The same locator may exist inside multiple components.

Use a parent locator to narrow the search.

page.locator("user-card")
    .getByRole(
        AriaRole.BUTTON,
        new Locator.GetByRoleOptions()
            .setName("Edit"))
    .click();

Dynamic Components

Shadow DOM components may render asynchronously.

Use Playwright's auto-waiting or explicit waits instead of Thread.sleep().


Closed Shadow DOM

Closed Shadow DOM cannot be traversed directly.

Possible approaches include:

  • Test through public UI interactions.
  • Request test-friendly hooks from developers.
  • Use accessible APIs exposed by the component.

Best Practices

Prefer Accessible Locators

Use:

  • getByRole()
  • getByLabel()
  • getByPlaceholder()
  • getByTestId()

These are generally more stable than complex CSS selectors.


Avoid Deep CSS Chains

Instead of:

app-root > div > custom-card > div > button

Prefer meaningful locators based on roles or test IDs.


Use Test IDs for Custom Components

If your development team supports testing, ask them to add:

<button data-testid="saveButton">

Then locate it using:

page.getByTestId("saveButton")
        .click();

Keep Components Independent

Write tests that interact with components through their public interface rather than relying on internal implementation details.


Test Real User Behaviour

Focus on user outcomes rather than component internals.

Examples:

  • Login succeeds.
  • Product is added to cart.
  • Settings are saved.

Selenium vs. Playwright

FeatureSeleniumPlaywright
Open Shadow DOM SupportRequires JavaScript execution in many casesNative support
Closed Shadow DOMNot supportedNot supported
Auto WaitingLimitedBuilt-in
Role-Based LocatorsLimitedExcellent
Nested Shadow DOMMore complexHandled automatically for open roots

Real-World Enterprise Use Cases

Shadow DOM is commonly found in:

  • SAP Fiori Web Components
  • Salesforce Lightning Web Components
  • Adobe Experience Manager Components
  • Ionic applications
  • Design systems built with Web Components
  • Internal enterprise UI libraries

Understanding Shadow DOM is valuable when working on modern enterprise applications.


Common Interview Questions

What is Shadow DOM?

Shadow DOM is a browser feature that encapsulates a component's HTML, CSS and JavaScript, preventing external interference.


Does Playwright support Shadow DOM?

Yes. Playwright automatically traverses open Shadow DOM boundaries when locating elements.


Can Playwright automate Closed Shadow DOM?

No. Closed Shadow DOM is intentionally inaccessible to browser automation frameworks.


Why are accessible locators recommended?

They improve readability, are more resilient to UI changes, and reflect how users interact with the application.


Why is Playwright considered easier than Selenium for Shadow DOM?

Playwright natively handles open Shadow DOM, reducing the need for custom JavaScript and simplifying locator strategies.


Conclusion

Shadow DOM is becoming increasingly common in modern web applications, and automation engineers need to understand how it affects element location and interaction.

Playwright greatly simplifies Shadow DOM automation through native support for open shadow roots, automatic waiting, and powerful locator strategies.

In this guide, you learned how to:

  • Understand Shadow DOM architecture
  • Differentiate between open and closed Shadow DOM
  • Locate elements inside open shadow roots
  • Work with nested Shadow DOM
  • Use stable locator strategies
  • Apply enterprise best practices
  • Prepare for common interview questions

Mastering Shadow DOM handling will help you automate modern component-based applications with greater confidence and significantly reduce maintenance effort in large-scale Playwright automation frameworks.

Friday, July 24, 2026

Playwright File Upload, Download & Drag-and-Drop Automation Using Java (Complete Guide)

Introduction

Modern web applications frequently require users to upload documents, download reports, or drag and drop files between different sections of the application.

Examples include:

  • Uploading profile pictures
  • Importing Excel spreadsheets
  • Downloading invoices or reports
  • Uploading resumes in job portals
  • Attaching files in support tickets
  • Dragging files into cloud storage applications

Automating these scenarios reliably is an essential skill for every automation engineer.

In this tutorial, you'll learn how to automate file uploads, file downloads, and drag-and-drop functionality using Playwright with Java.


Why File Handling Automation is Important

Many business-critical workflows depend on files.

Examples include:

  • Banking statement uploads
  • Insurance document verification
  • HR resume uploads
  • Medical report downloads
  • Invoice generation
  • Tax document processing

Automating these scenarios improves regression coverage and reduces manual effort.


Project Setup

Ensure your project includes the Playwright dependency.

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

Understanding File Upload in Playwright

Unlike Selenium, Playwright does not interact with the operating system's native file chooser.

Instead, it directly uploads files using the input element.

This makes uploads faster and more reliable.


Upload a Single File

Example:

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

page.setInputFiles(
    "input[type='file']",
    Paths.get("files/resume.pdf")
);

The selected file is uploaded immediately after it is assigned to the input element.


Upload Multiple Files

Some applications allow users to upload several files simultaneously.

page.setInputFiles(
    "input[type='file']",
    new Path[] {
        Paths.get("files/report.pdf"),
        Paths.get("files/image.png"),
        Paths.get("files/data.xlsx")
    }
);

Playwright uploads all selected files in one operation.


Remove Uploaded Files

To clear a previously selected file:

page.setInputFiles(
    "input[type='file']",
    new Path[] {}
);

This resets the file input field.


Handling Hidden File Inputs

Some applications hide the HTML file input and trigger it using a button.

Playwright can still upload files because it interacts directly with the input element.

Locate the hidden input and call:

page.setInputFiles(
    "#hiddenFileInput",
    Paths.get("files/document.pdf")
);

No JavaScript execution is required.


Working with File Chooser

Some websites open the file chooser after clicking a button.

Example:

FileChooser chooser =
    page.waitForFileChooser(() -> {

        page.click("#uploadButton");

    });

chooser.setFiles(
    Paths.get("files/profile.png")
);

Playwright waits for the chooser and then selects the file programmatically.


Downloading Files

Playwright provides built-in support for file downloads.

Example:

Download download =
    page.waitForDownload(() -> {

        page.click("#downloadReport");

    });

The Download object provides information about the downloaded file.


Save Downloaded File

Store the downloaded file in a specific directory.

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

This makes it easy to validate downloaded reports or archive test artifacts.


Verify Download

After saving the file, verify its existence.

Path path =
    Paths.get("downloads/report.pdf");

assert Files.exists(path);

You can also verify:

  • File name
  • File size
  • File extension
  • File content
  • Creation date

Drag and Drop

Many modern applications use drag-and-drop interactions.

Examples include:

  • Trello boards
  • Kanban applications
  • Cloud storage systems
  • Dashboard widgets

Playwright simplifies these actions.

page.dragAndDrop(
    "#source",
    "#target"
);

This performs the complete drag-and-drop interaction.


Drag Files into Upload Areas

Many websites support dragging files into a drop zone.

Typical flow:

  1. User selects a file.
  2. User drags it over the drop zone.
  3. Application uploads the file automatically.

In Playwright, this is usually implemented by uploading through the underlying file input element associated with the drop zone.


Validate Upload Success

Always verify that the upload completed successfully.

Example:

assertThat(
    page.locator(".success-message")
).containsText("Upload completed");

Validation is more reliable than assuming the upload succeeded.


Organizing Test Files

Store reusable files in a dedicated directory.

Example:

src

└── test

    └── resources

        └── testdata

            ├── sample.pdf

            ├── image.png

            ├── resume.docx

            └── report.xlsx

This structure keeps your project clean and portable.


Common Upload Challenges

File Size Restrictions

Applications may reject files larger than the allowed limit.

Test:

  • Small files
  • Large files
  • Boundary values

Unsupported File Types

Validate that unsupported formats produce appropriate validation messages.

Example:

  • Upload .exe
  • Upload .zip
  • Upload .bat

Verify that the application blocks invalid uploads.


Duplicate Uploads

Ensure the application correctly handles repeated uploads of the same file.


Interrupted Uploads

Test behavior during:

  • Network interruptions
  • Session expiration
  • Browser refresh
  • Upload cancellation

Best Practices

Store Test Files in Version Control

Keep sample files inside the project so that all team members use the same test data.


Use Relative Paths

Avoid absolute paths such as:

C:\Users\John\Desktop\file.pdf

Instead, use project-relative paths to improve portability.


Verify Download Content

Checking only the file name is insufficient.

Validate:

  • Content
  • Size
  • Format
  • Generated values

Keep Test Files Small

Large files increase execution time and repository size.

Use compact sample files unless testing file size limits.


Clean Up Download Directories

Delete temporary files after execution to prevent unnecessary storage growth.


Common Interview Questions

How does Playwright upload files?

Playwright uploads files by assigning them directly to the HTML file input element using setInputFiles(), without interacting with the native operating system file picker.


Can Playwright upload multiple files?

Yes. Pass an array of Path objects to setInputFiles().


How do you verify a downloaded file?

Save the file using download.saveAs() and validate its existence, size, name, or contents.


Does Playwright support drag-and-drop?

Yes. The dragAndDrop() method performs drag-and-drop interactions between source and target elements.


Why use relative file paths?

Relative paths make the framework portable across different operating systems, developers' machines, and CI/CD environments.


Conclusion

File handling is a critical aspect of end-to-end web automation.

Playwright provides simple and reliable APIs for uploading files, downloading reports, handling file chooser dialogs, and automating drag-and-drop interactions.

In this guide, you learned how to:

  • Upload single and multiple files
  • Handle hidden file inputs
  • Work with the file chooser
  • Download and verify files
  • Perform drag-and-drop actions
  • Organize test resources
  • Apply enterprise best practices

By mastering these techniques, you'll be able to automate many real-world business workflows involving documents, reports, and media files with confidence.

Wednesday, July 22, 2026

Playwright Authentication Handling (Basic Auth, OAuth, JWT & Session Management) Using Java

Introduction

Authentication is one of the first challenges automation engineers face when testing modern web applications. Whether you're working with an internal enterprise application, an e-commerce platform, or a cloud-based SaaS product, your tests often need to log in before performing business operations.

Repeatedly logging in before every test slows execution and increases maintenance. Playwright provides several mechanisms to handle authentication efficiently, including Basic Authentication, OAuth flows, JWT tokens, cookies, and session reuse.

In this guide, you'll learn the most common authentication techniques used in Playwright with Java and when to use each approach.


Why Authentication Matters in Automation

Authentication enables secure access to protected resources and user-specific functionality.

Common authentication methods include:

  • Username and password
  • HTTP Basic Authentication
  • OAuth 2.0
  • JWT (JSON Web Tokens)
  • Session cookies
  • Single Sign-On (SSO)

A good automation framework should support all of these without duplicating login logic across tests.


HTTP Basic Authentication

Basic Authentication sends a username and password with every request.

Playwright supports it during browser context creation.

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

Page page = context.newPage();

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

This is commonly used for internal tools or protected staging environments.


Form-Based Login

Most applications use login forms.

Example:

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

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

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

page.click("#loginButton");

page.waitForURL("**/dashboard");

Playwright automatically waits for navigation and element readiness.


Reusing Logged-In Sessions

Logging in before every test increases execution time.

Instead, log in once and reuse the authenticated session.

After a successful login:

context.storageState(
    new BrowserContext.StorageStateOptions()
        .setPath(Paths.get("storageState.json"))
);

This saves cookies and local storage to a file.


Loading a Saved Session

Reuse the saved session in future tests.

BrowserContext context =
    browser.newContext(
        new Browser.NewContextOptions()
            .setStorageStatePath(
                Paths.get("storageState.json")
            )
    );

Page page = context.newPage();

This allows tests to start in an authenticated state without repeating the login process.


Working with Cookies

Applications often use cookies to maintain user sessions.

Retrieve cookies:

List<BrowserContext.Cookie> cookies =
        context.cookies();

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

You can also inspect individual cookie properties for debugging or validation.


Adding Cookies Manually

Sometimes it's useful to inject cookies directly.

BrowserContext.Cookie cookie =
        new BrowserContext.Cookie();

cookie.setName("sessionId");
cookie.setValue("ABC123");
cookie.setDomain("example.com");
cookie.setPath("/");

context.addCookies(
        List.of(cookie)
);

This is useful when preparing pre-authenticated sessions.


JWT Token Authentication

Many REST APIs and Single Page Applications (SPAs) use JSON Web Tokens.

You can send a JWT token in request headers.

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

This approach is common for API testing and backend integration.


OAuth Authentication

OAuth is widely used for social login providers such as:

  • Google
  • Microsoft
  • GitHub
  • LinkedIn

The typical flow is:

  1. User clicks Sign in.
  2. Browser redirects to the identity provider.
  3. User authenticates.
  4. Identity provider redirects back with an authorization code or token.

Automating OAuth directly can be complex because it often involves multi-factor authentication or third-party security policies.

In enterprise environments, a common practice is to authenticate once and reuse the saved session instead of repeating the entire OAuth flow.


API Login for Faster Tests

Instead of logging in through the UI, authenticate using an API and then open the browser with the authenticated session.

Typical flow:

  1. Send login API request.
  2. Receive session token or cookie.
  3. Save authentication data.
  4. Launch browser using the authenticated state.

This reduces execution time and avoids repetitive UI interactions.


Handling Session Expiration

Sessions may expire during long-running test suites.

To avoid failures:

  • Refresh the session when necessary.
  • Regenerate authentication tokens.
  • Recreate the storage state periodically.
  • Monitor token expiration times.

Multi-User Testing

Enterprise applications often require testing with multiple roles.

Example roles:

  • Administrator
  • Manager
  • Employee
  • Customer

Create a separate storage state file for each role.

storage/

├── admin.json

├── manager.json

├── employee.json

This keeps user sessions isolated and easy to manage.


Secure Credential Management

Never hardcode usernames or passwords in source code.

Instead, use:

  • Environment variables
  • Configuration files
  • Secret management tools
  • CI/CD pipeline secrets

This improves security and simplifies maintenance.


Best Practices

Reuse Sessions

Save authenticated sessions and reuse them whenever possible.

This significantly reduces test execution time.


Prefer API Login

When available, use backend authentication APIs instead of UI login for setup.


Isolate User Sessions

Each test should use its own browser context and session data.

Avoid sharing authenticated contexts across parallel tests.


Rotate Test Accounts

Use dedicated automation accounts and reset their state regularly to prevent unexpected failures.


Monitor Authentication Failures

Log authentication errors clearly so that expired credentials or configuration issues are easy to identify.


Common Interview Questions

What is storageState in Playwright?

storageState saves cookies and local storage so that authenticated sessions can be reused in later tests.


Why reuse authenticated sessions?

It speeds up execution, reduces repeated login operations, and improves test stability.


Can Playwright automate OAuth?

Yes, but many OAuth providers use additional security mechanisms such as MFA. In practice, teams often authenticate once and reuse the saved session.


How do you authenticate API requests using JWT?

Include the JWT token in the Authorization header using the Bearer scheme.


Why shouldn't credentials be hardcoded?

Hardcoded credentials create security risks and make maintenance more difficult. Externalized configuration is the recommended approach.


Conclusion

Authentication is a foundational aspect of web automation.

Playwright provides flexible options for handling Basic Authentication, form-based login, OAuth, JWT tokens, cookies, and reusable sessions, enabling automation engineers to build secure, fast, and maintainable test frameworks.

In this guide, you learned how to:

  • Implement HTTP Basic Authentication
  • Automate form-based login
  • Save and reuse authenticated sessions
  • Work with cookies
  • Authenticate API requests using JWT
  • Understand OAuth automation strategies
  • Apply enterprise authentication best practices

By mastering these techniques, you'll build automation suites that execute faster, scale more effectively, and align with the authentication patterns used in modern enterprise applications.

Monday, July 20, 2026

Playwright Network Interception and API Mocking with Java (Complete Guide)

Introduction

Modern web applications communicate extensively with backend services through REST APIs. Every time you log in, search for products, submit forms, or load dashboards, your browser sends multiple HTTP requests behind the scenes.

Traditionally, UI automation relied on live backend services, making tests slow and vulnerable to network issues. Playwright changes this by allowing you to intercept network traffic, modify requests, mock responses, and even simulate server failures—all from your test code.

In this guide, you'll learn how to use Playwright's network interception and API mocking capabilities with Java to build faster, more reliable automation tests.


What is Network Interception?

Network interception allows you to inspect or control HTTP requests made by the browser during test execution.

You can:

  • Observe outgoing requests
  • Modify request headers
  • Change request payloads
  • Mock API responses
  • Abort requests
  • Simulate backend failures
  • Improve test reliability

Why Use API Mocking?

API mocking allows frontend testing even when backend services are:

  • Still under development
  • Temporarily unavailable
  • Returning inconsistent data
  • Difficult to reproduce specific scenarios
  • Rate limited

Instead of calling the real server, Playwright returns a predefined response.

Benefits include:

  • Faster execution
  • Stable tests
  • Repeatable scenarios
  • Easier edge-case testing

Understanding Playwright Routes

Playwright uses the route() method to intercept requests.

Basic syntax:

page.route("**/*", route -> {

    route.continue_();

});

This intercepts every request and allows it to continue normally.


Intercept a Specific API Request

Suppose the application calls:

GET /api/users

Intercept only that endpoint:

page.route("**/api/users", route -> {

    route.continue_();

});

Other requests continue without interception.


Block Images to Speed Up Tests

Large images increase page load time.

Block them during automation:

page.route("**/*.{png,jpg,jpeg,gif}", route -> {

    route.abort();

});

Benefits:

  • Faster execution
  • Lower bandwidth usage
  • Reduced memory consumption

Mock an API Response

Instead of calling the real server:

page.route("**/api/users", route -> {

    route.fulfill(

        new Route.FulfillOptions()

            .setStatus(200)

            .setContentType("application/json")

            .setBody("""
                [
                  {
                    "id":1,
                    "name":"John Doe"
                  }
                ]
            """)
    );

});

The application receives the mocked response immediately.


Mock an Error Response

Testing error handling is easy.

Example:

page.route("**/api/users", route -> {

    route.fulfill(

        new Route.FulfillOptions()

            .setStatus(500)

            .setBody("Internal Server Error")

    );

});

Now you can verify whether the application displays the correct error message.


Simulate Network Failure

To simulate a server outage:

page.route("**/api/users", route -> {

    route.abort();

});

This allows you to validate retry logic and offline behavior.


Modify Request Headers

You can add or replace HTTP headers.

page.route("**/api/users", route -> {

    Map<String, String> headers =
        new HashMap<>(route.request().headers());

    headers.put("X-Test-User", "Automation");

    route.resume(

        new Route.ResumeOptions()
            .setHeaders(headers)

    );

});

Useful for testing feature flags or custom authentication.


Modify POST Request Data

Intercept a request before it reaches the server.

page.route("**/api/orders", route -> {

    System.out.println(
        route.request().postData()
    );

    route.continue_();

});

This helps verify request payloads during automation.


Log Network Requests

Monitor all requests:

page.onRequest(request ->

    System.out.println(
        request.method() + " " + request.url()

    )
);

Useful for debugging complex applications.


Log Network Responses

Capture server responses:

page.onResponse(response ->

    System.out.println(

        response.status() +

        " " +

        response.url()

    )
);

This helps identify failed API calls.


Wait for a Specific Response

Instead of using delays:

page.waitForResponse(

    "**/api/users"

);

This ensures the test proceeds only after the required response is received.


Verify API Response Status

Example:

page.onResponse(response -> {

    if (response.url().contains("/users")) {

        System.out.println(

            response.status()

        );

    }

});

You can also validate response headers or body content.


Practical Scenario

Imagine an e-commerce application.

Flow:

  1. User searches for a product.
  2. Frontend calls:
/api/search
  1. Instead of calling the real backend, Playwright returns:
[
  {
    "product":"Laptop",
    "price":899
  }
]

The UI behaves exactly as if the backend had returned the data.

This approach enables testing even when backend systems are unavailable.


Best Practices

Mock Only What Is Necessary

Avoid mocking every request.

Use real backend services when integration testing is required.

Mock only external or unstable dependencies.


Keep Mock Data Realistic

Use responses that resemble production data.

Include:

  • IDs
  • Dates
  • Nested objects
  • Validation messages

This improves test quality.


Separate Mock Files

Store large mock responses in JSON files instead of embedding them in Java code.

Example:

src

└── test

    └── resources

        └── mocks

            ├── users.json

            ├── products.json

            └── orders.json

Log Requests During Debugging

Request and response logging simplifies troubleshooting.

Disable verbose logging in production pipelines unless needed.


Combine with API Tests

Use Playwright's built-in API testing features alongside network interception to create comprehensive end-to-end automation.


Common Interview Questions

What is network interception in Playwright?

Network interception allows tests to inspect, modify, block, or mock HTTP requests and responses during browser automation.


What is API mocking?

API mocking replaces real backend responses with predefined data, enabling reliable frontend testing without depending on live services.


Can Playwright block network requests?

Yes. The route.abort() method can block requests such as images, analytics scripts, or API calls.


Why use mocked APIs?

Mocked APIs make tests faster, more stable, and easier to execute when backend services are unavailable or difficult to control.


How do you wait for a specific network response?

Use page.waitForResponse() to synchronize test execution with a specific HTTP response.


Conclusion

Network interception and API mocking are among Playwright's most powerful capabilities.

They enable you to build faster, more reliable, and more maintainable automation suites by reducing dependency on external services and allowing precise control over browser communication.

In this guide, you learned how to:

  • Intercept network requests
  • Mock API responses
  • Modify headers and request payloads
  • Block unwanted resources
  • Simulate server failures
  • Wait for network responses
  • Apply enterprise best practices

Mastering these techniques will help you create robust automation frameworks capable of testing complex applications under a wide variety of real-world conditions.