use browser_use::{BrowserSession, LaunchOptions,
tools::{CloseTabParams, NewTabParams, SwitchTabParams, TabListParams, Tool, ToolContext,
close_tab::CloseTabTool, new_tab::NewTabTool, switch_tab::SwitchTabTool,
tab_list::TabListTool}};
use log::info;
#[test]
#[ignore]
fn test_new_tab() {
use browser_use::tools::{NewTabParams, Tool, ToolContext, new_tab::NewTabTool};
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
// Navigate to initial page
session.navigate("data:text/html,
First Tab
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
// Get initial tab count
let initial_tabs = session.get_tabs().expect("Failed to get tabs");
let initial_count = initial_tabs.len();
info!("Initial tab count: {}", initial_count);
// Create tool and context
let tool = NewTabTool::default();
let mut context = ToolContext::new(&session);
// Execute the tool to create a new tab
let result = tool
.execute_typed(
NewTabParams { url: "data:text/html,Second Tab
".to_string() },
&mut context,
)
.expect("Failed to execute new_tab tool");
// Verify the result
assert!(result.success, "Tool execution should succeed");
assert!(result.data.is_some());
let data = result.data.unwrap();
assert!(data["url"].as_str().is_some(), "Result should contain url field");
assert!(data["message"].as_str().is_some(), "Result should contain message field");
info!("New tab result: {}", serde_json::to_string_pretty(&data).unwrap());
std::thread::sleep(std::time::Duration::from_millis(500));
// Verify tab count increased
let final_tabs = session.get_tabs().expect("Failed to get tabs");
let final_count = final_tabs.len();
info!("Final tab count: {}", final_count);
assert_eq!(final_count, initial_count + 1, "Tab count should increase by 1");
}
#[test]
#[ignore] // Requires Chrome to be installed
fn test_tab_list() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
// Navigate to a simple page
session.navigate("data:text/html,First Tab
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
// Create tool and context
let tool = TabListTool::default();
let mut context = ToolContext::new(&session);
// Execute the tool
let result = tool.execute_typed(TabListParams {}, &mut context).expect("Failed to execute tab_list tool");
// Verify the result
assert!(result.success, "Tool execution should succeed");
assert!(result.data.is_some());
let data = result.data.unwrap();
let tab_list = data["tab_list"].as_array().expect("No tab_list field");
let count = data["count"].as_u64().expect("No count field");
info!("Tab list: {}", serde_json::to_string_pretty(&tab_list).unwrap());
// Should have at least 1 tab
assert!(count >= 1, "Expected at least 1 tab");
assert_eq!(tab_list.len() as u64, count);
// Check first tab structure
let first_tab = &tab_list[0];
assert!(first_tab["index"].is_number(), "Tab should have index");
assert!(first_tab["active"].is_boolean(), "Tab should have active flag");
assert!(first_tab["title"].is_string(), "Tab should have title");
assert!(first_tab["url"].is_string(), "Tab should have url");
}
#[test]
#[ignore]
fn test_new_tab_and_switch() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
// Navigate to initial page
session.navigate("data:text/html,First Tab
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
// Create a new tab
let new_tab_tool = NewTabTool::default();
let mut context = ToolContext::new(&session);
let result = new_tab_tool
.execute_typed(
NewTabParams { url: "data:text/html,Second Tab
".to_string() },
&mut context,
)
.expect("Failed to execute new_tab tool");
assert!(result.success, "New tab creation should succeed");
std::thread::sleep(std::time::Duration::from_millis(500));
// List tabs to verify count increased by 1
let tab_list_tool = TabListTool::default();
let mut context = ToolContext::new(&session);
let result = tab_list_tool.execute_typed(TabListParams {}, &mut context).expect("Failed to execute tab_list tool");
assert!(result.success);
let data = result.data.unwrap();
let count = data["count"].as_u64().expect("No count field");
info!("Tab count after creating new tab: {}", count);
assert!(count >= 2, "Should have at least 2 tabs, got {}", count);
// Switch to first tab (index 0)
let switch_tab_tool = SwitchTabTool::default();
let mut context = ToolContext::new(&session);
let result = switch_tab_tool
.execute_typed(SwitchTabParams { index: 0 }, &mut context)
.expect("Failed to execute switch_tab tool");
assert!(result.success, "Switch tab should succeed");
let data = result.data.unwrap();
assert_eq!(data["index"].as_u64(), Some(0));
info!("Switched to tab: {}", serde_json::to_string_pretty(&data).unwrap());
}
#[test]
#[ignore]
fn test_switch_tab_invalid_index() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
session.navigate("data:text/html,Tab
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
// Try to switch to invalid index
let switch_tab_tool = SwitchTabTool::default();
let mut context = ToolContext::new(&session);
let result = switch_tab_tool
.execute_typed(SwitchTabParams { index: 999 }, &mut context)
.expect("Failed to execute switch_tab tool");
// Should fail gracefully
assert!(!result.success, "Should fail for invalid index");
assert!(result.error.is_some());
info!("Expected error: {}", result.error.unwrap());
}
#[test]
#[ignore]
fn test_close_tab() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
// Create two tabs
session.navigate("data:text/html,First Tab
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let new_tab_tool = NewTabTool::default();
let mut context = ToolContext::new(&session);
new_tab_tool
.execute_typed(
NewTabParams { url: "data:text/html,Second Tab
".to_string() },
&mut context,
)
.expect("Failed to create new tab");
std::thread::sleep(std::time::Duration::from_millis(500));
// Verify we have at least 2 tabs
let tab_list_tool = TabListTool::default();
let mut context = ToolContext::new(&session);
let result = tab_list_tool.execute_typed(TabListParams {}, &mut context).expect("Failed to execute tab_list tool");
let count_before = result.data.unwrap()["count"].as_u64().unwrap();
info!("Tab count before closing: {}", count_before);
assert!(count_before >= 2, "Should have at least 2 tabs before closing, got {}", count_before);
// Close the active tab (second tab)
let close_tab_tool = CloseTabTool::default();
let mut context = ToolContext::new(&session);
let result =
close_tab_tool.execute_typed(CloseTabParams {}, &mut context).expect("Failed to execute close_tab tool");
assert!(result.success, "Close tab should succeed");
info!("Closed tab: {}", serde_json::to_string_pretty(&result.data.unwrap()).unwrap());
std::thread::sleep(std::time::Duration::from_millis(500));
// Verify we now have one less tab
let mut context = ToolContext::new(&session);
let result = tab_list_tool.execute_typed(TabListParams {}, &mut context).expect("Failed to execute tab_list tool");
let count_after = result.data.unwrap()["count"].as_u64().unwrap();
info!("Tab count after closing: {}", count_after);
assert_eq!(count_after, count_before - 1, "Should have one less tab after closing");
}
#[test]
#[ignore]
fn test_tab_workflow() {
// Test a complete workflow: create multiple tabs, switch between them, list them, and close one
let session = BrowserSession::launch(LaunchOptions::new().headless(true)).expect("Failed to launch browser");
// Start with first tab
session.navigate("data:text/html,Tab 1
").expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(300));
// Create second tab
let new_tab_tool = NewTabTool::default();
let mut context = ToolContext::new(&session);
new_tab_tool
.execute_typed(
NewTabParams { url: "data:text/html,Tab 2
".to_string() },
&mut context,
)
.expect("Failed to create tab 2");
std::thread::sleep(std::time::Duration::from_millis(300));
// Create third tab
let mut context = ToolContext::new(&session);
new_tab_tool
.execute_typed(
NewTabParams { url: "data:text/html,Tab 3
".to_string() },
&mut context,
)
.expect("Failed to create tab 3");
std::thread::sleep(std::time::Duration::from_millis(300));
// List all tabs
let tab_list_tool = TabListTool::default();
let mut context = ToolContext::new(&session);
let result = tab_list_tool.execute_typed(TabListParams {}, &mut context).expect("Failed to list tabs");
let count = result.data.as_ref().unwrap()["count"].as_u64().unwrap();
info!("Total tabs: {}", count);
assert!(count >= 3, "Should have at least 3 tabs, got {}", count);
info!("All tabs: {}", result.data.unwrap()["summary"].as_str().unwrap());
// Switch to second tab (index 1)
let switch_tab_tool = SwitchTabTool::default();
let mut context = ToolContext::new(&session);
let result =
switch_tab_tool.execute_typed(SwitchTabParams { index: 1 }, &mut context).expect("Failed to switch to tab 1");
assert!(result.success);
assert_eq!(result.data.unwrap()["index"].as_u64(), Some(1));
std::thread::sleep(std::time::Duration::from_millis(300));
// Close the current tab (tab 2, index 1)
let close_tab_tool = CloseTabTool::default();
let mut context = ToolContext::new(&session);
let result = close_tab_tool.execute_typed(CloseTabParams {}, &mut context).expect("Failed to close tab");
assert!(result.success);
info!("Closed: {}", result.data.unwrap()["message"].as_str().unwrap());
std::thread::sleep(std::time::Duration::from_millis(300));
// List tabs again to verify we have 2 tabs left
let mut context = ToolContext::new(&session);
let result = tab_list_tool.execute_typed(TabListParams {}, &mut context).expect("Failed to list tabs");
let final_count = result.data.unwrap()["count"].as_u64().unwrap();
info!("Final tab count: {}", final_count);
assert_eq!(final_count, count - 1, "Should have one less tab after closing");
}