use std::io::Write;
use std::process::{Command, Stdio};
fn oxibrowser() -> String {
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
format!("{}/../../target/release/oxibrowser", manifest_dir)
}
#[test]
#[ignore]
fn test_fetch_markdown() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert!(resp["data"]["markdown"].as_str().unwrap().contains("Example Domain"));
assert_eq!(resp["data"]["status"], 200);
assert!(resp["meta"]["elapsed_ms"].as_u64().unwrap() > 0);
}
#[test]
#[ignore]
fn test_fetch_text() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--format", "text"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Example Domain"));
assert!(stdout.contains("documentation"));
}
#[test]
#[ignore]
fn test_fetch_fields() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--fields", "url,title,status", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
let data = resp["data"].as_object().unwrap();
assert!(data.contains_key("url"));
assert!(data.contains_key("title"));
assert!(data.contains_key("status"));
assert!(!data.contains_key("markdown")); }
#[test]
#[ignore]
fn test_fetch_max_bytes() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--max-bytes", "50", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert_eq!(resp["data"]["truncated"], true);
assert!(resp["data"]["total_bytes"].as_u64().unwrap() > 50);
assert_eq!(resp["data"]["returned_bytes"], 50);
}
#[test]
#[ignore]
fn test_fetch_summary() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--summary", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert!(resp["data"]["title"].as_str().unwrap().contains("Example"));
assert!(resp["data"]["links_count"].as_u64().unwrap() > 0);
}
#[test]
#[ignore]
fn test_fetch_eval() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--eval", "document.title", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert_eq!(resp["data"]["value"], "Example Domain");
}
#[test]
#[ignore]
fn test_extract_links() {
let output = Command::new(oxibrowser())
.args(["extract", "https://example.com", "--links", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
let links = resp["data"]["links"].as_array().unwrap();
assert!(!links.is_empty());
}
#[test]
#[ignore]
fn test_extract_selector() {
let output = Command::new(oxibrowser())
.args(["extract", "https://example.com", "--selector", "a", "--attrs", "text,href", "--json"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
let m = resp["data"]["match"].as_object().unwrap();
assert!(m.contains_key("text"));
assert!(m.contains_key("href"));
assert!(m["href"].as_str().unwrap().contains("iana.org"));
}
#[test]
fn test_error_invalid_url() {
let output = Command::new(oxibrowser())
.args(["fetch", "ftp://evil.com", "--json"])
.output()
.expect("failed to run oxibrowser");
assert_eq!(output.status.code(), Some(2));
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], false);
assert_eq!(resp["error_code"], "INVALID_URL");
}
#[test]
fn test_error_bad_selector() {
let output = Command::new(oxibrowser())
.args(["fetch", "https://example.com", "--click", "div\x01", "--json"])
.output()
.expect("failed to run oxibrowser");
assert_eq!(output.status.code(), Some(2));
}
#[test]
fn test_error_no_args() {
let output = Command::new(oxibrowser())
.args(["fetch"])
.output()
.expect("failed to run oxibrowser");
assert_ne!(output.status.code(), Some(0));
}
#[test]
#[ignore]
fn test_session_basic() {
let mut child = Command::new(oxibrowser())
.args(["session"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("failed to spawn oxibrowser session");
let stdin = child.stdin.as_mut().unwrap();
writeln!(stdin, "new").unwrap();
writeln!(stdin, "goto t1 https://example.com").unwrap();
writeln!(stdin, "content t1 --format markdown --max-bytes 200").unwrap();
writeln!(stdin, "list").unwrap();
writeln!(stdin, "close t1").unwrap();
writeln!(stdin, "exit").unwrap();
let output = child.wait_with_output().expect("wait failed");
let stdout = String::from_utf8_lossy(&output.stdout);
let lines: Vec<&str> = stdout.lines().filter(|l| !l.is_empty()).collect();
assert!(lines.len() >= 5, "expected at least 5 output lines, got {}", lines.len());
let resp: serde_json::Value = serde_json::from_str(lines[0]).expect("new JSON");
assert_eq!(resp["ok"], true);
assert_eq!(resp["data"]["tab_id"], "t1");
let resp: serde_json::Value = serde_json::from_str(lines[1]).expect("goto JSON");
assert_eq!(resp["ok"], true);
assert_eq!(resp["data"]["status"], 200);
let resp: serde_json::Value = serde_json::from_str(lines[2]).expect("content JSON");
assert_eq!(resp["ok"], true);
assert!(resp["data"]["markdown"].as_str().unwrap_or("").contains("Example Domain"));
let resp: serde_json::Value = serde_json::from_str(lines[3]).expect("list JSON");
assert_eq!(resp["ok"], true);
assert!(resp["data"]["tabs"].as_array().unwrap().is_empty()); }
#[test]
#[ignore]
fn test_session_tab_not_found() {
let mut child = Command::new(oxibrowser())
.args(["session"])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::null())
.spawn()
.expect("failed to spawn oxibrowser session");
let stdin = child.stdin.as_mut().unwrap();
writeln!(stdin, "goto t99 https://example.com").unwrap();
writeln!(stdin, "exit").unwrap();
let output = child.wait_with_output().expect("wait failed");
let stdout = String::from_utf8_lossy(&output.stdout);
let lines: Vec<&str> = stdout.lines().filter(|l| !l.is_empty()).collect();
let resp: serde_json::Value = serde_json::from_str(lines[0]).expect("JSON");
assert_eq!(resp["ok"], false);
assert_eq!(resp["error_code"], "TAB_NOT_FOUND");
}
#[test]
#[ignore]
fn test_run_simple_script() {
let script = r#"
name: test
steps:
- step_type: goto
data:
goto: https://example.com
- step_type: content
data:
format: markdown
"#;
let dir = std::env::temp_dir().join("oxibrowser-test-run.yaml");
std::fs::write(&dir, script).unwrap();
let output = Command::new(oxibrowser())
.args(["run", dir.to_str().unwrap()])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert_eq!(resp["data"]["success"], true);
assert!(resp["meta"]["elapsed_ms"].as_u64().unwrap() > 0);
}
#[test]
fn test_describe_compact() {
let output = Command::new(oxibrowser())
.args(["describe", "--compact"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
let resp: serde_json::Value = serde_json::from_str(&stdout).expect("valid JSON");
assert_eq!(resp["ok"], true);
assert!(resp["data"].as_object().unwrap().contains_key("fetch"));
assert!(resp["data"].as_object().unwrap().contains_key("session"));
}
#[test]
fn test_skill() {
let output = Command::new(oxibrowser())
.args(["skill"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("OxiBrowser Agent Skills"));
assert!(stdout.contains("session"));
}
#[test]
fn test_version() {
let output = Command::new(oxibrowser())
.args(["version"])
.output()
.expect("failed to run oxibrowser");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("oxibrowser"));
assert!(stdout.contains("0."));
}