subx_cli/config/
builder.rs1use crate::config::test_service::TestConfigService;
7use crate::config::{Config, OverflowStrategy};
8
9pub struct TestConfigBuilder {
26 config: Config,
27}
28
29impl TestConfigBuilder {
30 pub fn new() -> Self {
32 Self {
33 config: Config::default(),
34 }
35 }
36
37 pub fn with_ai_provider(mut self, provider: &str) -> Self {
45 self.config.ai.provider = provider.to_string();
46 self
47 }
48
49 pub fn with_ai_model(mut self, model: &str) -> Self {
55 self.config.ai.model = model.to_string();
56 self
57 }
58
59 pub fn with_ai_api_key(mut self, api_key: &str) -> Self {
65 self.config.ai.api_key = Some(api_key.to_string());
66 self
67 }
68
69 pub fn with_ai_base_url(mut self, base_url: &str) -> Self {
75 self.config.ai.base_url = base_url.to_string();
76 self
77 }
78
79 pub fn with_max_sample_length(mut self, length: usize) -> Self {
85 self.config.ai.max_sample_length = length;
86 self
87 }
88
89 pub fn with_ai_temperature(mut self, temperature: f32) -> Self {
95 self.config.ai.temperature = temperature;
96 self
97 }
98
99 pub fn with_ai_max_tokens(mut self, max_tokens: u32) -> Self {
105 self.config.ai.max_tokens = max_tokens;
106 self
107 }
108
109 pub fn with_ai_retry(mut self, attempts: u32, delay_ms: u64) -> Self {
116 self.config.ai.retry_attempts = attempts;
117 self.config.ai.retry_delay_ms = delay_ms;
118 self
119 }
120
121 pub fn with_ai_request_timeout(mut self, timeout_seconds: u64) -> Self {
127 self.config.ai.request_timeout_seconds = timeout_seconds;
128 self
129 }
130
131 pub fn with_sync_method(mut self, method: &str) -> Self {
139 self.config.sync.default_method = method.to_string();
140 self
141 }
142
143 pub fn with_vad_enabled(mut self, enabled: bool) -> Self {
149 self.config.sync.vad.enabled = enabled;
150 self
151 }
152
153 pub fn with_vad_sensitivity(mut self, sensitivity: f32) -> Self {
159 self.config.sync.vad.sensitivity = sensitivity;
160 self
161 }
162
163 pub fn with_default_output_format(mut self, format: &str) -> Self {
171 self.config.formats.default_output = format.to_string();
172 self
173 }
174
175 pub fn with_preserve_styling(mut self, preserve: bool) -> Self {
181 self.config.formats.preserve_styling = preserve;
182 self
183 }
184
185 pub fn with_default_encoding(mut self, encoding: &str) -> Self {
191 self.config.formats.default_encoding = encoding.to_string();
192 self
193 }
194
195 pub fn with_encoding_detection_confidence(mut self, confidence: f32) -> Self {
201 self.config.formats.encoding_detection_confidence = confidence;
202 self
203 }
204
205 pub fn with_backup_enabled(mut self, enabled: bool) -> Self {
213 self.config.general.backup_enabled = enabled;
214 self
215 }
216
217 pub fn with_max_concurrent_jobs(mut self, jobs: usize) -> Self {
223 self.config.general.max_concurrent_jobs = jobs;
224 self
225 }
226
227 pub fn with_task_timeout(mut self, timeout_seconds: u64) -> Self {
233 self.config.general.task_timeout_seconds = timeout_seconds;
234 self
235 }
236
237 pub fn with_progress_bar(mut self, enabled: bool) -> Self {
243 self.config.general.enable_progress_bar = enabled;
244 self
245 }
246
247 pub fn with_worker_idle_timeout(mut self, timeout_seconds: u64) -> Self {
253 self.config.general.worker_idle_timeout_seconds = timeout_seconds;
254 self
255 }
256
257 pub fn with_task_queue_size(mut self, size: usize) -> Self {
265 self.config.parallel.task_queue_size = size;
266 self
267 }
268
269 pub fn with_task_priorities(mut self, enabled: bool) -> Self {
275 self.config.parallel.enable_task_priorities = enabled;
276 self
277 }
278
279 pub fn with_auto_balance_workers(mut self, enabled: bool) -> Self {
285 self.config.parallel.auto_balance_workers = enabled;
286 self
287 }
288
289 pub fn with_queue_overflow_strategy(mut self, strategy: OverflowStrategy) -> Self {
295 self.config.parallel.overflow_strategy = strategy;
296 self
297 }
298
299 pub fn with_parallel_settings(mut self, max_workers: usize, queue_size: usize) -> Self {
301 self.config.general.max_concurrent_jobs = max_workers;
302 self.config.parallel.task_queue_size = queue_size;
303 self
304 }
305
306 pub fn build_service(self) -> TestConfigService {
310 TestConfigService::new(self.config)
311 }
312
313 pub fn build_config(self) -> Config {
315 self.config
316 }
317
318 pub fn config(&self) -> &Config {
320 &self.config
321 }
322
323 pub fn config_mut(&mut self) -> &mut Config {
325 &mut self.config
326 }
327 pub fn with_mock_ai_server(mut self, mock_url: &str) -> Self {
346 self.config.ai.base_url = mock_url.to_string();
347 self.config.ai.api_key = Some("mock-api-key".to_string());
348 self
349 }
350}
351
352impl Default for TestConfigBuilder {
353 fn default() -> Self {
354 Self::new()
355 }
356}
357
358#[cfg(test)]
359mod tests {
360 use super::*;
361 use crate::config::service::ConfigService;
362
363 #[test]
364 fn test_builder_default() {
365 let config = TestConfigBuilder::new().build_config();
366 let default_config = Config::default();
367
368 assert_eq!(config.ai.provider, default_config.ai.provider);
369 assert_eq!(config.ai.model, default_config.ai.model);
370 }
371
372 #[test]
373 fn test_builder_ai_configuration() {
374 let config = TestConfigBuilder::new()
375 .with_ai_provider("anthropic")
376 .with_ai_model("claude-3")
377 .with_ai_api_key("test-key")
378 .with_max_sample_length(5000)
379 .with_ai_temperature(0.7)
380 .build_config();
381
382 assert_eq!(config.ai.provider, "anthropic");
383 assert_eq!(config.ai.model, "claude-3");
384 assert_eq!(config.ai.api_key, Some("test-key".to_string()));
385 assert_eq!(config.ai.max_sample_length, 5000);
386 assert_eq!(config.ai.temperature, 0.7);
387 }
388
389 #[test]
390 fn test_builder_sync_configuration() {
391 let config = TestConfigBuilder::new()
392 .with_sync_method("vad")
393 .with_vad_enabled(true)
394 .with_vad_sensitivity(0.8)
395 .build_config();
396
397 assert_eq!(config.sync.default_method, "vad");
398 assert!(config.sync.vad.enabled);
399 assert_eq!(config.sync.vad.sensitivity, 0.8);
400 }
401
402 #[test]
403 fn test_builder_service_creation() {
404 let service = TestConfigBuilder::new()
405 .with_ai_provider("test-provider")
406 .build_service();
407
408 let config = service.get_config().unwrap();
409 assert_eq!(config.ai.provider, "test-provider");
410 }
411
412 #[test]
413 fn test_builder_chaining() {
414 let config = TestConfigBuilder::new()
415 .with_ai_provider("openai")
416 .with_ai_model("gpt-4.1")
417 .with_sync_method("vad")
418 .with_vad_sensitivity(0.5)
419 .with_max_concurrent_jobs(8)
420 .with_task_queue_size(200)
421 .build_config();
422
423 assert_eq!(config.ai.provider, "openai");
424 assert_eq!(config.ai.model, "gpt-4.1");
425 assert_eq!(config.sync.default_method, "vad");
426 assert_eq!(config.sync.vad.sensitivity, 0.5);
427 assert_eq!(config.general.max_concurrent_jobs, 8);
428 assert_eq!(config.parallel.task_queue_size, 200);
429 }
430
431 #[test]
432 fn test_builder_ai_configuration_openrouter() {
433 let config = TestConfigBuilder::new()
434 .with_ai_provider("openrouter")
435 .with_ai_model("deepseek/deepseek-r1-0528:free")
436 .with_ai_api_key("test-openrouter-key")
437 .build_config();
438 assert_eq!(config.ai.provider, "openrouter");
439 assert_eq!(config.ai.model, "deepseek/deepseek-r1-0528:free");
440 assert_eq!(config.ai.api_key, Some("test-openrouter-key".to_string()));
441 }
442}