forked from
lewis.moe/bspds-sandbox
I've been saying "PDSes seem easy enough, they're what, some CRUD to a db? I can do that in my sleep". well i'm sleeping rn so let's go
1mod common;
2use common::*;
3use reqwest::StatusCode;
4use serde_json::Value;
5
6#[tokio::test]
7async fn test_frontend_client_metadata_returns_valid_json() {
8 let client = client();
9 let res = client
10 .get(format!("{}/oauth/client-metadata.json", base_url().await))
11 .send()
12 .await
13 .expect("Failed to send request");
14 assert_eq!(res.status(), StatusCode::OK);
15 let body: Value = res.json().await.expect("Should return valid JSON");
16 assert!(
17 body["client_id"].as_str().is_some(),
18 "Should have client_id"
19 );
20 assert!(
21 body["client_name"].as_str().is_some(),
22 "Should have client_name"
23 );
24 assert!(
25 body["redirect_uris"].as_array().is_some(),
26 "Should have redirect_uris"
27 );
28 assert!(
29 body["grant_types"].as_array().is_some(),
30 "Should have grant_types"
31 );
32 assert!(
33 body["response_types"].as_array().is_some(),
34 "Should have response_types"
35 );
36 assert!(body["scope"].as_str().is_some(), "Should have scope");
37 assert!(
38 body["token_endpoint_auth_method"].as_str().is_some(),
39 "Should have token_endpoint_auth_method"
40 );
41}
42
43#[tokio::test]
44async fn test_frontend_client_metadata_correct_values() {
45 let client = client();
46 let res = client
47 .get(format!("{}/oauth/client-metadata.json", base_url().await))
48 .send()
49 .await
50 .expect("Failed to send request");
51 assert_eq!(res.status(), StatusCode::OK);
52 let body: Value = res.json().await.unwrap();
53 let client_id = body["client_id"].as_str().unwrap();
54 assert!(
55 client_id.ends_with("/oauth/client-metadata.json"),
56 "client_id should end with /oauth/client-metadata.json"
57 );
58 let grant_types = body["grant_types"].as_array().unwrap();
59 let grant_strs: Vec<&str> = grant_types.iter().filter_map(|v| v.as_str()).collect();
60 assert!(
61 grant_strs.contains(&"authorization_code"),
62 "Should support authorization_code grant"
63 );
64 assert!(
65 grant_strs.contains(&"refresh_token"),
66 "Should support refresh_token grant"
67 );
68 let response_types = body["response_types"].as_array().unwrap();
69 let response_strs: Vec<&str> = response_types.iter().filter_map(|v| v.as_str()).collect();
70 assert!(
71 response_strs.contains(&"code"),
72 "Should support code response type"
73 );
74 assert_eq!(
75 body["token_endpoint_auth_method"].as_str(),
76 Some("none"),
77 "Should be public client (none auth)"
78 );
79 assert_eq!(
80 body["application_type"].as_str(),
81 Some("web"),
82 "Should be web application"
83 );
84 assert_eq!(
85 body["dpop_bound_access_tokens"].as_bool(),
86 Some(true),
87 "AT Protocol requires DPoP-bound access tokens"
88 );
89 let scope = body["scope"].as_str().unwrap();
90 assert!(scope.contains("atproto"), "Scope should include atproto");
91}
92
93#[tokio::test]
94async fn test_frontend_client_metadata_redirect_uri_matches_client_uri() {
95 let client = client();
96 let res = client
97 .get(format!("{}/oauth/client-metadata.json", base_url().await))
98 .send()
99 .await
100 .expect("Failed to send request");
101 assert_eq!(res.status(), StatusCode::OK);
102 let body: Value = res.json().await.unwrap();
103 let client_uri = body["client_uri"].as_str().unwrap();
104 let redirect_uris = body["redirect_uris"].as_array().unwrap();
105 assert!(
106 !redirect_uris.is_empty(),
107 "Should have at least one redirect URI"
108 );
109 let redirect_uri = redirect_uris[0].as_str().unwrap();
110 assert!(
111 redirect_uri.starts_with(client_uri),
112 "Redirect URI should be on same origin as client_uri"
113 );
114}