this repo has no description
1mod common;
2mod helpers;
3use common::*;
4use helpers::*;
5
6use reqwest::StatusCode;
7use serde_json::Value;
8
9#[tokio::test]
10async fn test_get_head_success() {
11 let client = client();
12 let (did, _jwt) = setup_new_user("gethead-success").await;
13
14 let res = client
15 .get(format!(
16 "{}/xrpc/com.atproto.sync.getHead",
17 base_url().await
18 ))
19 .query(&[("did", did.as_str())])
20 .send()
21 .await
22 .expect("Failed to send request");
23
24 assert_eq!(res.status(), StatusCode::OK);
25 let body: Value = res.json().await.expect("Response was not valid JSON");
26 assert!(body["root"].is_string());
27 let root = body["root"].as_str().unwrap();
28 assert!(root.starts_with("bafy"), "Root CID should be a CID");
29}
30
31#[tokio::test]
32async fn test_get_head_not_found() {
33 let client = client();
34 let res = client
35 .get(format!(
36 "{}/xrpc/com.atproto.sync.getHead",
37 base_url().await
38 ))
39 .query(&[("did", "did:plc:nonexistent12345")])
40 .send()
41 .await
42 .expect("Failed to send request");
43
44 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
45 let body: Value = res.json().await.expect("Response was not valid JSON");
46 assert_eq!(body["error"], "HeadNotFound");
47 assert!(body["message"].as_str().unwrap().contains("Could not find root"));
48}
49
50#[tokio::test]
51async fn test_get_head_missing_param() {
52 let client = client();
53 let res = client
54 .get(format!(
55 "{}/xrpc/com.atproto.sync.getHead",
56 base_url().await
57 ))
58 .send()
59 .await
60 .expect("Failed to send request");
61
62 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
63}
64
65#[tokio::test]
66async fn test_get_head_empty_did() {
67 let client = client();
68 let res = client
69 .get(format!(
70 "{}/xrpc/com.atproto.sync.getHead",
71 base_url().await
72 ))
73 .query(&[("did", "")])
74 .send()
75 .await
76 .expect("Failed to send request");
77
78 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
79 let body: Value = res.json().await.expect("Response was not valid JSON");
80 assert_eq!(body["error"], "InvalidRequest");
81}
82
83#[tokio::test]
84async fn test_get_head_whitespace_did() {
85 let client = client();
86 let res = client
87 .get(format!(
88 "{}/xrpc/com.atproto.sync.getHead",
89 base_url().await
90 ))
91 .query(&[("did", " ")])
92 .send()
93 .await
94 .expect("Failed to send request");
95
96 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
97}
98
99#[tokio::test]
100async fn test_get_head_changes_after_record_create() {
101 let client = client();
102 let (did, jwt) = setup_new_user("gethead-changes").await;
103
104 let res1 = client
105 .get(format!(
106 "{}/xrpc/com.atproto.sync.getHead",
107 base_url().await
108 ))
109 .query(&[("did", did.as_str())])
110 .send()
111 .await
112 .expect("Failed to get initial head");
113 let body1: Value = res1.json().await.unwrap();
114 let head1 = body1["root"].as_str().unwrap().to_string();
115
116 create_post(&client, &did, &jwt, "Post to change head").await;
117
118 let res2 = client
119 .get(format!(
120 "{}/xrpc/com.atproto.sync.getHead",
121 base_url().await
122 ))
123 .query(&[("did", did.as_str())])
124 .send()
125 .await
126 .expect("Failed to get head after record");
127 let body2: Value = res2.json().await.unwrap();
128 let head2 = body2["root"].as_str().unwrap().to_string();
129
130 assert_ne!(head1, head2, "Head CID should change after record creation");
131}
132
133#[tokio::test]
134async fn test_get_checkout_success() {
135 let client = client();
136 let (did, jwt) = setup_new_user("getcheckout-success").await;
137
138 create_post(&client, &did, &jwt, "Post for checkout test").await;
139
140 let res = client
141 .get(format!(
142 "{}/xrpc/com.atproto.sync.getCheckout",
143 base_url().await
144 ))
145 .query(&[("did", did.as_str())])
146 .send()
147 .await
148 .expect("Failed to send request");
149
150 assert_eq!(res.status(), StatusCode::OK);
151 assert_eq!(
152 res.headers()
153 .get("content-type")
154 .and_then(|h| h.to_str().ok()),
155 Some("application/vnd.ipld.car")
156 );
157 let body = res.bytes().await.expect("Failed to get body");
158 assert!(!body.is_empty(), "CAR file should not be empty");
159 assert!(body.len() > 50, "CAR file should contain actual data");
160}
161
162#[tokio::test]
163async fn test_get_checkout_not_found() {
164 let client = client();
165 let res = client
166 .get(format!(
167 "{}/xrpc/com.atproto.sync.getCheckout",
168 base_url().await
169 ))
170 .query(&[("did", "did:plc:nonexistent12345")])
171 .send()
172 .await
173 .expect("Failed to send request");
174
175 assert_eq!(res.status(), StatusCode::NOT_FOUND);
176 let body: Value = res.json().await.expect("Response was not valid JSON");
177 assert_eq!(body["error"], "RepoNotFound");
178}
179
180#[tokio::test]
181async fn test_get_checkout_missing_param() {
182 let client = client();
183 let res = client
184 .get(format!(
185 "{}/xrpc/com.atproto.sync.getCheckout",
186 base_url().await
187 ))
188 .send()
189 .await
190 .expect("Failed to send request");
191
192 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
193}
194
195#[tokio::test]
196async fn test_get_checkout_empty_did() {
197 let client = client();
198 let res = client
199 .get(format!(
200 "{}/xrpc/com.atproto.sync.getCheckout",
201 base_url().await
202 ))
203 .query(&[("did", "")])
204 .send()
205 .await
206 .expect("Failed to send request");
207
208 assert_eq!(res.status(), StatusCode::BAD_REQUEST);
209}
210
211#[tokio::test]
212async fn test_get_checkout_empty_repo() {
213 let client = client();
214 let (did, _jwt) = setup_new_user("getcheckout-empty").await;
215
216 let res = client
217 .get(format!(
218 "{}/xrpc/com.atproto.sync.getCheckout",
219 base_url().await
220 ))
221 .query(&[("did", did.as_str())])
222 .send()
223 .await
224 .expect("Failed to send request");
225
226 assert_eq!(res.status(), StatusCode::OK);
227 let body = res.bytes().await.expect("Failed to get body");
228 assert!(!body.is_empty(), "Even empty repo should return CAR header");
229}
230
231#[tokio::test]
232async fn test_get_checkout_includes_multiple_records() {
233 let client = client();
234 let (did, jwt) = setup_new_user("getcheckout-multi").await;
235
236 for i in 0..5 {
237 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
238 create_post(&client, &did, &jwt, &format!("Checkout post {}", i)).await;
239 }
240
241 let res = client
242 .get(format!(
243 "{}/xrpc/com.atproto.sync.getCheckout",
244 base_url().await
245 ))
246 .query(&[("did", did.as_str())])
247 .send()
248 .await
249 .expect("Failed to send request");
250
251 assert_eq!(res.status(), StatusCode::OK);
252 let body = res.bytes().await.expect("Failed to get body");
253 assert!(body.len() > 500, "CAR file with 5 records should be larger");
254}
255
256#[tokio::test]
257async fn test_get_head_matches_latest_commit() {
258 let client = client();
259 let (did, _jwt) = setup_new_user("gethead-matches-latest").await;
260
261 let head_res = client
262 .get(format!(
263 "{}/xrpc/com.atproto.sync.getHead",
264 base_url().await
265 ))
266 .query(&[("did", did.as_str())])
267 .send()
268 .await
269 .expect("Failed to get head");
270 let head_body: Value = head_res.json().await.unwrap();
271 let head_root = head_body["root"].as_str().unwrap();
272
273 let latest_res = client
274 .get(format!(
275 "{}/xrpc/com.atproto.sync.getLatestCommit",
276 base_url().await
277 ))
278 .query(&[("did", did.as_str())])
279 .send()
280 .await
281 .expect("Failed to get latest commit");
282 let latest_body: Value = latest_res.json().await.unwrap();
283 let latest_cid = latest_body["cid"].as_str().unwrap();
284
285 assert_eq!(head_root, latest_cid, "getHead root should match getLatestCommit cid");
286}
287
288#[tokio::test]
289async fn test_get_checkout_car_header_valid() {
290 let client = client();
291 let (did, _jwt) = setup_new_user("getcheckout-header").await;
292
293 let res = client
294 .get(format!(
295 "{}/xrpc/com.atproto.sync.getCheckout",
296 base_url().await
297 ))
298 .query(&[("did", did.as_str())])
299 .send()
300 .await
301 .expect("Failed to send request");
302
303 assert_eq!(res.status(), StatusCode::OK);
304 let body = res.bytes().await.expect("Failed to get body");
305
306 assert!(body.len() >= 2, "CAR file should have at least header length");
307}