First Steps

Ready to write your first widgetastic automation script? This guide walks you through creating a complete, working example that demonstrates the core concepts in action.

Your First Script

Let’s create a script that automates a simple web form. We’ll use a public testing website to ensure the example works reliably.

Complete Example

 1"""Complete First Script Example
 2
 3This is a complete, working example that demonstrates core widgetastic concepts.
 4"""
 5
 6# first_script.py
 7import json
 8import os
 9from pathlib import Path
10
11from playwright.sync_api import sync_playwright
12from widgetastic.browser import Browser
13from widgetastic.widget import View, Text, TextInput, Checkbox
14
15
16# Define your widgets and views i.e. Modeling of the testing page.
17class DemoFormView(View):
18    # Define the form elements as widgets
19    custname = TextInput(locator='.//input[@name="custname"]')
20    telephone = TextInput(locator='.//input[@name="custtel"]')
21    email = TextInput(locator='.//input[@name="custemail"]')
22
23    @View.nested
24    class pizza_size(View):  # noqa
25        small = Checkbox(locator=".//input[@value='small']")
26        medium = Checkbox(locator=".//input[@value='medium']")
27        large = Checkbox(locator=".//input[@value='large']")
28
29    @View.nested
30    class pizza_toppings(View):  # noqa
31        bacon = Checkbox(locator=".//input[@value='bacon']")
32        extra_cheese = Checkbox(locator=".//input[@value='cheese']")
33        onion = Checkbox(locator=".//input[@value='onion']")
34        mushroom = Checkbox(locator=".//input[@value='mushroom']")
35
36    delivery_instructions = TextInput(locator='.//textarea[@name="comments"]')
37    submit_order = Text(".//button[text()='Submit order']")
38
39    response = Text(
40        ".//body"
41    )  # After submitting the form, we will get the response in the body of the page.
42
43
44# Step: Main automation logic where actualy we are interacting with the page.
45def main():
46    # Get headless mode from environment (set by conftest or CI)
47    headless = os.getenv("PLAYWRIGHT_HEADLESS", "false").lower() == "true"
48
49    # Use a local HTML form to avoid any external network dependency.
50    form_path = Path(__file__).parent / "pizza_form.html"
51    form_url = form_path.resolve().as_uri()
52
53    with sync_playwright() as playwright:
54        # Launch browser using Playwright
55        browser = playwright.chromium.launch(headless=headless)
56        # Tip: Use slow_mo for debugging: browser = playwright.chromium.launch(headless=False, slow_mo=500)
57        page = browser.new_page()
58
59        # Create widgetastic browser instance
60        wt_browser = Browser(page)
61
62        # Navigate to the local pizza order form.
63        wt_browser.url = form_url
64
65        # Initialize the view i.e. Model of the testing page.
66        form_view = DemoFormView(wt_browser)
67
68        # Fill individual fields
69        form_view.custname.fill("John Doe")
70        form_view.telephone.fill("1234567890")
71        form_view.email.fill("john.doe@example.com")
72        form_view.pizza_size.small.fill(True)
73        form_view.pizza_toppings.bacon.fill(True)
74        form_view.delivery_instructions.fill("Hello from Widgetastic!")
75
76        form_view.submit_order.click()
77
78        response_data = json.loads(form_view.response.text)
79        print("Response data:")
80        print(json.dumps(response_data, indent=4))
81        # Close the browser
82        browser.close()
83
84
85if __name__ == "__main__":
86    main()

Note

Core widgetastic provides minimal widgets (Text, TextInput, Checkbox, etc.). For specialized widgets like Buttons, Modals, Charts, use extensions like widgetastic-patternfly5.

Running the Script

Save the code as first_script.py and run it:

python first_script.py

You should see the browser open, the form get filled out automatically, and output showing the progress.

Breaking Down the Example

Let’s examine each part of the script in detail:

1. Import Statements

import json
from playwright.sync_api import sync_playwright
from widgetastic.browser import Browser
from widgetastic.widget import View, Text, TextInput, Checkbox
  • json - For parsing the response data after form submission

  • sync_playwright - Playwright’s synchronous API for browser automation

  • Browser - Widgetastic’s enhanced browser wrapper

  • Widget classes - Individual UI component types (Text, TextInput, Checkbox)

2. View Definition with Nested Views

class DemoFormView(View):
    # Basic form fields
    custname = TextInput(locator='.//input[@name="custname"]')
    telephone = TextInput(locator='.//input[@name="custtel"]')
    email = TextInput(locator='.//input[@name="custemail"]')

    # Nested view for pizza size options
    @View.nested
    class pizza_size(View):
        small = Checkbox(locator=".//input[@value='small']")
        medium = Checkbox(locator=".//input[@value='medium']")
        large = Checkbox(locator=".//input[@value='large']")

    # Nested view for pizza toppings
    @View.nested
    class pizza_toppings(View):
        bacon = Checkbox(locator=".//input[@value='bacon']")
        extra_cheese = Checkbox(locator=".//input[@value='cheese']")
        # ... more toppings

This creates a hierarchical view structure: * Basic fields use XPath locators to find form inputs. * Nested views group related elements (pizza size, toppings) using @View.nested * Checkbox widgets handle radio buttons and checkboxes for selections

3. Browser Setup and Navigation

with sync_playwright() as playwright:
    browser = playwright.chromium.launch(headless=False)
    page = browser.new_page()
    wt_browser = Browser(page)
    wt_browser.url = "https://httpbin.org/forms/post"

This creates the browser hierarchy and navigates to the test form: * Playwright browser → Playwright page → Widgetastic browser * Uses httpbin.org for reliable testing (no custom setup required)

4. Form Interaction and Data Handling

# Initialize the view
form_view = DemoFormView(wt_browser)

# Fill individual fields
form_view.custname.fill("John Doe")
form_view.telephone.fill("1234567890")
form_view.email.fill("john.doe@example.com")

# Select pizza options using nested views
form_view.pizza_size.small.fill(True)
form_view.pizza_toppings.bacon.fill(True)

form_view.delivery_instructions.fill("Hello from Widgetastic!")

# Submit and handle response
form_view.submit_order.click()
response_data = json.loads(form_view.response.text)

We can fill the form in a single shot. Widgetastic will fill the form in the order of the widgets.

 1"""Batch Fill Example
 2
 3This example demonstrates filling a form in a single operation.
 4This is a code snippet that assumes form_view is already created.
 5See first_script.py for the complete example.
 6"""
 7
 8# We can fill the form at single shot. Widgetastic will fill the form in the order of the widgets.
 9# This example assumes form_view is already created (see first_script.py for full context)
10data = {
11    "custname": "John Doe",
12    "telephone": "1234567890",
13    "email": "john.doe@example.com",
14    "pizza_size": {"small": True},
15    "pizza_toppings": {"bacon": True},
16    "delivery_instructions": "Hello from Widgetastic!",
17}
18# form_view.fill(data)  # Uncomment when form_view is available

Adding Logging

Enable logging to see what widgetastic is doing:

import logging

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# Create browser with logger
logger = logging.getLogger("my_automation")
wt_browser = MyBrowser(page, logger=logger)

This will show detailed logs of widget operations:

2025-10-23 16:31:24,598 - my_automation - INFO - Opening URL: 'https://httpbin.org/forms/post' (wait_until=None)
2025-10-23 16:31:39,549 - my_automation - INFO - [DemoFormView/custname]: fill('John Doe') -> True (elapsed 624 ms)
2025-10-23 16:31:39,662 - my_automation - INFO - [DemoFormView/telephone]: fill('1234567890') -> True (elapsed 113 ms)