|
61 | 61 | //! |
62 | 62 | //! ### Driver Features |
63 | 63 | //! |
64 | | -//! To use static export, enable one of the following features: |
| 64 | +//! For compile time only, no specific feature must be provided. However, to use static export at runtime, one of the below features must be enabled. |
65 | 65 | //! |
66 | 66 | //! - `chromedriver`: Use Chrome/Chromium for rendering |
67 | 67 | //! - `geckodriver`: Use Firefox for rendering |
@@ -304,6 +304,9 @@ use crate::template::{image_export_js_script, pdf_export_js_script}; |
304 | 304 | mod template; |
305 | 305 | mod webdriver; |
306 | 306 |
|
| 307 | +#[cfg(not(any(feature = "chromedriver", feature = "geckodriver")))] |
| 308 | +const DRIVER_FEATURE_REQUIRED: &str = "Static image export at runtime requires enabling either the 'chromedriver' or 'geckodriver' feature."; |
| 309 | + |
307 | 310 | /// Supported image formats for static image export. |
308 | 311 | /// |
309 | 312 | /// This enum defines all the image formats that can be exported from Plotly |
@@ -649,6 +652,7 @@ impl StaticExporterBuilder { |
649 | 652 | } |
650 | 653 |
|
651 | 654 | /// Create a new WebDriver instance based on the spawn_webdriver flag |
| 655 | + #[cfg(any(feature = "chromedriver", feature = "geckodriver"))] |
652 | 656 | fn create_webdriver(&self) -> Result<WebDriver> { |
653 | 657 | let port = self.webdriver_port; |
654 | 658 | let in_async = tokio::runtime::Handle::try_current().is_ok(); |
@@ -689,16 +693,22 @@ impl StaticExporterBuilder { |
689 | 693 | /// .expect("Failed to build AsyncStaticExporter"); |
690 | 694 | /// ``` |
691 | 695 | pub fn build_async(&self) -> Result<AsyncStaticExporter> { |
692 | | - let wd = self.create_webdriver()?; |
693 | | - Ok(AsyncStaticExporter { |
694 | | - webdriver_port: self.webdriver_port, |
695 | | - webdriver_url: self.webdriver_url.clone(), |
696 | | - webdriver: wd, |
697 | | - offline_mode: self.offline_mode, |
698 | | - pdf_export_timeout: self.pdf_export_timeout, |
699 | | - webdriver_browser_caps: self.webdriver_browser_caps.clone(), |
700 | | - webdriver_client: None, |
701 | | - }) |
| 696 | + #[cfg(not(any(feature = "chromedriver", feature = "geckodriver")))] |
| 697 | + return Err(anyhow!(DRIVER_FEATURE_REQUIRED)); |
| 698 | + |
| 699 | + #[cfg(any(feature = "chromedriver", feature = "geckodriver"))] |
| 700 | + { |
| 701 | + let wd = self.create_webdriver()?; |
| 702 | + Ok(AsyncStaticExporter { |
| 703 | + webdriver_port: self.webdriver_port, |
| 704 | + webdriver_url: self.webdriver_url.clone(), |
| 705 | + webdriver: wd, |
| 706 | + offline_mode: self.offline_mode, |
| 707 | + pdf_export_timeout: self.pdf_export_timeout, |
| 708 | + webdriver_browser_caps: self.webdriver_browser_caps.clone(), |
| 709 | + webdriver_client: None, |
| 710 | + }) |
| 711 | + } |
702 | 712 | } |
703 | 713 | } |
704 | 714 |
|
@@ -779,7 +789,7 @@ impl StaticExporter { |
779 | 789 | /// # Examples |
780 | 790 | /// |
781 | 791 | /// ```no_run |
782 | | - /// |
| 792 | + /// |
783 | 793 | /// // This example requires a running WebDriver (chromedriver/geckodriver) and a browser. |
784 | 794 | /// // It cannot be run as a doc test. |
785 | 795 | /// |
@@ -842,7 +852,7 @@ impl StaticExporter { |
842 | 852 | /// # Examples |
843 | 853 | /// |
844 | 854 | /// ```no_run |
845 | | - /// |
| 855 | + /// |
846 | 856 | /// // This example requires a running WebDriver (chromedriver/geckodriver) and a browser. |
847 | 857 | /// // It cannot be run as a doc test. |
848 | 858 | /// use plotly_static::{StaticExporterBuilder, ImageFormat}; |
@@ -1128,9 +1138,7 @@ impl AsyncStaticExporter { |
1128 | 1138 | fn build_webdriver_caps(&self) -> Result<Capabilities> { |
1129 | 1139 | #[cfg(not(any(feature = "chromedriver", feature = "geckodriver")))] |
1130 | 1140 | { |
1131 | | - Err(anyhow!( |
1132 | | - "Static image export requires enabling either the 'chromedriver' or 'geckodriver' feature." |
1133 | | - )) |
| 1141 | + Err(anyhow!(DRIVER_FEATURE_REQUIRED)) |
1134 | 1142 | } |
1135 | 1143 | #[cfg(any(feature = "chromedriver", feature = "geckodriver"))] |
1136 | 1144 | { |
@@ -1348,6 +1356,15 @@ mod tests { |
1348 | 1356 | let _ = env_logger::try_init(); |
1349 | 1357 | } |
1350 | 1358 |
|
| 1359 | + #[test] |
| 1360 | + #[cfg(not(any(feature = "chromedriver", feature = "geckodriver")))] |
| 1361 | + fn build_without_driver_feature_returns_error() { |
| 1362 | + match StaticExporterBuilder::default().build_async() { |
| 1363 | + Err(e) => assert_eq!(e.to_string(), DRIVER_FEATURE_REQUIRED), |
| 1364 | + Ok(_) => panic!("expected build to fail without a driver feature"), |
| 1365 | + } |
| 1366 | + } |
| 1367 | + |
1351 | 1368 | // Helper to generate unique ports for parallel tests |
1352 | 1369 | #[cfg(not(feature = "debug"))] |
1353 | 1370 | fn get_unique_port() -> u32 { |
|
0 commit comments