use browsing::tools::handlers::FileHandler;
use browsing::tools::handlers::Handler;
use browsing::tools::views::{ActionContext, ActionParams};
use std::collections::HashMap;
#[tokio::test]
async fn test_write_file_creates_file_with_content() {
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("test_write.txt");
let file_path_str = file_path.to_str().unwrap();
let mut params = HashMap::new();
params.insert("path".to_string(), serde_json::json!(file_path_str));
params.insert("content".to_string(), serde_json::json!("Hello, file operations!"));
let action_params = ActionParams::new(¶ms).with_action_type("write_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await.unwrap();
assert!(result.extracted_content.is_some());
assert!(result
.extracted_content
.unwrap()
.contains("Successfully wrote"));
let read_content = std::fs::read_to_string(&file_path).unwrap();
assert_eq!(read_content, "Hello, file operations!");
}
#[tokio::test]
async fn test_read_file_reads_existing_file() {
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("test_read.txt");
let file_path_str = file_path.to_str().unwrap();
std::fs::write(&file_path, "Pre-existing content").unwrap();
let mut params = HashMap::new();
params.insert("path".to_string(), serde_json::json!(file_path_str));
let action_params = ActionParams::new(¶ms).with_action_type("read_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await.unwrap();
assert_eq!(
result.extracted_content,
Some("Pre-existing content".to_string())
);
}
#[tokio::test]
async fn test_write_file_rejects_path_traversal() {
let mut params = HashMap::new();
params.insert("path".to_string(), serde_json::json!("../etc/passwd"));
params.insert("content".to_string(), serde_json::json!("malicious"));
let action_params = ActionParams::new(¶ms).with_action_type("write_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await;
assert!(result.is_err());
let err_msg = format!("{}", result.unwrap_err());
assert!(err_msg.contains("path traversal"));
}
#[tokio::test]
async fn test_read_file_rejects_nonexistent_file() {
let mut params = HashMap::new();
params.insert(
"path".to_string(),
serde_json::json!("/tmp/nonexistent_file_12345.txt"),
);
let action_params = ActionParams::new(¶ms).with_action_type("read_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await;
assert!(result.is_err());
let err_msg = format!("{}", result.unwrap_err());
assert!(err_msg.contains("does not exist"));
}
#[tokio::test]
async fn test_write_file_creates_parent_directories() {
let temp_dir = tempfile::tempdir().unwrap();
let nested_path = temp_dir.path().join("a/b/c/nested.txt");
let nested_path_str = nested_path.to_str().unwrap();
let mut params = HashMap::new();
params.insert("path".to_string(), serde_json::json!(nested_path_str));
params.insert("content".to_string(), serde_json::json!("nested content"));
let action_params = ActionParams::new(¶ms).with_action_type("write_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await;
assert!(result.is_ok());
assert!(nested_path.exists());
let content = std::fs::read_to_string(&nested_path).unwrap();
assert_eq!(content, "nested content");
}
#[tokio::test]
async fn test_read_file_rejects_directory() {
let temp_dir = tempfile::tempdir().unwrap();
let dir_path = temp_dir.path().to_str().unwrap();
let mut params = HashMap::new();
params.insert("path".to_string(), serde_json::json!(dir_path));
let action_params = ActionParams::new(¶ms).with_action_type("read_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await;
assert!(result.is_err());
let err_msg = format!("{}", result.unwrap_err());
assert!(err_msg.contains("not a file"));
}
#[tokio::test]
async fn test_replace_file_replaces_text() {
let temp_dir = tempfile::tempdir().unwrap();
let file_path = temp_dir.path().join("replace_test.txt");
std::fs::write(&file_path, "Hello old world old").unwrap();
let mut params = HashMap::new();
params.insert(
"path".to_string(),
serde_json::json!(file_path.to_str().unwrap()),
);
params.insert("old_text".to_string(), serde_json::json!("old"));
params.insert("new_text".to_string(), serde_json::json!("new"));
let action_params =
ActionParams::new(¶ms).with_action_type("replace_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await.unwrap();
assert!(result.extracted_content.unwrap().contains("2 occurrence"));
let content = std::fs::read_to_string(&file_path).unwrap();
assert_eq!(content, "Hello new world new");
}
#[tokio::test]
async fn test_replace_file_rejects_nonexistent_file() {
let mut params = HashMap::new();
params.insert(
"path".to_string(),
serde_json::json!("/tmp/nonexistent_replace.txt"),
);
params.insert("old_text".to_string(), serde_json::json!("foo"));
params.insert("new_text".to_string(), serde_json::json!("bar"));
let action_params =
ActionParams::new(¶ms).with_action_type("replace_file".to_string());
let mut context = ActionContext {
browser: &mut browsing::browser::Browser::new(
browsing::browser::BrowserProfile::default(),
),
selector_map: None,
};
let result = FileHandler.handle(&action_params, &mut context).await;
assert!(result.is_err());
let err_msg = format!("{}", result.unwrap_err());
assert!(err_msg.contains("does not exist"));
}