Version picking

This tutorial demonstrates version picking in Widgetastic.core, a powerful feature for handling application evolution and multiple product versions. You’ll learn to create version-aware widgets/views that adapt to different application versions automatically.

Understanding Version Picking

Version picking allows widgets and views to adapt their behavior based on the application version being tested:

Why Version Picking is Important

  • Application Evolution: UI changes between software versions

  • Backward Compatibility: Support testing multiple versions simultaneously

  • Maintenance Efficiency: Single test suite for multiple product versions

  • Gradual Migration: Smooth transitions between widget implementations

Setting Up Version Picking Environment

"""Basic Version Picking

This example demonstrates version-dependent widget definitions.
"""

import inspect
import os
from pathlib import Path
from playwright.sync_api import sync_playwright
from widgetastic.browser import Browser
from widgetastic.utils import VersionPick, Version
from widgetastic.widget import View, Text, TextInput


# Browser setup (from previous example)
class BrowserV1(Browser):
    @property
    def product_version(self):
        return Version("1.0.0")


class BrowserV2(Browser):
    @property
    def product_version(self):
        return Version("2.1.0")


def get_pw_and_browser(version: str = "v1"):
    # Get headless mode from environment (set by conftest or CI)
    headless = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true"

    p = sync_playwright().start()
    browser_instance = p.chromium.launch(headless=headless)
    context = browser_instance.new_context()
    page = context.new_page()

    base_path = Path(inspect.getfile(Browser)).parent.parent.parent
    test_page_path = base_path / "testing" / "html" / "testing_page.html"
    test_page_url = test_page_path.as_uri()
    page.goto(test_page_url)

    if version == "v1":
        return p, BrowserV1(page)
    else:
        return p, BrowserV2(page)


Basic Version Picking

Start with simple version-dependent widget definitions:

Simple Version Pick Example

In this example, we want to select input and click button for different versions.

  • Default/fallback (v1.x): TextInput (name=fill_with_1) and Button (id=#fill_with_button_1)

  • Version 2.0.0+ (v2.x): TextInput (name=fill_with_2) and Button (id=#fill_with_button_2)

# Create versioned view
class VersionedView(View):
    input_field = VersionPick(
        {
            Version.lowest(): TextInput(name="fill_with_1"),  # Default/fallback (v1.x)
            "2.0.0": TextInput(name="fill_with_2"),  # Version 2.0.0+
        }
    )
    click_button = VersionPick(
        {
            Version.lowest(): Text("#fill_with_button_1"),  # Default/fallback (v1.x)
            "2.0.0": Text("#fill_with_button_2"),  # Version 2.0.0+
        }
    )


# Test with version 1.0.0 browser
pw, browser_v1 = get_pw_and_browser("v1")
view = VersionedView(browser_v1)
print(f"Browser version (v1): {browser_v1.product_version}")
print(f"Input locator (v1): {view.input_field.locator}")
print(f"Button locator (v1): {view.click_button.locator}")
pw.stop()

# Test with version 2.1.0 browser
pw, browser_v2 = get_pw_and_browser("v2")
view = VersionedView(browser_v2)
print(f"Browser version (v2): {browser_v2.product_version}")
print(f"Input locator (v2): {view.input_field.locator}")
print(f"Button locator (v2): {view.click_button.locator}")
pw.stop()