import pytest from pytest_httpserver import HTTPServer from browser_use.agent.views import ActionResult from browser_use.browser import BrowserSession from browser_use.browser.profile import BrowserProfile from browser_use.tools.service import Tools @pytest.fixture(scope='session') def http_server(): """Create and provide a test HTTP server that serves static content.""" server = HTTPServer() server.start() # Add route for ARIA menu test page server.expect_request('/aria-menu').respond_with_data( """ ARIA Menu Test

ARIA Menu Test

This menu uses ARIA roles instead of native select elements

Click an option to see the result
""", content_type='text/html', ) yield server server.stop() @pytest.fixture(scope='session') def base_url(http_server): """Return the base URL for the test HTTP server.""" return f'http://{http_server.host}:{http_server.port}' @pytest.fixture(scope='module') async def browser_session(): """Create and provide a Browser instance with security disabled.""" browser_session = BrowserSession( browser_profile=BrowserProfile( headless=True, user_data_dir=None, keep_alive=True, chromium_sandbox=False, # Disable sandbox for CI environment ) ) await browser_session.start() yield browser_session await browser_session.kill() @pytest.fixture(scope='function') def tools(): """Create and provide a Tools instance.""" return Tools() class TestARIAMenuDropdown: """Test ARIA menu support for get_dropdown_options and select_dropdown_option.""" @pytest.mark.skip(reason='TODO: fix') async def test_get_dropdown_options_with_aria_menu(self, tools, browser_session: BrowserSession, base_url): """Test that get_dropdown_options can retrieve options from ARIA menus.""" # Navigate to the ARIA menu test page await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session) # Wait for the page to load from browser_use.browser.events import NavigationCompleteEvent await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0) # Initialize the DOM state to populate the selector map await browser_session.get_browser_state_summary() # Find the ARIA menu element by ID menu_index = await browser_session.get_index_by_id('pyNavigation1752753375773') assert menu_index is not None, 'Could not find ARIA menu element' # Execute the action with the menu index result = await tools.dropdown_options(index=menu_index, browser_session=browser_session) # Verify the result structure assert isinstance(result, ActionResult) assert result.extracted_content is not None # Expected ARIA menu options expected_options = ['Filter', 'Sort', 'Appearance', 'Summarize', 'Delete'] # Verify all options are returned for option in expected_options: assert option in result.extracted_content, f"Option '{option}' not found in result content" # Verify the instruction for using the text in select_dropdown is included assert 'Use the exact text string in select_dropdown' in result.extracted_content @pytest.mark.skip(reason='TODO: fix') async def test_select_dropdown_option_with_aria_menu(self, tools, browser_session: BrowserSession, base_url): """Test that select_dropdown_option can select an option from ARIA menus.""" # Navigate to the ARIA menu test page await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session) # Wait for the page to load from browser_use.browser.events import NavigationCompleteEvent await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0) # Initialize the DOM state to populate the selector map await browser_session.get_browser_state_summary() # Find the ARIA menu element by ID menu_index = await browser_session.get_index_by_id('pyNavigation1752753375773') assert menu_index is not None, 'Could not find ARIA menu element' # Execute the action with the menu index to select "Filter" result = await tools.select_dropdown(index=menu_index, text='Filter', browser_session=browser_session) # Verify the result structure assert isinstance(result, ActionResult) # Core logic validation: Verify selection was successful assert result.extracted_content is not None assert 'selected option' in result.extracted_content.lower() or 'clicked' in result.extracted_content.lower() assert 'Filter' in result.extracted_content # Verify the click actually had an effect on the page using CDP cdp_session = await browser_session.get_or_create_cdp_session() result = await cdp_session.cdp_client.send.Runtime.evaluate( params={'expression': "document.getElementById('result').textContent", 'returnByValue': True}, session_id=cdp_session.session_id, ) result_text = result.get('result', {}).get('value', '') assert 'Filter' in result_text, f"Expected 'Filter' in result text, got '{result_text}'" @pytest.mark.skip(reason='TODO: fix') async def test_get_dropdown_options_with_nested_aria_menu(self, tools, browser_session: BrowserSession, base_url): """Test that get_dropdown_options can handle nested ARIA menus (like Sort submenu).""" # Navigate to the ARIA menu test page await tools.navigate(url=f'{base_url}/aria-menu', new_tab=False, browser_session=browser_session) # Wait for the page to load from browser_use.browser.events import NavigationCompleteEvent await browser_session.event_bus.expect(NavigationCompleteEvent, timeout=10.0) # Initialize the DOM state to populate the selector map await browser_session.get_browser_state_summary() # Get the selector map selector_map = await browser_session.get_selector_map() # Find the nested ARIA menu element in the selector map nested_menu_index = None for idx, element in selector_map.items(): # Look for the nested UL with id containing "$PpyNavigation" if ( element.tag_name.lower() == 'ul' and '$PpyNavigation' in str(element.attributes.get('id', '')) and element.attributes.get('role') == 'menu' ): nested_menu_index = idx break # The nested menu might not be in the selector map initially if it's hidden # In that case, we should test the main menu if nested_menu_index is None: # Find the main menu instead for idx, element in selector_map.items(): if element.tag_name.lower() == 'ul' and element.attributes.get('id') == 'pyNavigation1752753375773': nested_menu_index = idx break assert nested_menu_index is not None, ( f'Could not find any ARIA menu element in selector map. Available elements: {[f"{idx}: {element.tag_name}" for idx, element in selector_map.items()]}' ) # Execute the action with the menu index result = await tools.dropdown_options(index=nested_menu_index, browser_session=browser_session) # Verify the result structure assert isinstance(result, ActionResult) assert result.extracted_content is not None # The action should return some menu options assert 'Use the exact text string in select_dropdown' in result.extracted_content