mockforge_http/
replay_listing.rs1use globwalk::GlobWalkerBuilder;
3use serde::Serialize;
4
5#[derive(Debug, Serialize)]
7pub struct ReplayItem {
8 pub protocol: String,
10 pub operation_id: String,
12 pub saved_at: String,
14 pub path: String,
16}
17
18pub fn list_all(fixtures_root: &str) -> anyhow::Result<Vec<ReplayItem>> {
26 use std::path::Path;
27
28 let fixtures_path = Path::new(fixtures_root);
29 let mut out = Vec::new();
30
31 for proto in ["http", "grpc", "ws"] {
32 let proto_pattern = format!("{proto}/**/*.json");
34 for entry in GlobWalkerBuilder::from_patterns(fixtures_path, &[&proto_pattern]).build()? {
35 let p = entry?.path().to_path_buf();
36 if p.extension().map(|e| e == "json").unwrap_or(false) {
37 let relative_path = p.strip_prefix(fixtures_path).unwrap_or(&p).to_path_buf();
39
40 let comps: Vec<_> = relative_path
41 .components()
42 .map(|c| c.as_os_str().to_string_lossy().to_string())
43 .collect();
44 let len = comps.len();
45 let (op_id, ts) = if len >= 2 {
46 (comps[len - 2].clone(), comps[len - 1].replace(".json", ""))
47 } else {
48 ("unknown".into(), "unknown".into())
49 };
50 out.push(ReplayItem {
51 protocol: proto.to_string(),
52 operation_id: op_id,
53 saved_at: ts,
54 path: p.to_string_lossy().to_string(),
55 });
56 }
57 }
58 }
59 out.sort_by(|a, b| b.saved_at.cmp(&a.saved_at));
60 Ok(out)
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66 use std::fs;
67 use std::path::Path;
68 use tempfile::TempDir;
69
70 fn create_fixture_file(
71 dir: &Path,
72 protocol: &str,
73 op_id: &str,
74 timestamp: &str,
75 ) -> std::io::Result<()> {
76 let path = dir.join(protocol).join(op_id);
77 fs::create_dir_all(&path)?;
78 let file_path = path.join(format!("{}.json", timestamp));
79 fs::write(file_path, "{}")?;
80 Ok(())
81 }
82
83 #[test]
84 fn test_replay_item_structure() {
85 let item = ReplayItem {
86 protocol: "http".to_string(),
87 operation_id: "getUser".to_string(),
88 saved_at: "2024-01-01T12:00:00".to_string(),
89 path: "/fixtures/http/getUser/2024-01-01T12:00:00.json".to_string(),
90 };
91
92 assert_eq!(item.protocol, "http");
93 assert_eq!(item.operation_id, "getUser");
94 assert_eq!(item.saved_at, "2024-01-01T12:00:00");
95 }
96
97 #[test]
98 fn test_list_all_empty_directory() {
99 let temp_dir = TempDir::new().unwrap();
100 let fixtures_root = temp_dir.path().to_str().unwrap();
101
102 let result = list_all(fixtures_root);
103 assert!(result.is_ok());
104 let items = result.unwrap();
105 assert_eq!(items.len(), 0);
106 }
107
108 #[test]
109 fn test_list_all_with_http_fixtures() {
110 let temp_dir = TempDir::new().unwrap();
111
112 let temp_path = temp_dir.path().to_path_buf();
114 create_fixture_file(&temp_path, "http", "getUser", "2024-01-01T12:00:00").unwrap();
115 create_fixture_file(&temp_path, "http", "getUser", "2024-01-02T12:00:00").unwrap();
116 create_fixture_file(&temp_path, "http", "createUser", "2024-01-03T12:00:00").unwrap();
117
118 let fixtures_root = temp_path.to_str().unwrap();
119 let result = list_all(fixtures_root);
120
121 assert!(result.is_ok());
122 let items = result.unwrap();
123
124 assert_eq!(items.len(), 3);
125 assert!(items.iter().all(|item| item.protocol == "http"));
126 }
127
128 #[test]
129 fn test_list_all_with_multiple_protocols() {
130 let temp_dir = TempDir::new().unwrap();
131
132 let temp_path = temp_dir.path().to_path_buf();
134 create_fixture_file(&temp_path, "http", "getUser", "2024-01-01T12:00:00").unwrap();
135 create_fixture_file(&temp_path, "grpc", "GetUser", "2024-01-02T12:00:00").unwrap();
136 create_fixture_file(&temp_path, "ws", "subscribe", "2024-01-03T12:00:00").unwrap();
137
138 let fixtures_root = temp_path.to_str().unwrap();
139 let result = list_all(fixtures_root);
140
141 assert!(result.is_ok());
142 let items = result.unwrap();
143
144 assert_eq!(items.len(), 3);
145
146 let protocols: Vec<&str> = items.iter().map(|i| i.protocol.as_str()).collect();
147 assert!(protocols.contains(&"http"));
148 assert!(protocols.contains(&"grpc"));
149 assert!(protocols.contains(&"ws"));
150 }
151
152 #[test]
153 fn test_list_all_sorted_by_timestamp() {
154 let temp_dir = TempDir::new().unwrap();
155
156 let temp_path = temp_dir.path().to_path_buf();
158 create_fixture_file(&temp_path, "http", "op1", "2024-01-01T12:00:00").unwrap();
159 create_fixture_file(&temp_path, "http", "op2", "2024-01-03T12:00:00").unwrap();
160 create_fixture_file(&temp_path, "http", "op3", "2024-01-02T12:00:00").unwrap();
161
162 let fixtures_root = temp_path.to_str().unwrap();
163 let result = list_all(fixtures_root);
164
165 assert!(result.is_ok());
166 let items = result.unwrap();
167
168 assert_eq!(items.len(), 3);
169 assert!(items[0].saved_at >= items[1].saved_at);
171 assert!(items[1].saved_at >= items[2].saved_at);
172 }
173
174 #[test]
175 fn test_list_all_ignores_non_json_files() {
176 let temp_dir = TempDir::new().unwrap();
177
178 let temp_path = temp_dir.path().to_path_buf();
180 create_fixture_file(&temp_path, "http", "getUser", "2024-01-01T12:00:00").unwrap();
181
182 let txt_path = temp_path.join("http").join("getUser");
183 fs::create_dir_all(&txt_path).unwrap();
184 fs::write(txt_path.join("data.txt"), "not json").unwrap();
185
186 let fixtures_root = temp_path.to_str().unwrap();
187 let result = list_all(fixtures_root);
188
189 assert!(result.is_ok());
190 let items = result.unwrap();
191
192 assert_eq!(items.len(), 1);
194 assert!(items[0].path.ends_with(".json"));
195 }
196
197 #[test]
198 fn test_list_all_extracts_operation_id() {
199 let temp_dir = TempDir::new().unwrap();
200
201 let temp_path = temp_dir.path().to_path_buf();
202 create_fixture_file(&temp_path, "http", "getUserById", "2024-01-01T12:00:00").unwrap();
203
204 let fixtures_root = temp_path.to_str().unwrap();
205 let result = list_all(fixtures_root);
206
207 assert!(result.is_ok());
208 let items = result.unwrap();
209
210 assert_eq!(items.len(), 1);
211 assert_eq!(items[0].operation_id, "getUserById");
212 }
213
214 #[test]
215 fn test_list_all_extracts_timestamp_without_extension() {
216 let temp_dir = TempDir::new().unwrap();
217
218 let temp_path = temp_dir.path().to_path_buf();
219 create_fixture_file(&temp_path, "http", "getUser", "2024-01-01T12:00:00").unwrap();
220
221 let fixtures_root = temp_path.to_str().unwrap();
222 let result = list_all(fixtures_root);
223
224 assert!(result.is_ok());
225 let items = result.unwrap();
226
227 assert_eq!(items.len(), 1);
228 assert_eq!(items[0].saved_at, "2024-01-01T12:00:00");
229 assert!(!items[0].saved_at.contains(".json"));
230 }
231}