mirror of
https://github.com/hanzoai/mcp.git
synced 2026-10-29 02:55:49 +00:00
test_shell_tools and test_think_tools have not built since the shell->exec
consolidation, so `cargo test` was red and 46 tests were silently not running.
Nothing here is a new assertion — each change follows the tool's live contract,
read off the published 1.1.22 binary rather than guessed:
shell ShellTool -> ExecTool, ProcToolArgs -> ExecToolArgs. Pure rename;
all 16 pass untouched.
think ThinkTool::execute returns Value, not String, and HIP-0300 moved the
payload under "data". Help reports the tool as "tool", not "name".
Tests whose subject no longer exists are deleted, not rewritten to pass:
critic/review with focus, code_snippets, file_paths and work_description (11);
the timestamp and examples keys (2); action-less auto-detect, which now falls
through to help (1).
browser: playwright_available -> driver_running, its successor since the tool
moved to a CDP driver. That file compiled, so this one was failing, not skipped.
351 pass, 0 fail: lib 223, browser 28, fs 27, search 28, memory 22, shell 16,
think 5, research 2. tests/ is excluded from the package, so 1.1.22's contents
are unchanged and no version bump is warranted.
Co-authored-by: Hanzo Dev <[email protected]>
629 lines
16 KiB
Rust
629 lines
16 KiB
Rust
//! Browser Tools Tests - 1:1 parity with Python browser tests
|
|
//!
|
|
//! Tests for browser tool covering:
|
|
//! - Tool properties and metadata
|
|
//! - Status action
|
|
//! - Help action
|
|
//! - Action parsing
|
|
//! - Navigate action (requires Playwright)
|
|
//! - Click/Type/Fill actions
|
|
//! - Screenshot action
|
|
//! - Evaluate action
|
|
|
|
use hanzo_mcp::tools::{BrowserTool, BrowserToolArgs};
|
|
|
|
/// Test browser tool properties
|
|
#[test]
|
|
fn test_browser_tool_properties() {
|
|
let tool = BrowserTool::new();
|
|
// Tool exists and is properly initialized
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test browser help action
|
|
#[tokio::test]
|
|
async fn test_browser_help_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "help".to_string(),
|
|
..Default::default()
|
|
};
|
|
|
|
let result = tool.execute(args).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
let json: serde_json::Value = serde_json::from_str(&output).unwrap();
|
|
|
|
assert!(json.get("categories").is_some());
|
|
assert!(json.get("name").is_some());
|
|
assert_eq!(json["name"], "browser");
|
|
assert!(json.get("action_count").is_some());
|
|
assert!(json.get("devices").is_some());
|
|
}
|
|
|
|
/// Test browser status action
|
|
#[tokio::test]
|
|
async fn test_browser_status_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "status".to_string(),
|
|
..Default::default()
|
|
};
|
|
|
|
let result = tool.execute(args).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
let json: serde_json::Value = serde_json::from_str(&output).unwrap();
|
|
|
|
assert!(json.get("driver_running").is_some()); // CDP driver replaced Playwright
|
|
assert!(json.get("headless").is_some());
|
|
assert!(json.get("cdp_port").is_some());
|
|
assert!(json.get("categories").is_some());
|
|
}
|
|
|
|
/// Test browser default action (status)
|
|
#[tokio::test]
|
|
async fn test_browser_default_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
..Default::default()
|
|
};
|
|
|
|
let result = tool.execute(args).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
let json: serde_json::Value = serde_json::from_str(&output).unwrap();
|
|
|
|
// Default action should be status
|
|
assert!(json.get("headless").is_some() || json.get("categories").is_some());
|
|
}
|
|
|
|
/// Test all action categories in help
|
|
#[tokio::test]
|
|
async fn test_browser_help_categories() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "help".to_string(),
|
|
..Default::default()
|
|
};
|
|
|
|
let result = tool.execute(args).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
let json: serde_json::Value = serde_json::from_str(&output).unwrap();
|
|
|
|
let categories = json["categories"].as_object().unwrap();
|
|
|
|
// Should have all major categories
|
|
assert!(categories.get("navigation").is_some());
|
|
assert!(categories.get("input").is_some());
|
|
assert!(categories.get("mouse").is_some());
|
|
assert!(categories.get("locators").is_some());
|
|
assert!(categories.get("screen").is_some());
|
|
assert!(categories.get("javascript").is_some());
|
|
assert!(categories.get("browser").is_some());
|
|
}
|
|
|
|
/// Test navigation action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_navigate_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// Test "goto" alias
|
|
let args = BrowserToolArgs {
|
|
action: "goto".to_string(),
|
|
url: Some("https://example.com".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
// This will fail without Playwright, but should parse correctly
|
|
let result = tool.execute(args).await;
|
|
// Just verify it doesn't panic on action parsing
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test click action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_click_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "click".to_string(),
|
|
selector: Some("#submit-button".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
// Will fail without browser, but should parse action correctly
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test type action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_type_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "type".to_string(),
|
|
selector: Some("#input-field".to_string()),
|
|
text: Some("Hello World".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test fill action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_fill_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "fill".to_string(),
|
|
selector: Some("#username".to_string()),
|
|
text: Some("testuser".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test screenshot action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_screenshot_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "screenshot".to_string(),
|
|
full_page: Some(true),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test evaluate action parsing
|
|
#[tokio::test]
|
|
async fn test_browser_evaluate_action_parsing() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "evaluate".to_string(),
|
|
code: Some("return document.title".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test action aliases
|
|
#[tokio::test]
|
|
async fn test_browser_action_aliases() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// Test navigate aliases
|
|
for alias in &["navigate", "goto", "go"] {
|
|
let args = BrowserToolArgs {
|
|
action: alias.to_string(),
|
|
url: Some("https://test.com".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
}
|
|
|
|
// Test reload aliases
|
|
for alias in &["reload", "refresh"] {
|
|
let args = BrowserToolArgs {
|
|
action: alias.to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
}
|
|
|
|
// Test screenshot aliases
|
|
for alias in &["screenshot", "capture"] {
|
|
let args = BrowserToolArgs {
|
|
action: alias.to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
}
|
|
|
|
// Test evaluate aliases
|
|
for alias in &["evaluate", "eval", "js"] {
|
|
let args = BrowserToolArgs {
|
|
action: alias.to_string(),
|
|
code: Some("1+1".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
}
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test selector alias (ref)
|
|
#[tokio::test]
|
|
async fn test_browser_selector_alias() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// Test using ref_ instead of selector
|
|
let args = BrowserToolArgs {
|
|
action: "click".to_string(),
|
|
ref_: Some("#button".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test viewport action
|
|
#[tokio::test]
|
|
async fn test_browser_viewport_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "viewport".to_string(),
|
|
width: Some(1920),
|
|
height: Some(1080),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test device emulation
|
|
#[tokio::test]
|
|
async fn test_browser_device_emulation() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "emulate".to_string(),
|
|
device: Some("iphone_14".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test geolocation action
|
|
#[tokio::test]
|
|
async fn test_browser_geolocation() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "geolocation".to_string(),
|
|
latitude: Some(37.7749),
|
|
longitude: Some(-122.4194),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test wait action
|
|
#[tokio::test]
|
|
async fn test_browser_wait_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "wait".to_string(),
|
|
timeout: Some(1000),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test locator actions
|
|
#[tokio::test]
|
|
async fn test_browser_locator_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// get_by_role
|
|
let args = BrowserToolArgs {
|
|
action: "get_by_role".to_string(),
|
|
role: Some("button".to_string()),
|
|
name: Some("Submit".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// get_by_text
|
|
let args = BrowserToolArgs {
|
|
action: "get_by_text".to_string(),
|
|
text: Some("Click me".to_string()),
|
|
exact: Some(true),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// get_by_label
|
|
let args = BrowserToolArgs {
|
|
action: "get_by_label".to_string(),
|
|
text: Some("Email".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test assertion actions
|
|
#[tokio::test]
|
|
async fn test_browser_assertion_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// expect_visible
|
|
let args = BrowserToolArgs {
|
|
action: "expect_visible".to_string(),
|
|
selector: Some("#element".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// expect_text
|
|
let args = BrowserToolArgs {
|
|
action: "expect_text".to_string(),
|
|
selector: Some("#title".to_string()),
|
|
expected: Some("Welcome".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// expect_url
|
|
let args = BrowserToolArgs {
|
|
action: "expect_url".to_string(),
|
|
expected: Some("https://example.com".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test state check actions
|
|
#[tokio::test]
|
|
async fn test_browser_state_check_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
for action in &[
|
|
"is_visible",
|
|
"is_enabled",
|
|
"is_checked",
|
|
"is_hidden",
|
|
"is_editable",
|
|
] {
|
|
let args = BrowserToolArgs {
|
|
action: action.to_string(),
|
|
selector: Some("#element".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
}
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test mouse actions
|
|
#[tokio::test]
|
|
async fn test_browser_mouse_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// hover
|
|
let args = BrowserToolArgs {
|
|
action: "hover".to_string(),
|
|
selector: Some("#menu".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// drag
|
|
let args = BrowserToolArgs {
|
|
action: "drag".to_string(),
|
|
selector: Some("#source".to_string()),
|
|
target_selector: Some("#target".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// scroll
|
|
let args = BrowserToolArgs {
|
|
action: "scroll".to_string(),
|
|
delta_y: Some(500),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test touch actions
|
|
#[tokio::test]
|
|
async fn test_browser_touch_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// tap
|
|
let args = BrowserToolArgs {
|
|
action: "tap".to_string(),
|
|
selector: Some("#button".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// swipe
|
|
let args = BrowserToolArgs {
|
|
action: "swipe".to_string(),
|
|
direction: Some("left".to_string()),
|
|
distance: Some(200),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// pinch
|
|
let args = BrowserToolArgs {
|
|
action: "pinch".to_string(),
|
|
scale: Some(0.5),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test dialog handling
|
|
#[tokio::test]
|
|
async fn test_browser_dialog_action() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "dialog".to_string(),
|
|
accept: true,
|
|
prompt_text: Some("Yes".to_string()),
|
|
..Default::default()
|
|
};
|
|
|
|
let _ = tool.execute(args).await;
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test tab management
|
|
#[tokio::test]
|
|
async fn test_browser_tab_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// new_tab
|
|
let args = BrowserToolArgs {
|
|
action: "new_tab".to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// tabs
|
|
let args = BrowserToolArgs {
|
|
action: "tabs".to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// close_tab
|
|
let args = BrowserToolArgs {
|
|
action: "close_tab".to_string(),
|
|
tab_index: Some(0),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test network actions
|
|
#[tokio::test]
|
|
async fn test_browser_network_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// route
|
|
let args = BrowserToolArgs {
|
|
action: "route".to_string(),
|
|
pattern: Some("**/api/**".to_string()),
|
|
block: true,
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// unroute
|
|
let args = BrowserToolArgs {
|
|
action: "unroute".to_string(),
|
|
pattern: Some("**/api/**".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test storage actions
|
|
#[tokio::test]
|
|
async fn test_browser_storage_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// cookies
|
|
let args = BrowserToolArgs {
|
|
action: "cookies".to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// clear_cookies
|
|
let args = BrowserToolArgs {
|
|
action: "clear_cookies".to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// storage
|
|
let args = BrowserToolArgs {
|
|
action: "storage".to_string(),
|
|
storage_type: Some("local".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test debug actions
|
|
#[tokio::test]
|
|
async fn test_browser_debug_actions() {
|
|
let tool = BrowserTool::new();
|
|
|
|
// console
|
|
let args = BrowserToolArgs {
|
|
action: "console".to_string(),
|
|
level: Some("error".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// errors
|
|
let args = BrowserToolArgs {
|
|
action: "errors".to_string(),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
// highlight
|
|
let args = BrowserToolArgs {
|
|
action: "highlight".to_string(),
|
|
selector: Some("#element".to_string()),
|
|
..Default::default()
|
|
};
|
|
let _ = tool.execute(args).await;
|
|
|
|
assert!(true);
|
|
}
|
|
|
|
/// Test devices in help
|
|
#[tokio::test]
|
|
async fn test_browser_devices_list() {
|
|
let tool = BrowserTool::new();
|
|
let args = BrowserToolArgs {
|
|
action: "help".to_string(),
|
|
..Default::default()
|
|
};
|
|
|
|
let result = tool.execute(args).await;
|
|
assert!(result.is_ok());
|
|
|
|
let output = result.unwrap();
|
|
let json: serde_json::Value = serde_json::from_str(&output).unwrap();
|
|
|
|
let devices = json["devices"].as_array().unwrap();
|
|
assert!(devices.iter().any(|d| d == "mobile"));
|
|
assert!(devices.iter().any(|d| d == "tablet"));
|
|
assert!(devices.iter().any(|d| d == "iphone_14"));
|
|
}
|