runtime_foxdriver/
runtime.rs1use anyhow::{Context, Result};
7
8use crate::browser::{launch_firefox, FoxBrowserConfig, Page};
9
10#[derive(Debug, Clone)]
12pub struct BrowserDriveOptions {
13 pub headless: bool,
15 pub no_sandbox: bool,
17}
18
19impl Default for BrowserDriveOptions {
20 fn default() -> Self {
21 Self {
22 headless: true,
23 no_sandbox: true,
24 }
25 }
26}
27
28#[must_use]
30pub fn launch_options(opts: &BrowserDriveOptions) -> FoxBrowserConfig {
31 FoxBrowserConfig {
32 headless: opts.headless,
33 ..Default::default()
34 }
35}
36
37pub async fn drive_browser<F, Fut, T>(url: &str, opts: BrowserDriveOptions, f: F) -> Result<T>
39where
40 F: FnOnce(Page) -> Fut,
41 Fut: std::future::Future<Output = Result<T>>,
42{
43 let page = launch_firefox(launch_options(&opts))
44 .await
45 .map_err(|e| anyhow::anyhow!("launch firefox (is it installed and on PATH?): {e}"))?;
46 tokio::time::timeout(std::time::Duration::from_secs(30), page.goto(url))
47 .await
48 .map_err(|_| anyhow::anyhow!("navigate to {url} timed out after 30s"))?
49 .with_context(|| format!("navigate to {url}"))?;
50 f(page).await
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn launch_options_headless_maps_correctly() {
59 let opts = launch_options(&BrowserDriveOptions {
60 headless: true,
61 ..BrowserDriveOptions::default()
62 });
63 assert!(opts.headless);
64 }
65
66 #[test]
67 fn launch_options_headful_maps_correctly() {
68 let opts = launch_options(&BrowserDriveOptions {
69 headless: false,
70 ..BrowserDriveOptions::default()
71 });
72 assert!(!opts.headless);
73 }
74}