Window Management

This tutorial demonstrates window and popup management in Widgetastic.core using the framework’s test pages. You’ll learn to handle multiple browser windows, tabs, and popups using popup_test_page.html and external_test_page.html.

Note

Prerequisites: Basic widgets tutorial Test Pages Used: popup_test_page.html, external_test_page.html, testing_page.html

Learning Objectives

By completing this tutorial, you will:

  • ✅ Understand the WindowManager system

  • ✅ Handle popup windows and new tabs

  • ✅ Switch between multiple browser contexts

  • ✅ Manage browser lifecycle and cleanup

  • ✅ Handle cross-page automation workflows

Setting Up Window Management

"""Basic Windows Management Example
This example demonstrates creating and managing multiple browser windows.
"""

import inspect
import os
from pathlib import Path
from playwright.sync_api import sync_playwright
from widgetastic.browser import Browser, WindowManager


def setup_window_manager():
    """Setup WindowManager and base path."""
    # Get headless mode from environment (set by conftest or CI)
    headless = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true"

    base_path = Path(inspect.getfile(Browser)).parent.parent.parent
    p = sync_playwright().start()
    browser_instance = p.chromium.launch(headless=headless)
    context = browser_instance.new_context()
    page = context.new_page()

    return WindowManager(context, page), p, base_path


window_manager, pw, base_path = setup_window_manager()

Basic Window Operations

The WindowManager provides methods for creating and managing multiple browser windows:

Creating New Windows

# Example: Creating New Windows

# Get external test page URL
external_page_path = base_path / "testing" / "html" / "external_test_page.html"
external_url = external_page_path.as_uri()

# Current browser
initial_browser = window_manager.current
print(f"Initial browser URL: {initial_browser.url}")
print(f"Total browsers: {len(window_manager.all_browsers)}")

# Create new window/browser with focus (becomes current)
new_browser = window_manager.new_browser(external_url, focus=True)
print(f"\nNew browser URL: {new_browser.url}")
print(f"Current browser changed: {window_manager.current is new_browser}")
print(f"Total browsers: {len(window_manager.all_browsers)}")

# Create background window/browser (doesn't change focus)
bg_browser = window_manager.new_browser(external_url, focus=False)
print(f"\nCurrent browser unchanged: {window_manager.current is new_browser}")
print(f"Total browsers: {len(window_manager.all_browsers)}")


Switching Between Windows

# Example: Switching Between Windows
print(f"Initial browsers created: {len(window_manager.all_browsers)}")

# Switch to different browser by instance
window_manager.switch_to(bg_browser)
print(f"Switched to background browser: {window_manager.current is bg_browser}")

# Switch back to original browser
window_manager.switch_to(initial_browser)
print(f"Switched back to initial browser: {window_manager.current is initial_browser}")

# Switch by page instance
window_manager.switch_to(new_browser.page)
print(f"Switched using page reference: {window_manager.current.page is new_browser.page}")

# Close playwright instance
pw.stop()

Handling Popups and New Tabs

Manage popup windows and new tabs created by JavaScript. Widgetastic provides two approaches: reliable detection using expect_new_page() context manager, and automatic detection via all_browsers property.

Reliable Popup Detection with `expect_new_page()`

The recommended approach for handling popups and new tabs is using the expect_new_page() context manager. This method uses Playwright’s native expect_page() to reliably wait for and capture new pages opened by JavaScript or links.

"""Handling Popups and New Tabs

This example demonstrates handling JavaScript popups using expect_new_page().
"""

import inspect
import os
from pathlib import Path
from playwright.sync_api import sync_playwright
from widgetastic.browser import Browser, WindowManager
from widgetastic.widget import View, Text


def setup_window_manager():
    """Setup WindowManager with popup test page."""
    # Get headless mode from environment (set by conftest or CI)
    headless = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true"

    base_path = Path(inspect.getfile(Browser)).parent.parent.parent

    p = sync_playwright().start()
    browser_instance = p.chromium.launch(headless=headless)
    context = browser_instance.new_context()
    page = context.new_page()
    return WindowManager(context, page), p, base_path


window_manager, pw, base_path = setup_window_manager()


class PopupPageView(View):
    """View for popup_test_page.html"""

    open_popup_button = Text("#open-popup")
    open_tab_button = Text("#open-new-tab")
    external_link = Text("#external-link")


# Navigate to popup test page
popup_page_path = base_path / "testing" / "html" / "popup_test_page.html"
initial_browser = window_manager.current
initial_browser.url = popup_page_path.as_uri()
popup_view = PopupPageView(initial_browser)

print(f"Initial browser count: {len(window_manager.all_browsers)}")

# Handle JavaScript popup window
with window_manager.expect_new_page(timeout=5.0) as popup_browser:
    popup_view.open_popup_button.click()

print(f"Popup browser URL: {popup_browser.url}")
print(f"Popup browser title: {popup_browser.title}")
print(f"Total browsers: {len(window_manager.all_browsers)}")

# Handle new tab opened by JavaScript
with window_manager.expect_new_page(timeout=5.0) as new_tab_browser:
    popup_view.open_tab_button.click()

print(f"New tab URL: {new_tab_browser.url}")

# Handle link with target="_blank"
with window_manager.expect_new_page(timeout=5.0) as external_browser:
    popup_view.external_link.click()

print(f"External browser URL: {external_browser.url}")

# Clean up opened browsers
window_manager.close_browser(popup_browser)
window_manager.close_browser(new_tab_browser)
window_manager.close_browser(external_browser)

print(f"After cleanup: {len(window_manager.all_browsers)} browsers")

Working with `all_browsers` Property

The all_browsers property provides automatic cleanup and best-effort detection of new pages. It’s useful for listing all active browsers, but for reliable popup detection, use expect_new_page().

# Example: Working with all_browsers Property.

# Get all active browsers with automatic cleanup
all_browsers = window_manager.all_browsers
print(f"Currently managing {len(all_browsers)} windows")

# open one more page external test page
external_page_path = base_path / "testing" / "html" / "external_test_page.html"
test_browser = window_manager.new_browser(external_page_path.as_uri(), focus=False)
print(f"Before close: {len(window_manager.all_browsers)} browsers")

# Iterate through all browsers
for i, browser in enumerate(window_manager.all_browsers):
    print(f"Window {i}: {browser.title} - {browser.url}")

window_manager.close_browser(test_browser)
print(f"After close: {len(window_manager.all_browsers)} browsers")

# Close playwright instance
pw.stop()