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