Skip to content

JoanEsquivel/python-se

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

37 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸš€ Modern Selenium Framework with W3C BiDi Accessibility Locators

Enterprise-grade test automation framework featuring native W3C WebDriver BiDi accessibility locators with intelligent fallback strategies

Python 3.8+ Selenium 4.34+ W3C BiDi MIT License

🎯 Overview

This framework revolutionizes Selenium automation by providing native accessibility-based element location that mirrors how users actually interact with web applications. It seamlessly integrates W3C WebDriver BiDi protocol with intelligent fallback mechanisms for maximum compatibility and future-proofing.

🌟 Key Innovations

  • 🎯 W3C BiDi Native Support: First-class implementation of browsingContext.locateNodes
  • 🎭 Natural ARIA Locators: Find elements by roles and accessible names
  • πŸ”§ Zero-Setup Installation: Auto-extends WebDriver with new methods
  • 🌊 Intelligent Fallback: BiDi β†’ CDP β†’ DOM cascade for 100% compatibility
  • πŸ—οΈ Enterprise Architecture: Production-ready with comprehensive error handling
  • πŸš€ Performance Optimized: Caching and strategy pattern implementation

πŸ“‹ Table of Contents


πŸš€ Quick Start

Installation

# Clone repository git clone <repository-url> cd python-se # Create virtual environment (recommended) python -m venv se-python-env source se-python-env/bin/activate # Windows: se-python-env\Scripts\activate # Install dependencies  pip install -r requirements.txt

Basic Usage

import utils # πŸŽ‰ Auto-enables ARIA methods on WebDriver! # Natural element location (just like native Selenium) username = driver.find_element_by_role("textbox", name="Username") submit_btn = driver.find_element_by_role("button", name="Submit") all_links = driver.find_elements_by_role("link")

Type-Safe Usage

from utils import ARIARole, LocatorConfig # Use enums for IDE support and safety email_field = driver.find_element_by_role(ARIARole.TEXTBOX, name="Email") login_button = driver.find_element_by_role(ARIARole.BUTTON, name="Login") # Configure advanced options config = LocatorConfig( bidi_priority=True, # Prefer BiDi when available cdp_fallback=True, # Enable CDP fallback debug_mode=True # Detailed logging )

πŸ—οΈ Architecture Overview

🎯 Three-Tier Locator Strategy

Our framework implements a sophisticated cascading fallback system:

graph TD A[ARIA Locator Request] --> B{BiDi Available?} B -->|Yes| C[W3C BiDi browsingContext.locateNodes] B -->|No| D{CDP Available?} D -->|Yes| E[Chrome DevTools Protocol] D -->|No| F[DOM CSS Selectors + Accessibility Tree] C --> G{Elements Found?} E --> G F --> G G -->|Yes| H[Return WebElements] G -->|No| I[Graceful Fallback/Exception] 
Loading

πŸ”§ Core Components

Component Purpose Technology
BiDiAccessibilityLocator W3C BiDi native implementation browsingContext.locateNodes
CDPAccessibilityBridge Chrome DevTools fallback Accessibility.getFullAXTree
DOMAccessibilityParser Universal DOM fallback CSS selectors + ARIA parsing
WebDriverExtensions Seamless API integration Dynamic method injection

⚑ Performance Features

  • Intelligent Caching: Context IDs and availability checks
  • Strategy Pattern: Modular execution methods
  • Lazy Loading: Components initialized on-demand
  • Error Chaining: Comprehensive debugging information

🎭 BiDi Accessibility Locators

🌟 What is W3C WebDriver BiDi?

WebDriver BiDi (Bidirectional Protocol) is the next-generation W3C standard that enables two-way communication between test scripts and browsers. Our framework leverages BiDi's browsingContext.locateNodes command for native accessibility-based element location.

✨ BiDi Advantages

  • 🎯 Native Performance: Direct browser communication
  • πŸ›‘οΈ Future-Proof: W3C standard implementation
  • 🎭 True Accessibility: Authentic accessibility tree traversal
  • πŸš€ Cross-Browser: Consistent behavior across all browsers

πŸ”§ BiDi Implementation

from utils.bidi_locators import BiDiAccessibilityLocator # Direct BiDi usage locator = BiDiAccessibilityLocator(driver) # Check BiDi availability if locator.is_available(): elements = locator.find_elements( role="button", name="Submit", max_count=10 )

πŸŽ›οΈ BiDi Configuration

