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"); }