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}