diff --git a/Cargo.toml b/Cargo.toml index 17d4602..5eec101 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,6 @@ [workspace] - members = ["toolproof"] +resolver = "2" + +[profile.dev.package.similar] +opt-level = 3 diff --git a/toolproof/Cargo.toml b/toolproof/Cargo.toml index 766b215..2d3f744 100644 --- a/toolproof/Cargo.toml +++ b/toolproof/Cargo.toml @@ -35,6 +35,3 @@ path-slash = "0.2.1" normalize-path = "0.2.1" miette = { version = "7", features = ["fancy"] } semver = "1.0.26" - -[profile.dev.package.similar] -opt-level = 3 diff --git a/toolproof/src/civilization.rs b/toolproof/src/civilization.rs index 12497fa..7d19532 100644 --- a/toolproof/src/civilization.rs +++ b/toolproof/src/civilization.rs @@ -40,11 +40,27 @@ impl<'u> Civilization<'u> { pub async fn shutdown(mut self) { self.stop_servers().await; - if let Some(BrowserWindow::Chrome(window)) = self.window { - window - .close() - .await - .expect("Failed to close browser window"); + if let Some(BrowserWindow::Chrome { + page, + context_id, + browser, + }) = self.window + { + match tokio::time::timeout(Duration::from_secs(5), async { + if let Err(e) = page.close().await { + eprintln!("[toolproof] Warning: Failed to close browser window: {e}"); + } + if let Err(e) = browser.dispose_browser_context(context_id).await { + eprintln!("[toolproof] Warning: Failed to dispose browser context: {e}"); + } + }) + .await + { + Ok(()) => {} + Err(_) => { + eprintln!("[toolproof] Warning: Timed out cleaning up browser window"); + } + } } } } diff --git a/toolproof/src/definitions/browser/mod.rs b/toolproof/src/definitions/browser/mod.rs index 5d40667..5864507 100644 --- a/toolproof/src/definitions/browser/mod.rs +++ b/toolproof/src/definitions/browser/mod.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use async_trait::async_trait; use chromiumoxide::cdp::browser_protocol::page::CaptureScreenshotParams; +use chromiumoxide::cdp::browser_protocol::browser::BrowserContextId; use chromiumoxide::cdp::browser_protocol::target::{ CreateBrowserContextParams, CreateTargetParams, }; @@ -145,7 +146,7 @@ impl BrowserTester { browser_timeout, .. } => { - let context = browser + let context_id = browser .create_browser_context(CreateBrowserContextParams { dispose_on_detach: Some(true), proxy_server: None, @@ -160,7 +161,7 @@ impl BrowserTester { for_tab: None, width: None, height: None, - browser_context_id: Some(context), + browser_context_id: Some(context_id.clone()), enable_begin_frame_control: None, new_window: None, background: None, @@ -170,21 +171,29 @@ impl BrowserTester { page.evaluate_on_new_document(init_script(*browser_timeout)) .await .expect("Could not set initialization js"); - BrowserWindow::Chrome(page) + BrowserWindow::Chrome { + page, + context_id, + browser: Arc::clone(browser), + } } } } } pub enum BrowserWindow { - Chrome(chromiumoxide::Page), + Chrome { + page: chromiumoxide::Page, + context_id: BrowserContextId, + browser: Arc, + }, Pagebrowse(PagebrowserWindow), } impl BrowserWindow { async fn navigate(&self, url: String, wait_for_load: bool) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { // TODO: This is implicitly always wait_for_load: true page.goto(url) .await @@ -203,7 +212,7 @@ impl BrowserWindow { script: String, ) -> Result, ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { let res = page .evaluate_function(format!("async function() {{{}}}", harnessed(script))) .await @@ -220,7 +229,7 @@ impl BrowserWindow { async fn screenshot_page(&self, filepath: PathBuf) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { let image_format = browser_specific::chrome_image_format(&filepath)?; page.save_screenshot( @@ -253,7 +262,7 @@ impl BrowserWindow { timeout_secs: u64, ) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { let image_format = browser_specific::chrome_image_format(&filepath)?; let element = browser_specific::wait_for_chrome_element_selector( @@ -284,7 +293,7 @@ impl BrowserWindow { timeout_secs: u64, ) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { let text = text.to_lowercase(); let selector_text = escape_xpath_string(&text); let el_xpath = |el: &str| { @@ -437,7 +446,7 @@ impl BrowserWindow { timeout_secs: u64, ) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { loop { let element = browser_specific::wait_for_chrome_element_selector( page, @@ -523,7 +532,7 @@ impl BrowserWindow { timeout_secs: u64, ) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { loop { let element = browser_specific::wait_for_chrome_element_selector( page, @@ -563,7 +572,7 @@ impl BrowserWindow { async fn press_key(&self, key: &str, timeout_secs: u64) -> Result<(), ToolproofStepError> { match self { - BrowserWindow::Chrome(page) => { + BrowserWindow::Chrome { page, .. } => { let dom = browser_specific::wait_for_chrome_element_selector(page, "body", timeout_secs) .await?; diff --git a/toolproof/src/main.rs b/toolproof/src/main.rs index 7acd8c4..a6839d8 100644 --- a/toolproof/src/main.rs +++ b/toolproof/src/main.rs @@ -869,10 +869,12 @@ async fn main_inner() -> Result<(), ()> { let mut results = join_or_shutdown(hands, &shutdown_rx) .await? .into_iter() - .map(|outer_err| match outer_err { - Ok(Ok(success)) => Ok(success), - Ok(Err(e)) => Err(e), - Err(e) => panic!("Failed to await all tests: {e}"), + .filter_map(|outer_err| match outer_err { + Ok(inner) => Some(inner), + Err(e) => { + eprintln!("[toolproof] Error: A test task panicked: {e}"); + None + } }) .collect::>();