spinne_core/
config.rs

1// Handles interactions with the config file
2
3use std::{fs, path::PathBuf};
4
5use serde_json::Value;
6use spinne_logger::Logger;
7
8#[derive(Debug, PartialEq)]
9pub struct ConfigValues {
10    pub exclude: Option<Vec<String>>,
11    pub include: Option<Vec<String>>,
12}
13
14pub struct Config {
15    pub path: PathBuf,
16}
17
18impl Config {
19    /// Reads the config file and returns values
20    pub fn read(path: PathBuf) -> Option<ConfigValues> {
21        let config = fs::read_to_string(path);
22
23        if config.is_err() {
24            Logger::error("Failed to read config file");
25            return None;
26        }
27
28        match serde_json::from_str::<Value>(&config.unwrap()) {
29            Ok(value) => {
30                let exclude_value = value.get("exclude");
31                let include_value = value.get("include");
32
33                let exclude = match exclude_value {
34                    Some(value) => Some(Self::get_array_of_strings(value)),
35                    None => None,
36                };
37
38                let include = match include_value {
39                    Some(value) => Some(Self::get_array_of_strings(value)),
40                    None => None,
41                };
42
43                Some(ConfigValues { exclude, include })
44            }
45            Err(err) => {
46                Logger::error("Failed to parse config file");
47                Logger::error(&err.to_string());
48                return None;
49            }
50        }
51    }
52
53    /// Maps a Value to an array of strings
54    fn get_array_of_strings(value: &Value) -> Vec<String> {
55        value
56            .as_array()
57            .unwrap_or(&vec![])
58            .iter()
59            .map(|v| v.as_str().unwrap_or("").to_string())
60            .collect::<Vec<String>>()
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use crate::util::test_utils::create_mock_project;
67
68    use super::*;
69
70    #[test]
71    fn test_config_read() {
72        let temp_dir = create_mock_project(&vec![(
73            "spinne.json",
74            r#"{"exclude": ["test.tsx"], "include": ["test.tsx"]}"#,
75        )]);
76        let config = Config::read(temp_dir.path().join("spinne.json"));
77
78        assert_eq!(
79            config,
80            Some(ConfigValues {
81                exclude: Some(vec!["test.tsx".to_string()]),
82                include: Some(vec!["test.tsx".to_string()])
83            })
84        );
85    }
86
87    #[test]
88    fn test_config_read_no_config() {
89        let temp_dir = create_mock_project(&vec![]);
90        let config = Config::read(temp_dir.path().join("spinne.json"));
91
92        assert_eq!(config, None);
93    }
94
95    #[test]
96    fn test_config_read_invalid_config() {
97        let temp_dir = create_mock_project(&vec![("spinne.json", r#"{"]ht["te)}"#)]);
98        let config = Config::read(temp_dir.path().join("spinne.json"));
99
100        assert_eq!(config, None);
101    }
102
103    #[test]
104    fn test_config_without_include() {
105        let temp_dir = create_mock_project(&vec![("spinne.json", r#"{"exclude": ["test.tsx"]}"#)]);
106        let config = Config::read(temp_dir.path().join("spinne.json"));
107
108        assert_eq!(
109            config,
110            Some(ConfigValues {
111                exclude: Some(vec!["test.tsx".to_string()]),
112                include: None
113            })
114        );
115    }
116
117    #[test]
118    fn test_config_without_exclude() {
119        let temp_dir = create_mock_project(&vec![("spinne.json", r#"{"include": ["test.tsx"]}"#)]);
120        let config = Config::read(temp_dir.path().join("spinne.json"));
121
122        assert_eq!(
123            config,
124            Some(ConfigValues {
125                exclude: None,
126                include: Some(vec!["test.tsx".to_string()])
127            })
128        );
129    }
130}