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}