this repo has no description
1mod common; 2use common::*; 3use reqwest::StatusCode; 4use serde_json::{Value, json}; 5use wiremock::matchers::{method, path}; 6use wiremock::{Mock, MockServer, ResponseTemplate}; 7 8#[tokio::test] 9async fn test_resolve_handle_success() { 10 let client = client(); 11 let handle = format!("resolvetest_{}", uuid::Uuid::new_v4()); 12 let payload = json!({ 13 "handle": handle, 14 "email": format!("{}@example.com", handle), 15 "password": "password" 16 }); 17 18 let res = client 19 .post(format!( 20 "{}/xrpc/com.atproto.server.createAccount", 21 base_url().await 22 )) 23 .json(&payload) 24 .send() 25 .await 26 .expect("Failed to create account"); 27 28 assert_eq!(res.status(), StatusCode::OK); 29 let body: Value = res.json().await.expect("Invalid JSON"); 30 let did = body["did"].as_str().expect("No DID").to_string(); 31 32 let params = [("handle", handle.as_str())]; 33 let res = client 34 .get(format!( 35 "{}/xrpc/com.atproto.identity.resolveHandle", 36 base_url().await 37 )) 38 .query(&params) 39 .send() 40 .await 41 .expect("Failed to send request"); 42 43 assert_eq!(res.status(), StatusCode::OK); 44 let body: Value = res.json().await.expect("Response was not valid JSON"); 45 assert_eq!(body["did"], did); 46} 47 48#[tokio::test] 49async fn test_resolve_handle_not_found() { 50 let client = client(); 51 let params = [("handle", "nonexistent_handle_12345")]; 52 let res = client 53 .get(format!( 54 "{}/xrpc/com.atproto.identity.resolveHandle", 55 base_url().await 56 )) 57 .query(&params) 58 .send() 59 .await 60 .expect("Failed to send request"); 61 62 assert_eq!(res.status(), StatusCode::NOT_FOUND); 63 let body: Value = res.json().await.expect("Response was not valid JSON"); 64 assert_eq!(body["error"], "HandleNotFound"); 65} 66 67#[tokio::test] 68async fn test_resolve_handle_missing_param() { 69 let client = client(); 70 let res = client 71 .get(format!( 72 "{}/xrpc/com.atproto.identity.resolveHandle", 73 base_url().await 74 )) 75 .send() 76 .await 77 .expect("Failed to send request"); 78 79 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 80} 81 82#[tokio::test] 83async fn test_well_known_did() { 84 let client = client(); 85 let res = client 86 .get(format!("{}/.well-known/did.json", base_url().await)) 87 .send() 88 .await 89 .expect("Failed to send request"); 90 91 assert_eq!(res.status(), StatusCode::OK); 92 let body: Value = res.json().await.expect("Response was not valid JSON"); 93 assert!(body["id"].as_str().unwrap().starts_with("did:web:")); 94 assert_eq!(body["service"][0]["type"], "AtprotoPersonalDataServer"); 95} 96 97#[tokio::test] 98async fn test_create_did_web_account_and_resolve() { 99 let client = client(); 100 101 let mock_server = MockServer::start().await; 102 let mock_uri = mock_server.uri(); 103 let mock_addr = mock_uri.trim_start_matches("http://"); 104 105 let did = format!("did:web:{}", mock_addr.replace(":", "%3A")); 106 107 let handle = format!("webuser_{}", uuid::Uuid::new_v4()); 108 109 let pds_endpoint = "https://localhost"; 110 111 let did_doc = json!({ 112 "@context": ["https://www.w3.org/ns/did/v1"], 113 "id": did, 114 "service": [{ 115 "id": "#atproto_pds", 116 "type": "AtprotoPersonalDataServer", 117 "serviceEndpoint": pds_endpoint 118 }] 119 }); 120 121 Mock::given(method("GET")) 122 .and(path("/.well-known/did.json")) 123 .respond_with(ResponseTemplate::new(200).set_body_json(did_doc)) 124 .mount(&mock_server) 125 .await; 126 127 let payload = json!({ 128 "handle": handle, 129 "email": format!("{}@example.com", handle), 130 "password": "password", 131 "did": did 132 }); 133 134 let res = client 135 .post(format!( 136 "{}/xrpc/com.atproto.server.createAccount", 137 base_url().await 138 )) 139 .json(&payload) 140 .send() 141 .await 142 .expect("Failed to send request"); 143 144 if res.status() != StatusCode::OK { 145 let status = res.status(); 146 let body: Value = res 147 .json() 148 .await 149 .unwrap_or(json!({"error": "could not parse body"})); 150 panic!("createAccount failed with status {}: {:?}", status, body); 151 } 152 let body: Value = res 153 .json() 154 .await 155 .expect("createAccount response was not JSON"); 156 assert_eq!(body["did"], did); 157 158 let res = client 159 .get(format!("{}/u/{}/did.json", base_url().await, handle)) 160 .send() 161 .await 162 .expect("Failed to fetch DID doc"); 163 164 assert_eq!(res.status(), StatusCode::OK); 165 let doc: Value = res.json().await.expect("DID doc was not JSON"); 166 167 assert_eq!(doc["id"], did); 168 assert_eq!(doc["alsoKnownAs"][0], format!("at://{}", handle)); 169 assert_eq!(doc["verificationMethod"][0]["controller"], did); 170 assert!(doc["verificationMethod"][0]["publicKeyJwk"].is_object()); 171} 172 173#[tokio::test] 174async fn test_create_account_duplicate_handle() { 175 let client = client(); 176 let handle = format!("dupe_{}", uuid::Uuid::new_v4()); 177 let email = format!("{}@example.com", handle); 178 179 let payload = json!({ 180 "handle": handle, 181 "email": email, 182 "password": "password" 183 }); 184 185 let res = client 186 .post(format!( 187 "{}/xrpc/com.atproto.server.createAccount", 188 base_url().await 189 )) 190 .json(&payload) 191 .send() 192 .await 193 .expect("Failed to send request"); 194 assert_eq!(res.status(), StatusCode::OK); 195 196 let res = client 197 .post(format!( 198 "{}/xrpc/com.atproto.server.createAccount", 199 base_url().await 200 )) 201 .json(&payload) 202 .send() 203 .await 204 .expect("Failed to send request"); 205 206 assert_eq!(res.status(), StatusCode::BAD_REQUEST); 207 let body: Value = res.json().await.expect("Response was not JSON"); 208 assert_eq!(body["error"], "HandleTaken"); 209} 210 211#[tokio::test] 212async fn test_did_web_lifecycle() { 213 let client = client(); 214 let handle = format!("lifecycle_{}", uuid::Uuid::new_v4()); 215 let did = format!("did:web:localhost:u:{}", handle); 216 let email = format!("{}@test.com", handle); 217 218 let create_payload = json!({ 219 "handle": handle, 220 "email": email, 221 "password": "password", 222 "did": did 223 }); 224 225 let res = client 226 .post(format!( 227 "{}/xrpc/com.atproto.server.createAccount", 228 base_url().await 229 )) 230 .json(&create_payload) 231 .send() 232 .await 233 .expect("Failed createAccount"); 234 235 if res.status() != StatusCode::OK { 236 let body: Value = res.json().await.unwrap(); 237 println!("createAccount failed: {:?}", body); 238 panic!("createAccount returned non-200"); 239 } 240 assert_eq!(res.status(), StatusCode::OK); 241 let create_body: Value = res.json().await.expect("Not JSON"); 242 assert_eq!(create_body["did"], did); 243 244 let login_payload = json!({ 245 "identifier": handle, 246 "password": "password" 247 }); 248 let res = client 249 .post(format!( 250 "{}/xrpc/com.atproto.server.createSession", 251 base_url().await 252 )) 253 .json(&login_payload) 254 .send() 255 .await 256 .expect("Failed createSession"); 257 258 assert_eq!(res.status(), StatusCode::OK); 259 let session_body: Value = res.json().await.expect("Not JSON"); 260 let _jwt = session_body["accessJwt"].as_str().unwrap(); 261 262 /* 263 let profile_payload = json!({ 264 "repo": did, 265 "collection": "app.bsky.actor.profile", 266 "rkey": "self", 267 "record": { 268 "$type": "app.bsky.actor.profile", 269 "displayName": "DID Web User", 270 "description": "Testing lifecycle" 271 } 272 }); 273 274 let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", base_url().await)) 275 .bearer_auth(_jwt) 276 .json(&profile_payload) 277 .send() 278 .await 279 .expect("Failed putRecord"); 280 281 if res.status() != StatusCode::OK { 282 let body: Value = res.json().await.unwrap(); 283 println!("putRecord failed: {:?}", body); 284 panic!("putRecord returned non-200"); 285 } 286 assert_eq!(res.status(), StatusCode::OK); 287 288 let res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", base_url().await)) 289 .query(&[ 290 ("repo", &handle), 291 ("collection", &"app.bsky.actor.profile".to_string()), 292 ("rkey", &"self".to_string()) 293 ]) 294 .send() 295 .await 296 .expect("Failed getRecord"); 297 298 if res.status() != StatusCode::OK { 299 let body: Value = res.json().await.unwrap(); 300 println!("getRecord failed: {:?}", body); 301 panic!("getRecord returned non-200"); 302 } 303 let record_body: Value = res.json().await.expect("Not JSON"); 304 assert_eq!(record_body["value"]["displayName"], "DID Web User"); 305 */ 306} 307 308#[tokio::test] 309async fn test_get_recommended_did_credentials_success() { 310 let client = client(); 311 let (access_jwt, _) = create_account_and_login(&client).await; 312 313 let res = client 314 .get(format!( 315 "{}/xrpc/com.atproto.identity.getRecommendedDidCredentials", 316 base_url().await 317 )) 318 .bearer_auth(&access_jwt) 319 .send() 320 .await 321 .expect("Failed to send request"); 322 323 assert_eq!(res.status(), StatusCode::OK); 324 let body: Value = res.json().await.expect("Response was not valid JSON"); 325 assert!(body["rotationKeys"].is_array()); 326 assert!(body["alsoKnownAs"].is_array()); 327 assert!(body["verificationMethods"].is_object()); 328 assert!(body["services"].is_object()); 329 330 let rotation_keys = body["rotationKeys"].as_array().unwrap(); 331 assert!(!rotation_keys.is_empty()); 332 assert!(rotation_keys[0].as_str().unwrap().starts_with("did:key:")); 333 334 let also_known_as = body["alsoKnownAs"].as_array().unwrap(); 335 assert!(!also_known_as.is_empty()); 336 assert!(also_known_as[0].as_str().unwrap().starts_with("at://")); 337 338 assert!(body["verificationMethods"]["atproto"].is_string()); 339 assert_eq!(body["services"]["atprotoPds"]["type"], "AtprotoPersonalDataServer"); 340 assert!(body["services"]["atprotoPds"]["endpoint"].is_string()); 341} 342 343#[tokio::test] 344async fn test_get_recommended_did_credentials_no_auth() { 345 let client = client(); 346 let res = client 347 .get(format!( 348 "{}/xrpc/com.atproto.identity.getRecommendedDidCredentials", 349 base_url().await 350 )) 351 .send() 352 .await 353 .expect("Failed to send request"); 354 355 assert_eq!(res.status(), StatusCode::UNAUTHORIZED); 356 let body: Value = res.json().await.expect("Response was not valid JSON"); 357 assert_eq!(body["error"], "AuthenticationRequired"); 358}