Files
wehub-resource-sync 4cd2d4af2b
Test Browser Use CLI Install / uv pip install (ubuntu-latest) (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use from local wheel (push) Failing after 1s
Test Browser Use CLI Install / uvx browser-use[cli] from PyPI (push) Failing after 1s
package / pip-install-on-macos-latest-py-3.11 (push) Has been skipped
package / pip-install-on-macos-latest-py-3.13 (push) Has been skipped
package / pip-install-on-ubuntu-latest-py-3.11 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.13 (push) Has been skipped
cloud_evals / trigger_cloud_eval_image_build (push) Failing after 1s
docker / build_publish_image (push) Failing after 1s
Test Browser Use CLI Install / browser-use skill sync (push) Failing after 1s
lint / code-style (push) Failing after 0s
lint / type-checker (push) Failing after 1s
package / pip-build (push) Failing after 1s
lint / syntax-errors (push) Failing after 3s
package / pip-install-on-ubuntu-latest-py-3.13 (push) Has been skipped
package / pip-install-on-windows-latest-py-3.11 (push) Has been skipped
test / ${{ matrix.test_filename }} (push) Has been skipped
test / evaluate-tasks (push) Has been skipped
test / setup-chromium (push) Failing after 2s
test / find_tests (push) Failing after 2s
Test Browser Use CLI Install / uv pip install (windows-latest) (push) Has been cancelled
Test Browser Use CLI Install / uv pip install (macos-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:02:32 +08:00

189 lines
6.0 KiB
Python

"""
Test navigation on heavy/slow-loading pages (e.g. e-commerce PDPs).
Reproduces the issue where navigating to heavy pages like stevemadden.com PDPs
fails due to NavigateToUrlEvent timing out.
Usage:
uv run pytest tests/ci/browser/test_navigation_slow_pages.py -v -s
"""
import asyncio
import time
import pytest
from pytest_httpserver import HTTPServer
from werkzeug import Response
from browser_use.agent.service import Agent
from browser_use.browser import BrowserSession
from browser_use.browser.events import NavigateToUrlEvent
from browser_use.browser.profile import BrowserProfile
from tests.ci.conftest import create_mock_llm
HEAVY_PDP_HTML = """
<!DOCTYPE html>
<html>
<head><title>Frosting Black Velvet - Steve Madden</title></head>
<body>
<h1>FROSTING</h1>
<p class="price">$129.95</p>
<button id="add-to-cart">ADD TO BAG</button>
</body>
</html>
"""
@pytest.fixture(scope='session')
def heavy_page_server():
server = HTTPServer()
server.start()
def slow_initial_response(request):
time.sleep(6)
return Response(HEAVY_PDP_HTML, content_type='text/html')
server.expect_request('/slow-server-pdp').respond_with_handler(slow_initial_response)
def redirect_step1(request):
return Response('', status=302, headers={'Location': f'http://{server.host}:{server.port}/redirect-step2'})
def redirect_step2(request):
return Response('', status=302, headers={'Location': f'http://{server.host}:{server.port}/redirect-final'})
def redirect_final(request):
time.sleep(3)
return Response(HEAVY_PDP_HTML, content_type='text/html')
server.expect_request('/redirect-step1').respond_with_handler(redirect_step1)
server.expect_request('/redirect-step2').respond_with_handler(redirect_step2)
server.expect_request('/redirect-final').respond_with_handler(redirect_final)
server.expect_request('/fast-dom-slow-load').respond_with_data(HEAVY_PDP_HTML, content_type='text/html')
server.expect_request('/quick-page').respond_with_data(
'<html><body><h1>Quick Page</h1></body></html>', content_type='text/html'
)
yield server
server.stop()
@pytest.fixture(scope='session')
def heavy_base_url(heavy_page_server):
return f'http://{heavy_page_server.host}:{heavy_page_server.port}'
@pytest.fixture(scope='function')
async def browser_session():
session = BrowserSession(browser_profile=BrowserProfile(headless=True, user_data_dir=None, keep_alive=True))
await session.start()
yield session
await session.kill()
def _nav_actions(url: str, msg: str = 'Done') -> list[str]:
"""Helper to build a navigate-then-done action sequence."""
return [
f"""
{{
"thinking": "Navigate to the page",
"evaluation_previous_goal": "Starting task",
"memory": "Navigating",
"next_goal": "Navigate",
"action": [{{"navigate": {{"url": "{url}"}}}}]
}}
""",
f"""
{{
"thinking": "Page loaded",
"evaluation_previous_goal": "Navigation completed",
"memory": "Page loaded",
"next_goal": "Done",
"action": [{{"done": {{"text": "{msg}", "success": true}}}}]
}}
""",
]
class TestHeavyPageNavigation:
async def test_slow_server_response_completes(self, browser_session, heavy_base_url):
"""Navigation succeeds even when server takes 6s to respond."""
url = f'{heavy_base_url}/slow-server-pdp'
agent = Agent(
task=f'Navigate to {url}',
llm=create_mock_llm(actions=_nav_actions(url)),
browser_session=browser_session,
)
start = time.time()
history = await asyncio.wait_for(agent.run(max_steps=3), timeout=60)
assert len(history) > 0
assert history.final_result() is not None
assert time.time() - start >= 5, 'Should have waited for slow server'
async def test_redirect_chain_completes(self, browser_session, heavy_base_url):
"""Navigation handles multi-step redirects + slow final response."""
url = f'{heavy_base_url}/redirect-step1'
agent = Agent(
task=f'Navigate to {url}',
llm=create_mock_llm(actions=_nav_actions(url)),
browser_session=browser_session,
)
history = await asyncio.wait_for(agent.run(max_steps=3), timeout=60)
assert len(history) > 0
assert history.final_result() is not None
async def test_navigate_event_accepts_domcontentloaded(self, browser_session, heavy_base_url):
"""NavigateToUrlEvent with fast page should complete quickly via DOMContentLoaded/load."""
url = f'{heavy_base_url}/fast-dom-slow-load'
event = browser_session.event_bus.dispatch(NavigateToUrlEvent(url=url))
await asyncio.wait_for(event, timeout=15)
await event.event_result(raise_if_any=True, raise_if_none=False)
async def test_recovery_after_slow_navigation(self, browser_session, heavy_base_url):
"""Agent recovers and navigates to a fast page after a slow one."""
slow_url = f'{heavy_base_url}/slow-server-pdp'
quick_url = f'{heavy_base_url}/quick-page'
actions = [
f"""
{{
"thinking": "Navigate to slow page",
"evaluation_previous_goal": "Starting",
"memory": "Going to slow page",
"next_goal": "Navigate",
"action": [{{"navigate": {{"url": "{slow_url}"}}}}]
}}
""",
f"""
{{
"thinking": "Now navigate to quick page",
"evaluation_previous_goal": "Slow page loaded",
"memory": "Trying quick page",
"next_goal": "Navigate",
"action": [{{"navigate": {{"url": "{quick_url}"}}}}]
}}
""",
"""
{
"thinking": "Both done",
"evaluation_previous_goal": "Quick page loaded",
"memory": "Recovery successful",
"next_goal": "Done",
"action": [{"done": {"text": "Recovery succeeded", "success": true}}]
}
""",
]
agent = Agent(
task='Navigate to slow then quick page',
llm=create_mock_llm(actions=actions),
browser_session=browser_session,
)
history = await asyncio.wait_for(agent.run(max_steps=4), timeout=90)
assert len(history) >= 2
assert history.final_result() is not None
async def test_event_timeout_sufficient_for_heavy_pages(self, browser_session):
"""event_timeout should be >= 30s to handle slow servers + redirect chains."""
event = NavigateToUrlEvent(url='http://example.com')
assert event.event_timeout is not None
assert event.event_timeout >= 30.0, f'event_timeout={event.event_timeout}s is too low for heavy pages (need >= 30s)'