"""
Simple test to verify that sequential agents can reuse the same BrowserSession
without it being closed prematurely due to garbage collection.
"""
import asyncio
import gc
from browser_use import Agent, BrowserProfile, BrowserSession
from tests.ci.conftest import create_mock_llm
class TestSequentialAgentsSimple:
"""Test that sequential agents can properly reuse the same BrowserSession"""
async def test_sequential_agents_share_browser_session_simple(self, httpserver):
"""Test that multiple agents can reuse the same browser session without it being closed"""
# Set up test HTML pages
httpserver.expect_request('/page1').respond_with_data('
Page 1
')
httpserver.expect_request('/page2').respond_with_data('Page 2
')
# Create a browser session with keep_alive=True
browser_session = BrowserSession(
browser_profile=BrowserProfile(
keep_alive=True,
headless=True,
user_data_dir=None, # Use temporary directory
)
)
await browser_session.start()
# Verify browser is running
initial_pid = browser_session.browser_pid
# Browser PID detection may fail in CI environments
# The important thing is that the browser is connected
assert await browser_session.is_connected(restart=False)
# Agent 1: Navigate to page 1
agent1_actions = [
f"""{{
"thinking": "Navigating to page 1",
"evaluation_previous_goal": "Starting task",
"memory": "Need to navigate to page 1",
"next_goal": "Navigate to page 1",
"action": [
{{"go_to_url": {{"url": "{httpserver.url_for('/page1')}", "new_tab": false}}}}
]
}}"""
]
agent1 = Agent(
task='Navigate to page 1',
llm=create_mock_llm(agent1_actions),
browser_session=browser_session,
)
history1 = await agent1.run(max_steps=2)
assert len(history1.history) >= 1
assert history1.history[-1].state.url == httpserver.url_for('/page1')
# Verify browser session is still alive
assert browser_session.initialized
if initial_pid is not None:
assert browser_session.browser_pid == initial_pid
# Delete agent1 and force garbage collection
del agent1
gc.collect()
await asyncio.sleep(0.1) # Give time for any async cleanup
# Verify browser is STILL alive after garbage collection
assert browser_session.initialized
if initial_pid is not None:
assert browser_session.browser_pid == initial_pid
assert browser_session.browser_context is not None
# Agent 2: Navigate to page 2
agent2_actions = [
f"""{{
"thinking": "Navigating to page 2",
"evaluation_previous_goal": "Previous agent successfully navigated",
"memory": "Browser is still open, need to go to page 2",
"next_goal": "Navigate to page 2",
"action": [
{{"go_to_url": {{"url": "{httpserver.url_for('/page2')}", "new_tab": false}}}}
]
}}"""
]
agent2 = Agent(
task='Navigate to page 2',
llm=create_mock_llm(agent2_actions),
browser_session=browser_session,
)
history2 = await agent2.run(max_steps=2)
assert len(history2.history) >= 1
assert history2.history[-1].state.url == httpserver.url_for('/page2')
# Verify browser session is still alive after second agent
assert browser_session.initialized
if initial_pid is not None:
assert browser_session.browser_pid == initial_pid
assert browser_session.browser_context is not None
# Clean up
await browser_session.kill()
async def test_multiple_tabs_sequential_agents(self, httpserver):
"""Test that sequential agents can work with multiple tabs"""
# Set up test pages
httpserver.expect_request('/tab1').respond_with_data('Tab 1
')
httpserver.expect_request('/tab2').respond_with_data('Tab 2
')
browser_session = BrowserSession(
browser_profile=BrowserProfile(
keep_alive=True,
headless=True,
user_data_dir=None, # Use temporary directory
)
)
await browser_session.start()
# Agent 1: Open two tabs
agent1_actions = [
f"""{{
"thinking": "Opening two tabs",
"evaluation_previous_goal": "Starting task",
"memory": "Need to open two tabs",
"next_goal": "Open tab 1 and tab 2",
"action": [
{{"go_to_url": {{"url": "{httpserver.url_for('/tab1')}", "new_tab": false}}}},
{{"go_to_url": {{"url": "{httpserver.url_for('/tab2')}", "new_tab": true}}}}
]
}}"""
]
agent1 = Agent(
task='Open two tabs',
llm=create_mock_llm(agent1_actions),
browser_session=browser_session,
)
await agent1.run(max_steps=2)
# Verify 2 tabs are open
assert len(browser_session.tabs) == 2
# Agent1 should be on the second tab (tab2)
assert agent1.browser_session is not None
assert agent1.browser_session.agent_current_page is not None
assert '/tab2' in agent1.browser_session.agent_current_page.url
# Clean up agent1
del agent1
gc.collect()
await asyncio.sleep(0.1)
# Agent 2: Switch to first tab
agent2_actions = [
"""{
"thinking": "Switching to first tab",
"evaluation_previous_goal": "Two tabs are open",
"memory": "Need to switch to tab 0",
"next_goal": "Switch to tab 0",
"action": [
{"switch_tab": {"page_id": 0}}
]
}"""
]
agent2 = Agent(
task='Switch to first tab',
llm=create_mock_llm(agent2_actions),
browser_session=browser_session,
)
history2 = await agent2.run(max_steps=3)
# Verify agent2 is on the first tab
assert agent2.browser_session is not None
assert agent2.browser_session.agent_current_page is not None
assert '/tab1' in agent2.browser_session.agent_current_page.url
# Verify browser is still functional
assert browser_session.initialized
assert len(browser_session.tabs) == 2
await browser_session.kill()