probador/handlers/
init.rs1use crate::config::CliConfig;
4use crate::InitArgs;
5use std::path::Path;
6
7pub fn execute_init(_config: &CliConfig, args: &InitArgs) {
9 println!("Initializing Probar project in: {}", args.path.display());
10
11 if args.force {
12 println!("Force mode enabled - overwriting existing files");
13 }
14
15 if let Err(e) = std::fs::create_dir_all(&args.path) {
17 eprintln!("Failed to create directory: {e}");
18 return;
19 }
20
21 let test_file = args.path.join("tests").join("basic_test.rs");
23 if let Some(parent) = test_file.parent() {
24 let _ = std::fs::create_dir_all(parent);
25 }
26
27 let test_content = generate_probar_config();
28 if !test_file.exists() || args.force {
29 let _ = std::fs::write(&test_file, test_content);
30 println!("Created: {}", test_file.display());
31 }
32
33 println!("Probar project initialized successfully!");
34}
35
36#[must_use]
38pub const fn generate_probar_config() -> &'static str {
39 r#"//! Basic Probar test
40use jugar_probar::prelude::*;
41
42#[test]
43fn test_example() {
44 let result = TestResult::pass("example_test");
45 assert!(result.passed);
46}
47"#
48}
49
50#[must_use]
52pub fn is_valid_init_path(path: &Path) -> bool {
53 if !path.exists() {
55 return true;
56 }
57
58 if !path.is_dir() {
59 return false;
60 }
61
62 match std::fs::read_dir(path) {
64 Ok(entries) => {
65 for entry in entries.flatten() {
66 let name = entry.file_name();
67 let name_str = name.to_string_lossy();
68 if !name_str.starts_with('.') {
69 return false; }
71 }
72 true
73 }
74 Err(_) => false,
75 }
76}
77
78#[cfg(test)]
79#[allow(clippy::unwrap_used)]
80mod tests {
81 use super::*;
82 use tempfile::TempDir;
83
84 #[test]
85 fn test_generate_probar_config() {
86 let config = generate_probar_config();
87 assert!(config.contains("use jugar_probar::prelude::*"));
88 assert!(config.contains("fn test_example()"));
89 assert!(config.contains("TestResult::pass"));
90 }
91
92 #[test]
93 fn test_is_valid_init_path_nonexistent() {
94 let temp = TempDir::new().unwrap();
95 let nonexistent = temp.path().join("new_project");
96 assert!(is_valid_init_path(&nonexistent));
97 }
98
99 #[test]
100 fn test_is_valid_init_path_empty_dir() {
101 let temp = TempDir::new().unwrap();
102 assert!(is_valid_init_path(temp.path()));
103 }
104
105 #[test]
106 fn test_is_valid_init_path_nonempty_dir() {
107 let temp = TempDir::new().unwrap();
108 std::fs::write(temp.path().join("existing.rs"), "// content").unwrap();
109 assert!(!is_valid_init_path(temp.path()));
110 }
111
112 #[test]
113 fn test_is_valid_init_path_dir_with_hidden_files() {
114 let temp = TempDir::new().unwrap();
115 std::fs::write(temp.path().join(".gitignore"), "target/").unwrap();
116 assert!(is_valid_init_path(temp.path()));
117 }
118
119 #[test]
120 fn test_is_valid_init_path_file() {
121 let temp = TempDir::new().unwrap();
122 let file_path = temp.path().join("file.txt");
123 std::fs::write(&file_path, "content").unwrap();
124 assert!(!is_valid_init_path(&file_path));
125 }
126
127 #[test]
128 fn test_execute_init_creates_directory() {
129 let temp = TempDir::new().unwrap();
130 let project_path = temp.path().join("new_project");
131
132 let config = CliConfig::default();
133 let args = InitArgs {
134 path: project_path.clone(),
135 force: false,
136 };
137
138 execute_init(&config, &args);
139
140 assert!(project_path.exists());
141 assert!(project_path.join("tests").exists());
142 assert!(project_path.join("tests").join("basic_test.rs").exists());
143 }
144
145 #[test]
146 fn test_execute_init_force_overwrites() {
147 let temp = TempDir::new().unwrap();
148 let project_path = temp.path().join("existing_project");
149 std::fs::create_dir_all(project_path.join("tests")).unwrap();
150
151 let old_content = "// old content";
152 std::fs::write(
153 project_path.join("tests").join("basic_test.rs"),
154 old_content,
155 )
156 .unwrap();
157
158 let config = CliConfig::default();
159 let args = InitArgs {
160 path: project_path.clone(),
161 force: true,
162 };
163
164 execute_init(&config, &args);
165
166 let content =
167 std::fs::read_to_string(project_path.join("tests").join("basic_test.rs")).unwrap();
168 assert!(content.contains("jugar_probar"));
169 assert!(!content.contains("old content"));
170 }
171
172 #[test]
173 fn test_execute_init_does_not_overwrite_without_force() {
174 let temp = TempDir::new().unwrap();
175 let project_path = temp.path().join("existing_project");
176 std::fs::create_dir_all(project_path.join("tests")).unwrap();
177
178 let old_content = "// old content that should remain";
179 std::fs::write(
180 project_path.join("tests").join("basic_test.rs"),
181 old_content,
182 )
183 .unwrap();
184
185 let config = CliConfig::default();
186 let args = InitArgs {
187 path: project_path.clone(),
188 force: false,
189 };
190
191 execute_init(&config, &args);
192
193 let content =
194 std::fs::read_to_string(project_path.join("tests").join("basic_test.rs")).unwrap();
195 assert!(content.contains("old content that should remain"));
196 }
197}