fluent_test/
config.rs

1use std::env;
2use std::sync::Once;
3
4// Initialization flag to ensure we only initialize once
5static INIT: Once = Once::new();
6
7// Environment variable to control enhanced output
8const ENV_ENHANCED_OUTPUT: &str = "FLUENT_TEST_ENHANCED_OUTPUT";
9
10/// Configuration for FluentTest's output and behavior
11pub struct Config {
12    pub(crate) use_colors: bool,
13    pub(crate) use_unicode_symbols: bool,
14    pub(crate) show_success_details: bool,
15    /// Enable enhanced test output (fluent assertions instead of standard output)
16    pub(crate) enhanced_output: bool,
17}
18
19impl Default for Config {
20    fn default() -> Self {
21        Self::new()
22    }
23}
24
25// Implement Clone for Config
26impl Clone for Config {
27    fn clone(&self) -> Self {
28        Self {
29            use_colors: self.use_colors,
30            use_unicode_symbols: self.use_unicode_symbols,
31            show_success_details: self.show_success_details,
32            enhanced_output: self.enhanced_output,
33        }
34    }
35}
36
37impl Config {
38    /// Creates a new configuration with default settings
39    pub fn new() -> Self {
40        // Check for environment variable to enable enhanced output
41        let enhanced_from_env = match env::var(ENV_ENHANCED_OUTPUT) {
42            Ok(val) => val.to_lowercase() == "true" || val == "1" || val == "yes",
43            Err(_) => false, // Default to standard output if env var not set
44        };
45
46        Self { use_colors: true, use_unicode_symbols: true, show_success_details: true, enhanced_output: enhanced_from_env }
47    }
48
49    /// Enable or disable colored output
50    pub fn use_colors(mut self, enable: bool) -> Self {
51        self.use_colors = enable;
52        self
53    }
54
55    /// Enable or disable Unicode symbols
56    pub fn use_unicode_symbols(mut self, enable: bool) -> Self {
57        self.use_unicode_symbols = enable;
58        self
59    }
60
61    /// Control whether to show details for successful tests
62    pub fn show_success_details(mut self, enable: bool) -> Self {
63        self.show_success_details = enable;
64        self
65    }
66
67    /// Enable or disable enhanced output (fluent assertions)
68    pub fn enhanced_output(mut self, enable: bool) -> Self {
69        self.enhanced_output = enable;
70        self
71    }
72
73    /// Apply the configuration
74    pub fn apply(self) {
75        use crate::reporter::GLOBAL_CONFIG;
76
77        // Clone self before moving it into the global config
78        let config = self.clone();
79        *GLOBAL_CONFIG.write().unwrap() = self;
80
81        // Initialize the event system if enhanced output is enabled
82        if config.enhanced_output {
83            crate::initialize();
84        }
85    }
86}
87
88/// Initialize the FluentTest system
89/// This is called automatically when needed but can also be called explicitly
90pub fn initialize() {
91    INIT.call_once(|| {
92        // Check if enhanced output is enabled in the config
93        let config = crate::reporter::GLOBAL_CONFIG.read().unwrap();
94
95        if config.enhanced_output {
96            // Initialize event system
97            crate::events::EventEmitter::init();
98
99            // Register event handlers
100            crate::Reporter::init();
101        }
102    });
103}
104
105/// Check if enhanced output is enabled in the current configuration
106pub fn is_enhanced_output_enabled() -> bool {
107    let config = crate::reporter::GLOBAL_CONFIG.read().unwrap();
108    return config.enhanced_output;
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114    use std::env;
115
116    // Helper function to reset environment variables
117    fn reset_env_var() {
118        unsafe {
119            env::remove_var(ENV_ENHANCED_OUTPUT);
120        }
121    }
122
123    #[test]
124    fn test_config_default() {
125        // Make sure we start with a clean environment
126        reset_env_var();
127
128        let config = Config::new();
129
130        // Check default values
131        assert_eq!(config.use_colors, true);
132        assert_eq!(config.use_unicode_symbols, true);
133        assert_eq!(config.show_success_details, true);
134        assert_eq!(config.enhanced_output, false); // Default is false without env var
135    }
136
137    #[test]
138    fn test_config_env_var_true() {
139        // Test with environment variable set to true
140        reset_env_var();
141        unsafe {
142            env::set_var(ENV_ENHANCED_OUTPUT, "true");
143        }
144
145        let config = Config::new();
146        assert_eq!(config.enhanced_output, true);
147
148        // Cleanup
149        reset_env_var();
150    }
151
152    #[test]
153    fn test_config_env_var_false() {
154        // Test with environment variable set to false
155        reset_env_var();
156        unsafe {
157            env::set_var(ENV_ENHANCED_OUTPUT, "false");
158        }
159
160        let config = Config::new();
161        assert_eq!(config.enhanced_output, false);
162
163        // Cleanup
164        reset_env_var();
165    }
166
167    #[test]
168    fn test_config_env_var_alternative_values() {
169        // Test alternative true values
170        reset_env_var();
171
172        // Test "1" as true
173        unsafe {
174            env::set_var(ENV_ENHANCED_OUTPUT, "1");
175        }
176        let config = Config::new();
177        assert_eq!(config.enhanced_output, true);
178
179        // Test "yes" as true
180        reset_env_var();
181        unsafe {
182            env::set_var(ENV_ENHANCED_OUTPUT, "yes");
183        }
184        let config = Config::new();
185        assert_eq!(config.enhanced_output, true);
186
187        // Test case-insensitivity
188        reset_env_var();
189        unsafe {
190            env::set_var(ENV_ENHANCED_OUTPUT, "TRUE");
191        }
192        let config = Config::new();
193        assert_eq!(config.enhanced_output, true);
194
195        // Cleanup
196        reset_env_var();
197    }
198
199    #[test]
200    fn test_config_builder_methods() {
201        let config = Config::new().use_colors(false).use_unicode_symbols(false).show_success_details(false).enhanced_output(true);
202
203        assert_eq!(config.use_colors, false);
204        assert_eq!(config.use_unicode_symbols, false);
205        assert_eq!(config.show_success_details, false);
206        assert_eq!(config.enhanced_output, true);
207    }
208
209    #[test]
210    fn test_config_clone() {
211        let config1 = Config::new().use_colors(false).enhanced_output(true);
212
213        let config2 = config1.clone();
214
215        // Make sure the clone has the same values
216        assert_eq!(config1.use_colors, config2.use_colors);
217        assert_eq!(config1.use_unicode_symbols, config2.use_unicode_symbols);
218        assert_eq!(config1.show_success_details, config2.show_success_details);
219        assert_eq!(config1.enhanced_output, config2.enhanced_output);
220    }
221
222    // Note: Testing apply() and initialize() would require mocking or complex setups
223    // since they interact with global state. For a unit test, we're focusing on the
224    // pure functionality that can be tested in isolation.
225}