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_search_accounts_as_admin() {
10 let client = client();
11 let (admin_jwt, _) = create_admin_account_and_login(&client).await;
12 let (user_did, _) = setup_new_user("search-target").await;
13 let mut found = false;
14 let mut cursor: Option<String> = None;
15 for _ in 0..10 {
16 let url = match &cursor {
17 Some(c) => format!(
18 "{}/xrpc/com.atproto.admin.searchAccounts?limit=100&cursor={}",
19 base_url().await,
20 c
21 ),
22 None => format!(
23 "{}/xrpc/com.atproto.admin.searchAccounts?limit=100",
24 base_url().await
25 ),
26 };
27 let res = client
28 .get(&url)
29 .bearer_auth(&admin_jwt)
30 .send()
31 .await
32 .expect("Failed to send request");
33 assert_eq!(res.status(), StatusCode::OK);
34 let body: Value = res.json().await.unwrap();
35 let accounts = body["accounts"]
36 .as_array()
37 .expect("accounts should be array");
38 if accounts
39 .iter()
40 .any(|a| a["did"].as_str() == Some(&user_did))
41 {
42 found = true;
43 break;
44 }
45 cursor = body["cursor"].as_str().map(|s| s.to_string());
46 if cursor.is_none() {
47 break;
48 }
49 }
50 assert!(
51 found,
52 "Should find the created user in results (DID: {})",
53 user_did
54 );
55}
56
57#[tokio::test]
58async fn test_search_accounts_with_handle_filter() {
59 let client = client();
60 let (admin_jwt, _) = create_admin_account_and_login(&client).await;
61 let ts = chrono::Utc::now().timestamp_millis();
62 let unique_handle = format!("unique-handle-{}.test", ts);
63 let create_payload = serde_json::json!({
64 "handle": unique_handle,
65 "email": format!("unique-{}@searchtest.com", ts),
66 "password": "Testpass123!"
67 });
68 let create_res = client
69 .post(format!(
70 "{}/xrpc/com.atproto.server.createAccount",
71 base_url().await
72 ))
73 .json(&create_payload)
74 .send()
75 .await
76 .expect("Failed to create account");
77 assert_eq!(create_res.status(), StatusCode::OK);
78 let res = client
79 .get(format!(
80 "{}/xrpc/com.atproto.admin.searchAccounts?handle={}",
81 base_url().await,
82 unique_handle
83 ))
84 .bearer_auth(&admin_jwt)
85 .send()
86 .await
87 .expect("Failed to send request");
88 assert_eq!(res.status(), StatusCode::OK);
89 let body: Value = res.json().await.unwrap();
90 let accounts = body["accounts"].as_array().unwrap();
91 assert_eq!(
92 accounts.len(),
93 1,
94 "Should find exactly one account with this handle"
95 );
96 assert_eq!(accounts[0]["handle"].as_str(), Some(unique_handle.as_str()));
97}
98
99#[tokio::test]
100async fn test_search_accounts_pagination() {
101 let client = client();
102 let (admin_jwt, _) = create_admin_account_and_login(&client).await;
103 for i in 0..3 {
104 let _ = setup_new_user(&format!("search-page-{}", i)).await;
105 }
106 let res = client
107 .get(format!(
108 "{}/xrpc/com.atproto.admin.searchAccounts?limit=2",
109 base_url().await
110 ))
111 .bearer_auth(&admin_jwt)
112 .send()
113 .await
114 .expect("Failed to send request");
115 assert_eq!(res.status(), StatusCode::OK);
116 let body: Value = res.json().await.unwrap();
117 let accounts = body["accounts"].as_array().unwrap();
118 assert_eq!(accounts.len(), 2, "Should return exactly 2 accounts");
119 let cursor = body["cursor"].as_str();
120 assert!(cursor.is_some(), "Should have cursor for more results");
121 let res2 = client
122 .get(format!(
123 "{}/xrpc/com.atproto.admin.searchAccounts?limit=2&cursor={}",
124 base_url().await,
125 cursor.unwrap()
126 ))
127 .bearer_auth(&admin_jwt)
128 .send()
129 .await
130 .expect("Failed to send request");
131 assert_eq!(res2.status(), StatusCode::OK);
132 let body2: Value = res2.json().await.unwrap();
133 let accounts2 = body2["accounts"].as_array().unwrap();
134 assert!(
135 !accounts2.is_empty(),
136 "Should return more accounts after cursor"
137 );
138 let first_page_dids: Vec<&str> = accounts
139 .iter()
140 .map(|a| a["did"].as_str().unwrap())
141 .collect();
142 let second_page_dids: Vec<&str> = accounts2
143 .iter()
144 .map(|a| a["did"].as_str().unwrap())
145 .collect();
146 for did in &second_page_dids {
147 assert!(
148 !first_page_dids.contains(did),
149 "Second page should not repeat first page DIDs"
150 );
151 }
152}
153
154#[tokio::test]
155async fn test_search_accounts_requires_admin() {
156 let client = client();
157 let _ = create_account_and_login(&client).await;
158 let (_, user_jwt) = setup_new_user("search-nonadmin").await;
159 let res = client
160 .get(format!(
161 "{}/xrpc/com.atproto.admin.searchAccounts",
162 base_url().await
163 ))
164 .bearer_auth(&user_jwt)
165 .send()
166 .await
167 .expect("Failed to send request");
168 assert_eq!(res.status(), StatusCode::FORBIDDEN);
169}
170
171#[tokio::test]
172async fn test_search_accounts_requires_auth() {
173 let client = client();
174 let res = client
175 .get(format!(
176 "{}/xrpc/com.atproto.admin.searchAccounts",
177 base_url().await
178 ))
179 .send()
180 .await
181 .expect("Failed to send request");
182 assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
183}
184
185#[tokio::test]
186async fn test_search_accounts_returns_expected_fields() {
187 let client = client();
188 let (admin_jwt, _) = create_admin_account_and_login(&client).await;
189 let _ = setup_new_user("search-fields").await;
190 let res = client
191 .get(format!(
192 "{}/xrpc/com.atproto.admin.searchAccounts?limit=1",
193 base_url().await
194 ))
195 .bearer_auth(&admin_jwt)
196 .send()
197 .await
198 .expect("Failed to send request");
199 assert_eq!(res.status(), StatusCode::OK);
200 let body: Value = res.json().await.unwrap();
201 let accounts = body["accounts"].as_array().unwrap();
202 assert!(!accounts.is_empty());
203 let account = &accounts[0];
204 assert!(account["did"].as_str().is_some(), "Should have did");
205 assert!(account["handle"].as_str().is_some(), "Should have handle");
206 assert!(
207 account["indexedAt"].as_str().is_some(),
208 "Should have indexedAt"
209 );
210}