use eoka::{Browser, StealthConfig};
fn chrome_available() -> bool {
eoka::stealth::patcher::find_chrome().is_ok()
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_browser_launch() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_browser_launch_visible() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let config = StealthConfig::visible();
let browser = Browser::launch_with_config(config)
.await
.expect("Failed to launch browser");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_page_navigation() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<h1>Hello</h1>")
.await
.expect("Failed to navigate");
let content = page.content().await.expect("Failed to get content");
assert!(content.contains("Hello"));
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_page_title() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<title>Test Title</title><body>Content</body>")
.await
.expect("Failed to navigate");
let title = page.title().await.expect("Failed to get title");
assert_eq!(title, "Test Title");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_page_url() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<h1>Test</h1>")
.await
.expect("Failed to navigate");
let url = page.url().await.expect("Failed to get URL");
assert!(url.starts_with("data:"));
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_screenshot() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<body style='background:red'><h1>Red</h1></body>")
.await
.expect("Failed to navigate");
let png = page.screenshot().await.expect("Failed to take screenshot");
assert!(png.len() > 100);
assert_eq!(&png[0..4], &[0x89, 0x50, 0x4E, 0x47]);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_screenshot_jpeg() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<body style='background:blue'><h1>Blue</h1></body>")
.await
.expect("Failed to navigate");
let jpeg = page
.screenshot_jpeg(80)
.await
.expect("Failed to take screenshot");
assert!(jpeg.len() > 100);
assert_eq!(&jpeg[0..2], &[0xFF, 0xD8]);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_element_finding() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<button id="btn">Click Me</button>
<input type="text" class="input" value="test">
"#,
)
.await
.expect("Failed to navigate");
let btn = page.find("#btn").await.expect("Failed to find button");
let html = btn.outer_html().await.expect("Failed to get HTML");
assert!(html.contains("Click Me"));
let input = page.find(".input").await.expect("Failed to find input");
let html = input.outer_html().await.expect("Failed to get HTML");
assert!(html.contains("type=\"text\""));
let all = page.find_all("*").await.expect("Failed to find all");
assert!(all.len() > 2);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_element_not_found() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<div>Simple</div>")
.await
.expect("Failed to navigate");
let result = page.find("#nonexistent").await;
assert!(result.is_err());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_evaluate_javascript() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
let result: i32 = page.evaluate("1 + 2").await.expect("Failed to evaluate");
assert_eq!(result, 3);
let result: String = page
.evaluate("'hello' + ' world'")
.await
.expect("Failed to evaluate");
assert_eq!(result, "hello world");
let result: Vec<i32> = page
.evaluate("[1, 2, 3]")
.await
.expect("Failed to evaluate");
assert_eq!(result, vec![1, 2, 3]);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_cookies() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("https://example.com")
.await
.expect("Failed to navigate");
page.wait(1000).await;
page.set_cookie("test_cookie", "test_value", Some("example.com"), Some("/"))
.await
.expect("Failed to set cookie");
let cookies = page.cookies().await.expect("Failed to get cookies");
let test_cookie = cookies.iter().find(|c| c.name == "test_cookie");
assert!(test_cookie.is_some());
assert_eq!(test_cookie.unwrap().value, "test_value");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_wait_for_element() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<script>
setTimeout(() => {
document.body.innerHTML = '<div id="delayed">Loaded!</div>';
}, 100);
</script>
"#,
)
.await
.expect("Failed to navigate");
let element = page
.wait_for("#delayed", 5000)
.await
.expect("Element not found");
let html = element.outer_html().await.expect("Failed to get HTML");
assert!(html.contains("Loaded!"));
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_wait_for_element_timeout() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<div>No delayed element</div>")
.await
.expect("Failed to navigate");
let result = page.wait_for("#never-exists", 500).await;
assert!(result.is_err());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_click_element() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<button id="btn" onclick="this.textContent = 'Clicked!'">Click Me</button>
"#,
)
.await
.expect("Failed to navigate");
page.click("#btn").await.expect("Failed to click");
page.wait(100).await;
let content = page.content().await.expect("Failed to get content");
assert!(content.contains("Clicked!"));
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_type_into_input() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<input type="text" id="input" value="">
"#,
)
.await
.expect("Failed to navigate");
page.type_into("#input", "Hello World")
.await
.expect("Failed to type");
let value: String = page
.evaluate("document.getElementById('input').value")
.await
.expect("Failed to evaluate");
assert_eq!(value, "Hello World");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_select_dropdown() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<select id="country">
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="de">Germany</option>
</select>
"#,
)
.await
.expect("Failed to navigate");
page.select("#country", "uk")
.await
.expect("Failed to select");
let value: String = page
.evaluate("document.getElementById('country').value")
.await
.expect("Failed to evaluate");
assert_eq!(value, "uk");
page.select_by_text("#country", "Germany")
.await
.expect("Failed to select by text");
let value: String = page
.evaluate("document.getElementById('country').value")
.await
.expect("Failed to evaluate");
assert_eq!(value, "de");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_select_invalid_option() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<select id="country">
<option value="us">United States</option>
</select>
"#,
)
.await
.expect("Failed to navigate");
let result = page.select("#country", "invalid").await;
assert!(result.is_err());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_hover() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto("data:text/html,<div id='target' style='width:100px;height:100px;background:blue'></div><script>window.hovered=false;document.getElementById('target').onmouseenter=()=>{window.hovered=true};</script>")
.await
.expect("Failed to navigate");
page.wait(200).await;
page.hover("#target").await.expect("Failed to hover");
let hovered: bool = page
.evaluate("window.hovered")
.await
.expect("Failed to evaluate");
assert!(hovered);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_press_key() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<input type="text" id="input" autofocus>
<script>
window.lastKey = '';
document.getElementById('input').addEventListener('keydown', (e) => {
window.lastKey = e.key;
});
</script>
"#,
)
.await
.expect("Failed to navigate");
page.wait(100).await;
page.press_key("Enter").await.expect("Failed to press key");
let key: String = page
.evaluate("window.lastKey")
.await
.expect("Failed to evaluate");
assert_eq!(key, "Enter");
page.press_key("Tab").await.expect("Failed to press tab");
let key: String = page
.evaluate("window.lastKey")
.await
.expect("Failed to evaluate");
assert_eq!(key, "Tab");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_upload_file() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<input type="file" id="upload">
<script>
window.filename = '';
document.getElementById('upload').addEventListener('change', (e) => {
window.filename = e.target.files[0]?.name || '';
});
</script>
"#,
)
.await
.expect("Failed to navigate");
let temp_dir = std::env::temp_dir();
let temp_file = temp_dir.join("eoka_test_upload.txt");
std::fs::write(&temp_file, "test content").expect("Failed to write temp file");
page.upload_file("#upload", temp_file.to_str().unwrap())
.await
.expect("Failed to upload file");
let filename: String = page
.evaluate("window.filename")
.await
.expect("Failed to evaluate");
assert_eq!(filename, "eoka_test_upload.txt");
std::fs::remove_file(&temp_file).ok();
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_select_multiple() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page = browser
.new_page("about:blank")
.await
.expect("Failed to create page");
page.goto(
r#"data:text/html,
<select id="tags" multiple>
<option value="rust">Rust</option>
<option value="async">Async</option>
<option value="web">Web</option>
</select>
"#,
)
.await
.expect("Failed to navigate");
page.select_multiple("#tags", &["rust", "web"])
.await
.expect("Failed to select multiple");
let selected: Vec<String> = page
.evaluate("Array.from(document.getElementById('tags').selectedOptions).map(o => o.value)")
.await
.expect("Failed to evaluate");
assert_eq!(selected, vec!["rust", "web"]);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
#[ignore = "requires Chrome"]
async fn test_multi_tab() {
if !chrome_available() {
eprintln!("Chrome not found, skipping test");
return;
}
let browser = Browser::launch().await.expect("Failed to launch browser");
let page1 = browser
.new_page("data:text/html,<title>Tab1</title>")
.await
.expect("Failed to create page 1");
let page2 = browser
.new_page("data:text/html,<title>Tab2</title>")
.await
.expect("Failed to create page 2");
assert_ne!(page1.target_id(), page2.target_id());
let tabs = browser.tabs().await.expect("Failed to list tabs");
assert!(tabs.len() >= 2);
let tab1_found = tabs.iter().any(|t| t.id == page1.target_id());
let tab2_found = tabs.iter().any(|t| t.id == page2.target_id());
assert!(tab1_found, "Tab 1 not found in tabs list");
assert!(tab2_found, "Tab 2 not found in tabs list");
browser
.activate_tab(page1.target_id())
.await
.expect("Failed to activate tab");
browser
.close_tab(page2.target_id())
.await
.expect("Failed to close tab");
let tabs = browser.tabs().await.expect("Failed to list tabs");
let tab2_still_exists = tabs.iter().any(|t| t.id == page2.target_id());
assert!(!tab2_still_exists, "Tab 2 should be closed");
browser.close().await.expect("Failed to close browser");
}