workspacer_cratesio_mock/
lib.rs1#[macro_use] mod imports; use imports::*;
3
4x!{app_state}
5x!{crates_db}
6x!{protocol}
7x!{publish}
8x!{stored_crate}
9
10#[cfg(test)]
11mod test_publish_integration {
12 use super::*;
13 use rocket::http::{ContentType, Status};
14 use rocket::local::blocking::Client;
15 use rocket::serde::json::serde_json;
16 use tracing::{trace, debug, info};
17 use crate::app_state::AppStateBuilder;
18 use crate::crates_db::MockCratesDb;
19
20
21
22
23 fn setup_rocket() -> Client {
26 trace!("Setting up test rocket instance.");
27
28 let state = AppStateBuilder::default()
29 .db(Arc::new(AsyncMutex::new(MockCratesDb::default())))
30 .build()
31 .unwrap();
32
33 let rocket = rocket::build()
34 .manage(state)
35 .mount("/", rocket::routes![publish_new])
36 .register("/", rocket::catchers![not_found]);
37
38 Client::tracked(rocket).expect("valid rocket instance")
39 }
40
41 #[traced_test]
42 fn test_successful_publish() {
43 trace!("Starting test_successful_publish.");
44
45 let client = setup_rocket();
46 let body = serde_json::json!({
47 "name": "my-crate",
48 "vers": "0.1.0",
49 "description": "A test crate."
50 })
51 .to_string();
52
53 debug!("POST body: {}", body);
54
55 let response = client
56 .post("/api/v1/crates/new")
57 .header(ContentType::JSON)
58 .body(body)
59 .dispatch();
60
61 info!("Response status: {:?}", response.status());
62 assert_eq!(response.status(), Status::Ok);
63
64 let response_json = response.into_json::<serde_json::Value>()
65 .expect("Response should be valid JSON");
66 debug!("Response JSON: {:?}", response_json);
67
68 assert!(response_json.get("ok").and_then(|v| v.as_bool()).unwrap_or(false));
70 }
71
72 #[traced_test]
73 fn test_missing_description() {
74 trace!("Starting test_missing_description.");
75
76 let client = setup_rocket();
77 let body = serde_json::json!({
78 "name": "my-crate",
79 "vers": "0.2.0"
80 })
82 .to_string();
83
84 debug!("POST body: {}", body);
85
86 let response = client
87 .post("/api/v1/crates/new")
88 .header(ContentType::JSON)
89 .body(body)
90 .dispatch();
91
92 info!("Response status: {:?}", response.status());
93 assert_eq!(response.status(), Status::BadRequest);
94
95 let response_json = response.into_json::<serde_json::Value>()
96 .expect("Response should be valid JSON");
97 debug!("Response JSON: {:?}", response_json);
98
99 let errors = response_json
101 .get("errors")
102 .and_then(|v| v.as_array())
103 .expect("Expected 'errors' array in response");
104 let detail = errors[0]
105 .get("detail")
106 .and_then(|v| v.as_str())
107 .unwrap_or("");
108 assert!(
109 detail.contains("description"),
110 "Should complain about missing description"
111 );
112 }
113
114 #[traced_test]
115 fn test_already_published() {
116 trace!("Starting test_already_published.");
117
118 let client = setup_rocket();
119
120 let body = serde_json::json!({
122 "name": "my-crate",
123 "vers": "1.0.0",
124 "description": "Initial publish."
125 })
126 .to_string();
127
128 let first_resp = client
129 .post("/api/v1/crates/new")
130 .header(ContentType::JSON)
131 .body(body.clone())
132 .dispatch();
133 assert_eq!(first_resp.status(), Status::Ok);
134
135 let second_resp = client
137 .post("/api/v1/crates/new")
138 .header(ContentType::JSON)
139 .body(body)
140 .dispatch();
141
142 info!("Response status: {:?}", second_resp.status());
143 assert_eq!(second_resp.status(), Status::BadRequest);
144
145 let response_json = second_resp.into_json::<serde_json::Value>()
146 .expect("Response should be valid JSON");
147 debug!("Response JSON: {:?}", response_json);
148
149 let errors = response_json
150 .get("errors")
151 .and_then(|v| v.as_array())
152 .expect("Expected 'errors' array in response");
153 let detail = errors[0]
154 .get("detail")
155 .and_then(|v| v.as_str())
156 .unwrap_or("");
157 assert!(
158 detail.contains("already exists"),
159 "Should complain about crate already existing"
160 );
161 }
162
163 #[traced_test]
164 fn test_invalid_json_body() {
165 trace!("Starting test_invalid_json_body.");
166
167 let client = setup_rocket();
168
169 let body = "{ invalid-json".to_string();
171 debug!("POST body: {}", body);
172
173 let response = client
174 .post("/api/v1/crates/new")
175 .header(ContentType::JSON)
176 .body(body)
177 .dispatch();
178
179 info!("Response status: {:?}", response.status());
180 assert_eq!(response.status(), Status::BadRequest);
181
182 let response_json = response.into_json::<serde_json::Value>()
183 .expect("Response should be valid JSON");
184 debug!("Response JSON: {:?}", response_json);
185
186 let errors = response_json
187 .get("errors")
188 .and_then(|v| v.as_array())
189 .expect("Expected 'errors' array in response");
190 let detail = errors[0]
191 .get("detail")
192 .and_then(|v| v.as_str())
193 .unwrap_or("");
194 assert!(
195 detail.contains("invalid JSON"),
196 "Should complain about invalid JSON"
197 );
198 }
199
200 #[traced_test]
201 fn test_404_catcher() {
202 trace!("Starting test_404_catcher.");
203
204 let client = setup_rocket();
205 let response = client.get("/this/does/not/exist").dispatch();
206 info!("Response status: {:?}", response.status());
207 assert_eq!(response.status(), Status::NotFound);
208
209 let response_json = response.into_json::<serde_json::Value>()
210 .expect("Response should be valid JSON");
211 debug!("Response JSON: {:?}", response_json);
212
213 let errors = response_json
214 .get("errors")
215 .and_then(|v| v.as_array())
216 .expect("Expected 'errors' array in response");
217 let detail = errors[0]
218 .get("detail")
219 .and_then(|v| v.as_str())
220 .unwrap_or("");
221 assert!(
222 detail.contains("No route for /this/does/not/exist"),
223 "Should contain a 404 message with requested URI"
224 );
225 }
226
227 #[traced_test]
228 fn test_too_large_body() {
229 trace!("Starting test_too_large_body.");
230
231 let size = 11 * 1024 * 1024;
235 let oversized_body = "A".repeat(size);
236
237 let client = setup_rocket();
238 let response = client
239 .post("/api/v1/crates/new")
240 .header(ContentType::JSON)
241 .body(oversized_body)
242 .dispatch();
243
244 info!("Response status: {:?}", response.status());
245 assert_eq!(response.status(), Status::BadRequest);
249
250 let response_json = response.into_json::<serde_json::Value>()
251 .expect("Response should be valid JSON");
252 debug!("Response JSON: {:?}", response_json);
253
254 let errors = response_json
255 .get("errors")
256 .and_then(|v| v.as_array())
257 .expect("Expected 'errors' array in response");
258 let detail = errors[0]
259 .get("detail")
260 .and_then(|v| v.as_str())
261 .unwrap_or("");
262 assert!(
263 detail.contains("Failed reading request body"),
264 "Should mention failed reading body for large input"
265 );
266 }
267}