1use std::time::Duration;
3
4use bao_stealth::StealthProfile;
5
6use crate::permission::Permission;
7
8#[derive(Debug, Clone)]
9pub struct BaoConfig {
10 pub cdp_port: Option<u16>,
11 pub max_pages: usize,
12 pub idle_ttl: Duration,
13 pub default_viewport_width: u32,
14 pub default_viewport_height: u32,
15 pub stealth_profile: Option<StealthProfile>,
16 pub ignore_certificate_errors: bool,
23}
24
25impl Default for BaoConfig {
26 fn default() -> Self {
27 BaoConfig {
28 cdp_port: None,
29 max_pages: 50,
30 idle_ttl: Duration::from_secs(60),
31 default_viewport_width: 1920,
32 default_viewport_height: 1080,
33 stealth_profile: None,
34 ignore_certificate_errors: false,
35 }
36 }
37}
38
39impl BaoConfig {
40 pub fn validate(&self) -> Result<(), String> {
41 if self.max_pages < 1 {
42 return Err(format!("max_pages must be >= 1, got {}", self.max_pages));
43 }
44 if self.default_viewport_width < 800 {
45 return Err(format!(
46 "viewport_width must be >= 800, got {}",
47 self.default_viewport_width
48 ));
49 }
50 if self.default_viewport_height < 600 {
51 return Err(format!(
52 "viewport_height must be >= 600, got {}",
53 self.default_viewport_height
54 ));
55 }
56 Ok(())
57 }
58}
59
60#[derive(Debug, Clone, Default)]
61pub struct PageConfig {
62 pub url: Option<String>,
63 pub viewport_width: Option<u32>,
64 pub viewport_height: Option<u32>,
65 pub stealth_profile: Option<StealthProfile>,
66 pub permission: Option<Permission>,
67}
68
69#[derive(Debug, Clone)]
70pub struct BrowserConfig {
71 pub url: Option<String>,
72 pub cdp_port: u16,
73 pub viewport_width: u32,
74 pub viewport_height: u32,
75 pub headless: bool,
76 pub stealth_profile: Option<StealthProfile>,
77}
78
79impl Default for BrowserConfig {
80 fn default() -> Self {
81 BrowserConfig {
82 url: None,
83 cdp_port: 9222,
84 viewport_width: 1920,
85 viewport_height: 1080,
86 headless: true,
87 stealth_profile: None,
88 }
89 }
90}
91
92impl From<BrowserConfig> for BaoConfig {
93 fn from(bc: BrowserConfig) -> Self {
94 BaoConfig {
95 cdp_port: Some(bc.cdp_port),
96 max_pages: 50,
97 idle_ttl: Duration::from_secs(60),
98 default_viewport_width: bc.viewport_width,
99 default_viewport_height: bc.viewport_height,
100 stealth_profile: bc.stealth_profile,
101 ignore_certificate_errors: false,
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
112
113 #[test]
114 fn bao_config_default_values() {
115 let cfg = BaoConfig::default();
116 assert_eq!(cfg.cdp_port, None);
117 assert_eq!(cfg.max_pages, 50);
118 assert_eq!(cfg.idle_ttl, Duration::from_secs(60));
119 assert_eq!(cfg.default_viewport_width, 1920);
120 assert_eq!(cfg.default_viewport_height, 1080);
121 assert!(cfg.stealth_profile.is_none());
122 }
123
124 #[test]
125 fn validate_ok_with_defaults() {
126 assert!(BaoConfig::default().validate().is_ok());
127 }
128
129 #[test]
130 fn validate_fails_max_pages_zero() {
131 let mut cfg = BaoConfig::default();
132 cfg.max_pages = 0;
133 let err = cfg.validate().unwrap_err();
134 assert!(
135 err.contains("max_pages must be >= 1"),
136 "unexpected error: {err}"
137 );
138 assert!(err.contains("0"), "error should report the value 0: {err}");
139 }
140
141 #[test]
142 fn validate_fails_viewport_width_799() {
143 let mut cfg = BaoConfig::default();
144 cfg.default_viewport_width = 799;
145 let err = cfg.validate().unwrap_err();
146 assert!(
147 err.contains("viewport_width must be >= 800"),
148 "unexpected error: {err}"
149 );
150 assert!(
151 err.contains("799"),
152 "error should report the value 799: {err}"
153 );
154 }
155
156 #[test]
157 fn validate_fails_viewport_height_599() {
158 let mut cfg = BaoConfig::default();
159 cfg.default_viewport_height = 599;
160 let err = cfg.validate().unwrap_err();
161 assert!(
162 err.contains("viewport_height must be >= 600"),
163 "unexpected error: {err}"
164 );
165 assert!(
166 err.contains("599"),
167 "error should report the value 599: {err}"
168 );
169 }
170
171 #[test]
172 fn browser_config_default_values() {
173 let cfg = BrowserConfig::default();
174 assert_eq!(cfg.url, None);
175 assert_eq!(cfg.cdp_port, 9222);
176 assert_eq!(cfg.viewport_width, 1920);
177 assert_eq!(cfg.viewport_height, 1080);
178 assert!(cfg.headless);
179 assert!(cfg.stealth_profile.is_none());
180 }
181
182 #[test]
183 fn from_browser_config_preserves_cdp_port() {
184 let bc = BrowserConfig {
185 cdp_port: 9333,
186 ..Default::default()
187 };
188 let bao: BaoConfig = bc.into();
189 assert_eq!(bao.cdp_port, Some(9333));
190 }
191
192 #[test]
193 fn from_browser_config_preserves_stealth_profile_none() {
194 let bc = BrowserConfig::default();
195 let bao: BaoConfig = bc.into();
196 assert!(bao.stealth_profile.is_none());
197 }
198
199 #[test]
200 fn from_browser_config_maps_fields_correctly() {
201 let bc = BrowserConfig {
202 url: Some("https://example.com".into()),
203 cdp_port: 1234,
204 viewport_width: 1280,
205 viewport_height: 720,
206 headless: false,
207 stealth_profile: None,
208 };
209 let bao: BaoConfig = bc.into();
210 assert_eq!(bao.cdp_port, Some(1234));
211 assert_eq!(bao.max_pages, 50);
212 assert_eq!(bao.idle_ttl, Duration::from_secs(60));
213 assert_eq!(bao.default_viewport_width, 1280);
214 assert_eq!(bao.default_viewport_height, 720);
215 assert!(bao.stealth_profile.is_none());
216 }
217}