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