#![cfg(feature = "integration")]
mod common;
use std::time::Duration;
use viewpoint_core::Browser;
use common::init_tracing;
#[tokio::test]
async fn test_browser_launch_and_close() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.timeout(Duration::from_secs(30))
.launch()
.await
.expect("Failed to launch browser");
assert!(browser.is_owned());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_browser_context_creation() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let context = browser
.new_context()
.await
.expect("Failed to create context");
assert!(!context.id().is_empty());
assert!(!context.is_closed());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_page_creation() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let context = browser
.new_context()
.await
.expect("Failed to create context");
let page = context.new_page().await.expect("Failed to create page");
assert!(!page.target_id().is_empty());
assert!(!page.session_id().is_empty());
assert!(!page.frame_id().is_empty());
assert!(!page.is_closed());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_page_close() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let context = browser
.new_context()
.await
.expect("Failed to create context");
let mut page = context.new_page().await.expect("Failed to create page");
assert!(!page.is_closed());
page.close().await.expect("Failed to close page");
assert!(page.is_closed());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_context_close() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let mut context = browser
.new_context()
.await
.expect("Failed to create context");
let _page1 = context.new_page().await.expect("Failed to create page 1");
let _page2 = context.new_page().await.expect("Failed to create page 2");
assert!(!context.is_closed());
context.close().await.expect("Failed to close context");
assert!(context.is_closed());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_browser_contexts_launched() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let _context1 = browser
.new_context()
.await
.expect("Failed to create context 1");
let _context2 = browser
.new_context()
.await
.expect("Failed to create context 2");
let contexts = browser.contexts().await.expect("Failed to get contexts");
assert!(
contexts.len() >= 3,
"Expected at least 3 contexts, got {}",
contexts.len()
);
let has_default = contexts.iter().any(|c| c.is_default());
assert!(has_default, "Should have a default context");
let _owned_count = contexts.iter().filter(|c| c.is_owned()).count();
let non_owned_count = contexts.iter().filter(|c| !c.is_owned()).count();
assert!(
non_owned_count >= 1,
"Should have at least 1 non-owned context (default)"
);
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_context_ownership_on_close() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let mut owned_context = browser
.new_context()
.await
.expect("Failed to create context");
assert!(
owned_context.is_owned(),
"Context created with new_context() should be owned"
);
let contexts = browser.contexts().await.expect("Failed to get contexts");
let default_context = contexts.into_iter().find(|c| c.is_default());
assert!(default_context.is_some(), "Should find default context");
let mut default_ctx = default_context.unwrap();
assert!(
!default_ctx.is_owned(),
"Default context from contexts() should not be owned"
);
default_ctx
.close()
.await
.expect("Closing non-owned context should succeed");
owned_context
.close()
.await
.expect("Closing owned context should succeed");
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_default_context_pages() {
init_tracing();
let browser = Browser::launch()
.headless(true)
.launch()
.await
.expect("Failed to launch browser");
let contexts = browser.contexts().await.expect("Failed to get contexts");
let default_context = contexts.into_iter().find(|c| c.is_default());
assert!(default_context.is_some(), "Should find default context");
let default_ctx = default_context.unwrap();
let pages = default_ctx.pages().await.expect("Failed to get pages");
tracing::info!("Default context has {} pages", pages.len());
browser.close().await.expect("Failed to close browser");
}
#[tokio::test]
async fn test_connect_over_cdp_invalid_url() {
init_tracing();
let result = Browser::connect_over_cdp("ftp://localhost:9222")
.timeout(Duration::from_secs(5))
.connect()
.await;
assert!(result.is_err(), "Should fail with invalid URL scheme");
let err = result.unwrap_err();
tracing::info!("Got expected error: {}", err);
}
#[tokio::test]
async fn test_connect_over_cdp_unreachable() {
init_tracing();
let result = Browser::connect_over_cdp("http://127.0.0.1:59999")
.timeout(Duration::from_secs(2))
.connect()
.await;
assert!(result.is_err(), "Should fail with unreachable endpoint");
let err = result.unwrap_err();
tracing::info!("Got expected error: {}", err);
}
#[tokio::test]
async fn test_connect_over_cdp_timeout() {
init_tracing();
let result = Browser::connect_over_cdp("http://10.255.255.1:9222")
.timeout(Duration::from_millis(500))
.connect()
.await;
assert!(
result.is_err(),
"Should fail with timeout or connection error"
);
let err = result.unwrap_err();
tracing::info!("Got expected error: {}", err);
}
#[tokio::test]
async fn test_user_data_dir_persistence() {
init_tracing();
let temp_dir = tempfile::tempdir().expect("Failed to create temp dir");
let user_data_path = temp_dir.path().to_path_buf();
{
let browser = Browser::launch()
.headless(true)
.user_data_dir(&user_data_path)
.timeout(Duration::from_secs(30))
.launch()
.await
.expect("Failed to launch first browser");
let context = browser
.new_context()
.await
.expect("Failed to create context");
let _page = context.new_page().await.expect("Failed to create page");
browser
.close()
.await
.expect("Failed to close first browser");
}
let entries_after_first: Vec<_> = std::fs::read_dir(&user_data_path)
.expect("Failed to read user data dir")
.collect();
tracing::info!(
"User data directory has {} entries after first session",
entries_after_first.len()
);
assert!(
!entries_after_first.is_empty(),
"Browser should create profile data in user data directory"
);
{
let browser = Browser::launch()
.headless(true)
.user_data_dir(&user_data_path)
.timeout(Duration::from_secs(30))
.launch()
.await
.expect("Failed to launch second browser with same profile");
assert!(browser.is_owned());
browser
.close()
.await
.expect("Failed to close second browser");
}
let entries_after_second: Vec<_> = std::fs::read_dir(&user_data_path)
.expect("Failed to read user data dir")
.collect();
tracing::info!(
"User data directory has {} entries after second session",
entries_after_second.len()
);
assert!(
!entries_after_second.is_empty(),
"Profile data should persist after second session"
);
}
#[tokio::test]
async fn test_user_data_dir_launch() {
init_tracing();
let temp_dir = tempfile::tempdir().expect("Failed to create temp dir");
let browser = Browser::launch()
.headless(true)
.user_data_dir(temp_dir.path())
.timeout(Duration::from_secs(30))
.launch()
.await
.expect("Failed to launch browser with user data dir");
assert!(browser.is_owned());
let entries: Vec<_> = std::fs::read_dir(temp_dir.path())
.expect("Failed to read user data dir")
.collect();
tracing::info!(
"User data directory contains {} entries after browser launch",
entries.len()
);
assert!(
!entries.is_empty(),
"Browser should create files in user data directory"
);
browser.close().await.expect("Failed to close browser");
}