this repo has no description
1//
2// IdentityResolverTests.swift
3// CoreATProtocol
4//
5// Created by Claude on 2026-01-02.
6//
7
8import Testing
9import Foundation
10@testable import CoreATProtocol
11
12@Suite("Identity Resolver Tests")
13struct IdentityResolverTests {
14
15 // MARK: - DID Document Tests
16
17 @Test("DID Document parses correctly")
18 func testDIDDocumentParsing() throws {
19 let json = """
20 {
21 "@context": ["https://www.w3.org/ns/did/v1"],
22 "id": "did:plc:abc123",
23 "alsoKnownAs": ["at://alice.bsky.social"],
24 "verificationMethod": [{
25 "id": "#atproto",
26 "type": "Multikey",
27 "controller": "did:plc:abc123",
28 "publicKeyMultibase": "zDnae..."
29 }],
30 "service": [{
31 "id": "#atproto_pds",
32 "type": "AtprotoPersonalDataServer",
33 "serviceEndpoint": "https://bsky.social"
34 }]
35 }
36 """.data(using: .utf8)!
37
38 let document = try JSONDecoder().decode(DIDDocument.self, from: json)
39
40 #expect(document.id == "did:plc:abc123")
41 #expect(document.handle == "alice.bsky.social")
42 #expect(document.pdsEndpoint == "https://bsky.social")
43 #expect(document.verificationMethod?.count == 1)
44 #expect(document.service?.count == 1)
45 }
46
47 @Test("DID Document extracts handle from alsoKnownAs")
48 func testHandleExtraction() throws {
49 let document = DIDDocument(
50 id: "did:plc:test",
51 alsoKnownAs: ["at://user.example.com", "https://other.url"],
52 verificationMethod: nil,
53 service: nil
54 )
55
56 #expect(document.handle == "user.example.com")
57 }
58
59 @Test("DID Document returns nil handle when missing")
60 func testMissingHandle() throws {
61 let document = DIDDocument(
62 id: "did:plc:test",
63 alsoKnownAs: nil,
64 verificationMethod: nil,
65 service: nil
66 )
67
68 #expect(document.handle == nil)
69 }
70
71 @Test("PLC Directory response converts to DID Document")
72 func testPLCResponseConversion() throws {
73 let json = """
74 {
75 "did": "did:plc:xyz789",
76 "alsoKnownAs": ["at://bob.test.com"],
77 "verificationMethods": {
78 "#atproto": "did:key:zDnae..."
79 },
80 "services": {
81 "#atproto_pds": {
82 "type": "AtprotoPersonalDataServer",
83 "endpoint": "https://pds.example.com"
84 }
85 }
86 }
87 """.data(using: .utf8)!
88
89 let plcResponse = try JSONDecoder().decode(PLCDirectoryResponse.self, from: json)
90 let document = plcResponse.toDIDDocument()
91
92 #expect(document.id == "did:plc:xyz789")
93 #expect(document.alsoKnownAs?.contains("at://bob.test.com") == true)
94 }
95
96 // MARK: - Identity Error Tests
97
98 @Test("Identity errors are properly typed")
99 func testIdentityErrors() {
100 let handleError = IdentityError.invalidHandle("bad handle")
101 let pdsError = IdentityError.pdsNotFound
102
103 // Test error descriptions
104 #expect(String(describing: handleError).contains("invalidHandle"))
105 #expect(String(describing: pdsError).contains("pdsNotFound"))
106 }
107
108 // MARK: - Handle Validation Tests
109
110 @Test("Valid handles are accepted")
111 func testValidHandles() async throws {
112 // These should be valid handle formats
113 let validHandles = [
114 "alice.bsky.social",
115 "user.example.com",
116 "test.subdomain.domain.tld"
117 ]
118
119 for handle in validHandles {
120 // Just testing the format is accepted
121 let normalized = handle.lowercased()
122 #expect(normalized.contains("."), "\(handle) should contain a dot")
123 }
124 }
125
126 // MARK: - Cache Tests
127
128 @Test("Cache is cleared correctly")
129 func testCacheClear() async {
130 let resolver = await IdentityResolver()
131 await resolver.clearCache()
132 // Should not throw
133 }
134
135 @Test("Cache TTL is configurable")
136 func testCacheTTL() async {
137 let resolver = await IdentityResolver()
138 let defaultTTL = await resolver.cacheTTL
139 #expect(defaultTTL == 600, "Default cache TTL should be 600 seconds")
140
141 await MainActor.run {
142 // Note: Need to access through proper isolation
143 }
144 }
145
146 // MARK: - Protected Resource Metadata Tests
147
148 @Test("Protected resource metadata parses correctly")
149 func testProtectedResourceMetadata() throws {
150 let json = """
151 {
152 "resource": "https://bsky.social",
153 "authorization_servers": ["https://bsky.social"]
154 }
155 """.data(using: .utf8)!
156
157 let metadata = try JSONDecoder().decode(
158 IdentityResolver.ProtectedResourceMetadata.self,
159 from: json
160 )
161
162 #expect(metadata.resource == "https://bsky.social")
163 #expect(metadata.authorizationServers.count == 1)
164 #expect(metadata.authorizationServers.first == "https://bsky.social")
165 }
166}