ralph/queue/search/
mod.rs1mod fields;
22mod filter;
23mod fuzzy;
24mod normalize;
25mod options;
26mod substring;
27
28#[cfg(test)]
29mod test_support;
30
31pub use filter::filter_tasks;
32pub use fuzzy::fuzzy_search_tasks;
33pub use options::SearchOptions;
34pub use substring::search_tasks;
35
36use crate::contracts::Task;
37use anyhow::Result;
38
39pub fn search_tasks_with_options<'a>(
45 tasks: impl IntoIterator<Item = &'a Task>,
46 query: &str,
47 options: &SearchOptions,
48) -> Result<Vec<&'a Task>> {
49 if options.use_fuzzy {
50 fuzzy_search_tasks(tasks, query, options.case_sensitive)
51 .map(|results| results.into_iter().map(|(_, task)| task).collect())
52 } else {
53 search_tasks(tasks, query, options.use_regex, options.case_sensitive)
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use test_support::task;
61
62 #[test]
63 fn search_tasks_with_options_fuzzy_mode() -> Result<()> {
64 let mut t1 = task("RQ-0001");
65 t1.title = "Fix authentication".to_string();
66
67 let mut t2 = task("RQ-0002");
68 t2.title = "Update docs".to_string();
69
70 let tasks: Vec<&Task> = vec![&t1, &t2];
71 let options = SearchOptions {
72 use_regex: false,
73 case_sensitive: false,
74 use_fuzzy: true,
75 scopes: vec![],
76 };
77
78 let results = search_tasks_with_options(tasks.iter().copied(), "auth", &options)?;
79 assert_eq!(results.len(), 1);
80 assert_eq!(results[0].id, "RQ-0001");
81 Ok(())
82 }
83
84 #[test]
85 fn search_tasks_with_options_regex_mode() -> Result<()> {
86 let mut t1 = task("RQ-0001");
87 t1.title = "Fix RQ-1234 bug".to_string();
88
89 let mut t2 = task("RQ-0002");
90 t2.title = "Update docs".to_string();
91
92 let tasks: Vec<&Task> = vec![&t1, &t2];
93 let options = SearchOptions {
94 use_regex: true,
95 case_sensitive: false,
96 use_fuzzy: false,
97 scopes: vec![],
98 };
99
100 let results = search_tasks_with_options(tasks.iter().copied(), r"RQ-\d{4}", &options)?;
101 assert_eq!(results.len(), 1);
102 assert_eq!(results[0].id, "RQ-0001");
103 Ok(())
104 }
105
106 #[test]
107 fn search_tasks_with_options_substring_mode() -> Result<()> {
108 let mut t1 = task("RQ-0001");
109 t1.title = "Fix authentication".to_string();
110
111 let mut t2 = task("RQ-0002");
112 t2.title = "Update docs".to_string();
113
114 let tasks: Vec<&Task> = vec![&t1, &t2];
115 let options = SearchOptions {
116 use_regex: false,
117 case_sensitive: false,
118 use_fuzzy: false,
119 scopes: vec![],
120 };
121
122 let results = search_tasks_with_options(tasks.iter().copied(), "auth", &options)?;
123 assert_eq!(results.len(), 1);
124 assert_eq!(results[0].id, "RQ-0001");
125 Ok(())
126 }
127}