Rust and WASM did-method-plc tools and structures
1//! Tests for DID document parsing and conversion
2
3use atproto_plc::{Did, DidDocument, PlcState, ServiceEndpoint};
4use std::collections::HashMap;
5
6#[test]
7fn test_plc_state_validation() {
8 let mut state = PlcState::new();
9
10 // Empty state should fail (no rotation keys)
11 assert!(state.validate().is_err());
12
13 // Add rotation key
14 state
15 .rotation_keys
16 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
17 assert!(state.validate().is_ok());
18
19 // Add duplicate rotation key
20 state
21 .rotation_keys
22 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
23 assert!(state.validate().is_err());
24}
25
26#[test]
27fn test_plc_state_too_many_rotation_keys() {
28 let mut state = PlcState::new();
29
30 // Add 6 rotation keys (max is 5)
31 for i in 0..6 {
32 state
33 .rotation_keys
34 .push(format!("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6{}", i));
35 }
36
37 assert!(state.validate().is_err());
38}
39
40#[test]
41fn test_plc_state_too_many_verification_methods() {
42 let mut state = PlcState::new();
43 state
44 .rotation_keys
45 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
46
47 // Add 11 verification methods (max is 10)
48 for i in 0..11 {
49 state.verification_methods.insert(
50 format!("key{}", i),
51 format!("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn{}", i),
52 );
53 }
54
55 assert!(state.validate().is_err());
56}
57
58#[test]
59fn test_service_endpoint_validation() {
60 let valid = ServiceEndpoint::new(
61 "AtprotoPersonalDataServer".to_string(),
62 "https://pds.example.com".to_string(),
63 );
64 assert!(valid.validate().is_ok());
65
66 let empty_type = ServiceEndpoint::new(String::new(), "https://example.com".to_string());
67 assert!(empty_type.validate().is_err());
68
69 let empty_endpoint = ServiceEndpoint::new("SomeService".to_string(), String::new());
70 assert!(empty_endpoint.validate().is_err());
71}
72
73#[test]
74fn test_did_document_from_plc_state() {
75 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap();
76 let mut state = PlcState::new();
77
78 state
79 .rotation_keys
80 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
81
82 state.verification_methods.insert(
83 "atproto".to_string(),
84 "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169".to_string(),
85 );
86
87 state
88 .also_known_as
89 .push("at://alice.bsky.social".to_string());
90
91 state.services.insert(
92 "atproto_pds".to_string(),
93 ServiceEndpoint::new(
94 "AtprotoPersonalDataServer".to_string(),
95 "https://pds.example.com".to_string(),
96 ),
97 );
98
99 let doc = state.to_did_document(&did);
100
101 assert_eq!(doc.id, did);
102 assert_eq!(doc.verification_method.len(), 1);
103 assert_eq!(doc.also_known_as.len(), 1);
104 assert_eq!(doc.service.len(), 1);
105 assert!(!doc.context.is_empty());
106}
107
108#[test]
109fn test_did_document_serialization() {
110 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap();
111 let mut state = PlcState::new();
112 state
113 .rotation_keys
114 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
115
116 let doc = state.to_did_document(&did);
117
118 // Serialize to JSON
119 let json = serde_json::to_string_pretty(&doc).unwrap();
120 assert!(json.contains("\"@context\""));
121 assert!(json.contains("did:plc:ewvi7nxzyoun6zhxrhs64oiz"));
122
123 // Deserialize back
124 let deserialized: DidDocument = serde_json::from_str(&json).unwrap();
125 assert_eq!(doc, deserialized);
126}
127
128#[test]
129fn test_plc_state_serialization() {
130 let mut state = PlcState::new();
131 state
132 .rotation_keys
133 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
134
135 // Serialize
136 let json = serde_json::to_string(&state).unwrap();
137 assert!(json.contains("rotationKeys"));
138
139 // Deserialize
140 let deserialized: PlcState = serde_json::from_str(&json).unwrap();
141 assert_eq!(state, deserialized);
142}
143
144#[test]
145fn test_did_document_to_plc_state_conversion() {
146 let did = Did::parse("did:plc:ewvi7nxzyoun6zhxrhs64oiz").unwrap();
147 let mut original_state = PlcState::new();
148 original_state
149 .rotation_keys
150 .push("did:key:zQ3shZc2QzApp2oymGvQbzP8eKheVshBHbU4ZYjeXqwSKEn6N".to_string());
151 original_state.verification_methods.insert(
152 "atproto".to_string(),
153 "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169".to_string(),
154 );
155
156 // Convert to DID document and back
157 let doc = original_state.to_did_document(&did);
158 let converted_state = doc.to_plc_state().unwrap();
159
160 // Note: rotation_keys are not stored in DID document, so they won't round-trip
161 assert_eq!(
162 original_state.verification_methods,
163 converted_state.verification_methods
164 );
165}