check.rs
104 lignes · 3514 octets
//! Contrôle statique du réalisé : une route du todo est « faite » si un //! `.route("<chemin>")` (chaîne exacte) apparaît dans les sources du projet. use std::path::Path; use crate::todo::TodoRow; /// (pur) Marque `done` selon la présence de `"<route>"` dans `haystack`. pub fn mark(rows: &mut [TodoRow], haystack: &str) { for r in rows.iter_mut() { // chaîne littérale exacte, guillemet fermant inclus → évite les // faux positifs de préfixe (/settings vs /settings/sessions). let needle = format!("\"{}\"", r.route); r.done = haystack.contains(&needle); } } /// (I/O) Concatène le contenu des `.rs` sous `root`, en ignorant `target/` /// et les crates vendored `rustwarden-*`. pub fn collect_sources(root: &Path) -> String { let mut out = String::new(); walk(root, &mut out); out } fn walk(dir: &Path, out: &mut String) { let Ok(entries) = std::fs::read_dir(dir) else { return; }; for entry in entries.flatten() { let path = entry.path(); let name = entry.file_name(); let name = name.to_string_lossy(); if path.is_dir() { if name == "target" || name.starts_with("rustwarden-") { continue; } walk(&path, out); } else if path.extension().is_some_and(|e| e == "rs") { if let Ok(s) = std::fs::read_to_string(&path) { out.push_str(&s); out.push('\n'); } } } } #[cfg(test)] mod tests { use super::*; fn row(route: &str) -> TodoRow { TodoRow { done: false, functionality: "F".into(), screen: "S".into(), route: route.into(), channel: "browser".into(), protected: true, methods: "".into(), io: "".into(), } } #[test] fn mark_detecte_route_presente() { let mut rows = vec![row("/profile"), row("/settings/sessions")]; let haystack = r#"router.route("/profile", get(profile))"#; mark(&mut rows, haystack); assert!(rows[0].done, "/profile trouvée"); assert!(!rows[1].done, "/settings/sessions absente"); } #[test] fn mark_evite_les_faux_positifs_de_prefixe() { // "/settings" ne doit PAS matcher "/settings/sessions" let mut rows = vec![row("/settings")]; let haystack = r#".route("/settings/sessions", get(h))"#; mark(&mut rows, haystack); assert!(!rows[0].done); } #[test] fn collect_sources_ignore_target_et_vendored() { let base = std::env::temp_dir().join(format!("scrsel_{}", std::process::id())); let _ = std::fs::remove_dir_all(&base); std::fs::create_dir_all(base.join("src")).unwrap(); std::fs::create_dir_all(base.join("crates/rustwarden-core/src")).unwrap(); std::fs::create_dir_all(base.join("target")).unwrap(); std::fs::write(base.join("src/app.rs"), r#".route("/mine", get(h))"#).unwrap(); std::fs::write( base.join("crates/rustwarden-core/src/x.rs"), r#".route("/vendored", get(h))"#, ) .unwrap(); std::fs::write(base.join("target/y.rs"), r#".route("/built", get(h))"#).unwrap(); let hay = collect_sources(&base); assert!(hay.contains("/mine")); assert!(!hay.contains("/vendored")); assert!(!hay.contains("/built")); let _ = std::fs::remove_dir_all(&base); } }
GitRust