use browser_use::tools::{
HoverParams, ScrollParams, SelectParams, Tool, ToolContext, hover::HoverTool,
scroll::ScrollTool, select::SelectTool,
};
use browser_use::{BrowserSession, LaunchOptions};
use log::info;
#[test]
#[ignore] fn test_select_tool() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true))
.expect("Failed to launch browser");
let html = r#"
<!DOCTYPE html>
<html>
<body>
<select id="country">
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
</select>
<div id="result"></div>
<script>
document.getElementById('country').addEventListener('change', function(e) {
document.getElementById('result').textContent = 'Selected: ' + e.target.value;
});
</script>
</body>
</html>
"#;
let data_url = format!("data:text/html,{}", html);
session.navigate(&data_url).expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let tool = SelectTool::default();
let mut context = ToolContext::new(&session);
let result = tool
.execute_typed(
SelectParams {
selector: Some("#country".to_string()),
index: None,
value: "uk".to_string(),
},
&mut context,
)
.expect("Failed to execute select tool");
assert!(result.success, "Tool execution should succeed");
assert!(result.data.is_some());
let data = result.data.unwrap();
info!(
"Select result: {}",
serde_json::to_string_pretty(&data).unwrap()
);
assert_eq!(data["value"].as_str(), Some("uk"));
assert_eq!(data["selectedText"].as_str(), Some("United Kingdom"));
}
#[test]
#[ignore]
fn test_hover_tool() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true))
.expect("Failed to launch browser");
let html = r#"
<!DOCTYPE html>
<html>
<body>
<button id="hover-btn">Hover Me</button>
<div id="result"></div>
<script>
document.getElementById('hover-btn').addEventListener('mouseover', function() {
document.getElementById('result').textContent = 'Hovered!';
});
</script>
</body>
</html>
"#;
let data_url = format!("data:text/html,{}", html);
session.navigate(&data_url).expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let tool = HoverTool::default();
let mut context = ToolContext::new(&session);
let result = tool
.execute_typed(
HoverParams {
selector: Some("#hover-btn".to_string()),
index: None,
},
&mut context,
)
.expect("Failed to execute hover tool");
assert!(result.success, "Tool execution should succeed");
assert!(result.data.is_some());
let data = result.data.unwrap();
info!(
"Hover result: {}",
serde_json::to_string_pretty(&data).unwrap()
);
assert_eq!(data["selector"].as_str(), Some("#hover-btn"));
}
#[test]
#[ignore]
fn test_scroll_tool_with_amount() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true))
.expect("Failed to launch browser");
let html = r#"
<!DOCTYPE html>
<html>
<body style="height: 3000px;">
<h1>Top of page</h1>
<div style="margin-top: 1000px;">Middle</div>
<div style="margin-top: 1000px;">Bottom</div>
</body>
</html>
"#;
let data_url = format!("data:text/html,{}", html);
session.navigate(&data_url).expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let tool = ScrollTool::default();
let mut context = ToolContext::new(&session);
let result = tool
.execute_typed(ScrollParams { amount: Some(500) }, &mut context)
.expect("Failed to execute scroll tool");
assert!(result.success, "Tool execution should succeed");
assert!(result.data.is_some());
let data = result.data.unwrap();
info!(
"Scroll result: {}",
serde_json::to_string_pretty(&data).unwrap()
);
let scrolled = data["scrolled"].as_i64();
assert!(
scrolled.is_some() && scrolled.unwrap() > 0,
"Should have scrolled"
);
}
#[test]
#[ignore]
fn test_scroll_tool_to_bottom() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true))
.expect("Failed to launch browser");
let html = r#"
<!DOCTYPE html>
<html>
<body style="height: 2000px;">
<h1>Top of page</h1>
<div style="margin-top: 1800px;">Bottom</div>
</body>
</html>
"#;
let data_url = format!("data:text/html,{}", html);
session.navigate(&data_url).expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let tool = ScrollTool::default();
let mut context = ToolContext::new(&session);
for _ in 0..10 {
let result = tool
.execute_typed(ScrollParams { amount: None }, &mut context)
.expect("Failed to execute scroll tool");
assert!(result.success);
let data = result.data.as_ref().unwrap();
let is_at_bottom = data["isAtBottom"].as_bool().unwrap_or(false);
info!(
"Scroll iteration: scrolled={}, isAtBottom={}",
data["scrolled"], is_at_bottom
);
if is_at_bottom {
info!("Reached bottom of page");
break;
}
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
#[test]
#[ignore]
fn test_select_with_index() {
let session = BrowserSession::launch(LaunchOptions::new().headless(true))
.expect("Failed to launch browser");
let html = r#"
<!DOCTYPE html>
<html>
<body>
<select id="color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
</body>
</html>
"#;
let data_url = format!("data:text/html,{}", html);
session.navigate(&data_url).expect("Failed to navigate");
std::thread::sleep(std::time::Duration::from_millis(500));
let _dom = session.extract_dom().expect("Failed to extract DOM");
let tool = SelectTool::default();
let mut context = ToolContext::new(&session);
let result = tool.execute_typed(
SelectParams {
selector: None,
index: Some(0),
value: "green".to_string(),
},
&mut context,
);
if let Ok(result) = result {
info!(
"Select with index result: {}",
serde_json::to_string_pretty(&result.data.unwrap()).unwrap()
);
} else {
info!("Select with index failed (may be expected if select not indexed)");
}
}