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}