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