# Enable BiDi in your WebDriver chrome_options.set_capability("webSocketUrl", True) # Essential! firefox_options.set_capability("webSocketUrl", True) edge_options.set_capability("webSocketUrl", True)

πŸ“Š Supported ARIA Roles & Attributes

Role Description Additional Attributes
textbox Input fields, textareas placeholder, required
button Buttons, submit elements pressed, disabled
checkbox Checkbox inputs checked, disabled
radio Radio button inputs checked, disabled
link Anchor elements href
heading Headers (h1-h6) level
listitem List items setsize, posinset
tab Tab elements selected
dialog Modal dialogs modal

βš™οΈ Implementation Details

🏭 Enterprise Architecture Patterns

Strategy Pattern for Execution

class BiDiAccessibilityLocator: def _execute_bidi_command(self, method: str, params: Dict[str, Any]) -> Dict[str, Any]: execution_strategies = [ self._try_native_browsing_context, # Selenium 4.15+ self._try_direct_bidi_command, # Future versions self._try_legacy_bidi_connection, # Legacy support self._try_cdp_bridge # CDP fallback ] for strategy in execution_strategies: try: result = strategy(method, params) if result is not None: return result except Exception as e: logger.debug(f"Strategy failed: {strategy.__name__}: {e}") continue

Intelligent Caching System

class BiDiAccessibilityLocator: def __init__(self, driver: WebDriver) -> None: self.driver = driver self._context_id: Optional[str] = None # Cache context ID self._bidi_available: Optional[bool] = None # Cache availability

Robust Error Handling

# Exception chaining for better debugging except WebDriverException as e: raise BiDiNotAvailableError(f"Context error: {e}") from e

πŸ” Fallback Strategy Details

  1. BiDi Native (_try_native_browsing_context):

    driver.browsing_context.locate_nodes( context=context_id, locator={"type": "accessibility", "value": {"role": "button"}}, max_node_count=1000 )
  2. CDP Bridge (_try_cdp_bridge):

    driver.execute_cdp_cmd("Accessibility.enable", {}) tree_result = driver.execute_cdp_cmd("Accessibility.getFullAXTree", {})
  3. DOM Fallback:

    driver.find_elements(By.CSS_SELECTOR, 'button, [role="button"]')

πŸ§ͺ Testing & Debugging

🎯 Test Structure

Our comprehensive test suite validates all implementation layers:

class TestBiDiIntegration: def test_bidi_availability_check(self, driver): """Verify BiDi detection works correctly""" def test_bidi_direct_usage_when_available(self, driver): """Test direct BiDi implementation""" def test_priority_order_works(self, driver): """Verify BiDi β†’ CDP β†’ DOM cascade""" def test_error_handling(self, driver): """Test robust error scenarios"""

πŸ”§ Debug Mode

Enable detailed logging to understand execution flow:

from utils import LocatorConfig config = LocatorConfig(debug_mode=True)

Debug Output Example:

DEBUG Using native BiDi accessibility locators DEBUG -> {"method": "browsingContext.locateNodes", "params": {...}} DEBUG <- {'id': 1, 'result': {'nodes': []}, 'type': 'success'} DEBUG BiDi accessibility found 0 elements DEBUG CDP accessibility tree found 2 elements DEBUG DOM search found 2 elements 

πŸ“Š Performance Testing

def test_performance_comparison(self, driver): """Compare BiDi vs CDP vs DOM performance""" # Measure execution times bidi_time = measure_execution_time(bidi_locator.find_elements) cdp_time = measure_execution_time(cdp_locator.find_elements) dom_time = measure_execution_time(dom_locator.find_elements)

πŸ“Š Command Reference

πŸš€ Basic Testing Commands

# Run all tests (default: Chrome) pytest tests/ -v # Test specific browser pytest tests/ --browser chrome -v pytest tests/ --browser firefox -v pytest tests/ --browser edge -v # Run specific test file pytest tests/test_bidi_integration.py -v pytest tests/test_get_by_role.py -v

πŸ” BiDi-Specific Testing

# Test BiDi functionality across all browsers pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=chrome -v pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=firefox -v pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_bidi_direct_usage_when_available --browser=edge -v # Test priority system (BiDi β†’ CDP β†’ DOM) pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_priority_order_works -v # Test with debug logging pytest tests/test_bidi_integration.py -v -s --log-cli-level=DEBUG

πŸ› οΈ Debugging Commands

# Enable verbose debug output pytest tests/ -v -s --log-cli-level=DEBUG # Run single test with maximum verbosity pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_locator_config_debug_mode -v -s --log-cli-level=DEBUG # Generate HTML test report pytest tests/ --html=report.html --self-contained-html # Run tests and show performance metrics pytest tests/test_bidi_integration.py::TestBiDiIntegration::test_performance_comparison -v -s

πŸ”§ Development Commands

# Install in development mode pip install -e . # Run linting (if configured) flake8 utils/ tests/ # Type checking (if configured)  mypy utils/ # Run tests with coverage pytest tests/ --cov=utils --cov-report=html

πŸ“ˆ Advanced Testing Scenarios

# Test BiDi availability detection python -c " from selenium import webdriver from utils.bidi_locators import is_bidi_accessibility_available from selenium.webdriver.chrome.options import Options  options = Options() options.set_capability('webSocketUrl', True) driver = webdriver.Chrome(options=options) print(f'BiDi Available: {is_bidi_accessibility_available(driver)}') driver.quit() " # Test error handling scenarios python -c " from selenium import webdriver from utils.bidi_locators import BiDiAccessibilityLocator, BiDiNotAvailableError  driver = webdriver.Chrome() # No webSocketUrl locator = BiDiAccessibilityLocator(driver) try:  locator.find_element('button') except BiDiNotAvailableError as e:  print(f'Expected error: {e}') driver.quit() " # Manual BiDi testing python -c " from selenium import webdriver from selenium.webdriver.chrome.options import Options from utils.bidi_locators import BiDiAccessibilityLocator  options = Options() options.set_capability('webSocketUrl', True) driver = webdriver.Chrome(options=options) driver.get('https://example.com')  locator = BiDiAccessibilityLocator(driver) print(f'BiDi Available: {locator.is_available()}')  # Try direct BiDi usage try:  elements = locator.find_elements('button')  print(f'Found {len(elements)} buttons via BiDi') except Exception as e:  print(f'BiDi error: {e}')  driver.quit() "

🌐 Browser Support

βœ… Compatibility Matrix

Browser BiDi Native CDP Fallback DOM Fallback Status
Chrome 118+ βœ… βœ… βœ… Fully Supported
Firefox 119+ βœ… ❌ βœ… Fully Supported
Edge 118+ βœ… βœ… βœ… Fully Supported
Safari ⏳ ❌ βœ… DOM Only

πŸ”§ Browser Configuration

Chrome Configuration

from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.set_capability("webSocketUrl", True) # Enable BiDi chrome_options.add_argument("--headless") # Optional chrome_options.add_argument("--no-sandbox") # CI/CD chrome_options.add_argument("--disable-dev-shm-usage") driver = webdriver.Chrome(options=chrome_options)

Firefox Configuration

from selenium.webdriver.firefox.options import Options firefox_options = Options() firefox_options.set_capability("webSocketUrl", True) # Enable BiDi firefox_options.add_argument("--headless") # Optional driver = webdriver.Firefox(options=firefox_options)

Edge Configuration

from selenium.webdriver.edge.options import Options edge_options = Options() edge_options.set_capability("webSocketUrl", True) # Enable BiDi edge_options.add_argument("--headless") # Optional driver = webdriver.Edge(options=edge_options)

πŸ“ Project Structure

python-se/ β”œβ”€β”€ πŸ“ tests/ # Test suite β”‚ β”œβ”€β”€ conftest.py # pytest configuration & fixtures β”‚ β”œβ”€β”€ test_bidi_integration.py # 🎯 BiDi integration tests β”‚ β”œβ”€β”€ test_get_by_role.py # ARIA locator tests β”‚ └── test_login_page.py # Example test scenarios β”œβ”€β”€ πŸ“ utils/ # Core framework β”‚ β”œβ”€β”€ __init__.py # Package initialization β”‚ β”œβ”€β”€ aria_locators.py # 🎭 Main ARIA implementation β”‚ β”œβ”€β”€ bidi_locators.py # πŸš€ W3C BiDi implementation β”‚ └── webdriver_extensions.py # WebDriver method injection β”œβ”€β”€ πŸ“„ requirements.txt # Python dependencies β”œβ”€β”€ πŸ“„ readme.md # This documentation β”œβ”€β”€ πŸ“„ BLOG_POST.md # Technical blog post └── πŸ“„ SELENIUM_ISSUE_UPDATE.md # BiDi implementation notes 

πŸ” Core Module Details

utils/bidi_locators.py - W3C BiDi Implementation

  • BiDiAccessibilityLocator: Main BiDi locator class
  • Strategy pattern for execution methods
  • Intelligent caching and error handling
  • Full W3C browsingContext.locateNodes support

utils/aria_locators.py - Comprehensive ARIA Support

  • Multi-tier locator strategy (BiDi β†’ CDP β†’ DOM)
  • ARIARole enum definitions
  • LocatorConfig for advanced options
  • Performance optimization

utils/webdriver_extensions.py - Seamless Integration

  • Dynamic method injection into WebDriver
  • find_element_by_role() / find_elements_by_role()
  • Zero-setup auto-installation

tests/test_bidi_integration.py - BiDi Test Suite

  • BiDi availability testing
  • Cross-browser compatibility validation
  • Priority system verification
  • Performance benchmarking

πŸ”§ Advanced Usage

πŸŽ›οΈ Configuration Options

from utils import LocatorConfig # Advanced configuration config = LocatorConfig( bidi_priority=True, # Prefer BiDi when available cdp_fallback=True, # Enable CDP fallback dom_fallback=True, # Enable DOM fallback  debug_mode=True, # Detailed logging timeout=10, # Element timeout (seconds) retry_count=3, # Retry attempts cache_results=True # Cache element lookups ) # Apply configuration globally driver.aria_config = config

πŸ” Direct BiDi Access

from utils.bidi_locators import BiDiAccessibilityLocator # Direct BiDi usage (advanced) bidi_locator = BiDiAccessibilityLocator(driver) if bidi_locator.is_available(): # Find with custom parameters elements = bidi_locator.find_elements( role="button", name="Submit", max_count=5, # Limit results pressed=False, # Button state disabled=False # Accessibility state ) # Single element with validation try: submit_btn = bidi_locator.find_element("button", name="Submit") except NoSuchElementException: print("Submit button not found")

πŸ“Š Performance Monitoring

import time from utils import LocatorConfig # Performance testing config = LocatorConfig(debug_mode=True) start_time = time.time() elements = driver.find_elements_by_role("button") execution_time = time.time() - start_time print(f"Found {len(elements)} elements in {execution_time:.3f}s")

πŸ›‘οΈ Error Handling Best Practices

from utils.bidi_locators import BiDiNotAvailableError from selenium.common.exceptions import NoSuchElementException try: # Attempt element location element = driver.find_element_by_role("button", name="Submit") element.click() except BiDiNotAvailableError: # BiDi not available, but fallback should work print("BiDi unavailable, using fallback methods") except NoSuchElementException: # Element genuinely not found print("Submit button not found on page") except Exception as e: # Unexpected error print(f"Unexpected error: {e}")

🀝 Contributing

We welcome contributions! This framework represents cutting-edge Selenium automation with W3C BiDi integration.

Development Setup

git clone <repository-url> cd python-se python -m venv dev-env source dev-env/bin/activate pip install -r requirements.txt pip install -e .

Running Tests

# Full test suite pytest tests/ -v # BiDi-specific tests pytest tests/test_bidi_integration.py -v # With coverage pytest tests/ --cov=utils --cov-report=html

πŸ“„ License

MIT License - Feel free to use in your projects!


πŸŽ‰ Why Choose This Framework?

πŸš€ Next-Generation Technology

  • W3C BiDi Native: First framework with production-ready BiDi accessibility locators
  • Future-Proof: Built on emerging W3C standards
  • Enterprise-Ready: Production-tested architecture patterns

πŸ’‘ Developer Experience

  • Zero Setup: Import and use immediately
  • Natural API: Familiar Selenium-style methods
  • Type Safety: Full IDE support with enums
  • Comprehensive Docs: Extensive documentation and examples

🎯 Reliability

  • Intelligent Fallbacks: Never fails due to technology limitations
  • Cross-Browser: Consistent behavior across all major browsers
  • Performance Optimized: Caching and strategy patterns
  • Error Resilient: Comprehensive error handling and debugging

πŸ“ˆ Comparison with Traditional Approaches

Aspect Traditional Selenium This Framework
Locator Strategy CSS/XPath selectors Accessibility-based
Brittleness High (layout changes break) Low (semantic stability)
Readability Poor (By.XPATH, "//div[@class='btn']") Excellent (role="button")
Future-Proof No (legacy selectors) Yes (W3C standards)
Performance Variable Optimized with caching
Browser Support Manual configuration Auto-detection + fallbacks

🎯 Ready to revolutionize your Selenium automation? Get started with W3C BiDi accessibility locators today!

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages