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