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 submissionsync_playwright- Playwright’s synchronous API for browser automationBrowser- Widgetastic’s enhanced browser wrapperWidget 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)