// // Copyright 2026 Element Creations Ltd. // // SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial. // Please see LICENSE files in the repository root for full details. // @testable import ElementX import Foundation import Synchronization import Testing final class ExtendedProfileServiceTests { private let clientProxy = ClientProxyMock(.init()) private let service: ExtendedProfileService init() { let configuration = URLSessionConfiguration.ephemeral configuration.protocolClasses = [MockProfileURLProtocol.self] service = ExtendedProfileService(clientProxy: clientProxy, urlSession: URLSession(configuration: configuration)) clientProxy.homeserverCredentialsReturnValue = .success(.init(homeserverURL: "https://matrix.example.com", accessToken: MockProfileURLProtocol.accessToken)) } @Test func fetchesProfileWithBearerToken() async throws { let result = await service.profile(for: "@alice:healthchat.ch") let profile = try result.get() #expect(profile.displayName == "Dr. Alice Alpha") #expect(profile.businessTel == "+41 44 123 45 67") let request = try #require(MockProfileURLProtocol.lastRequest) #expect(request.url?.path(percentEncoded: false) == "/_matrix/client/v3/profile/@alice:healthchat.ch") #expect(request.value(forHTTPHeaderField: "Authorization") == "Bearer \(MockProfileURLProtocol.accessToken)") } @Test func missingCredentialsFailWithoutRequest() async { clientProxy.homeserverCredentialsReturnValue = .failure(.sdkError(ClientProxyMockError.generic)) let result = await service.profile(for: "@alice:healthchat.ch") #expect(result == .failure(.missingCredentials)) } @Test func unknownUserFailsWithHTTPStatus() async { let result = await service.profile(for: "@unknown:healthchat.ch") #expect(result == .failure(.httpStatus(404))) } @Test func credentialsDescriptionRedactsAccessToken() { let credentials = HomeserverCredentials(homeserverURL: "https://matrix.example.com", accessToken: "supersecret") #expect(!String(describing: credentials).contains("supersecret")) } } // MARK: - MockProfileURLProtocol private nonisolated class MockProfileURLProtocol: URLProtocol { static let accessToken = "testAccessToken" private static let _lastRequest: Mutex = .init(nil) static var lastRequest: URLRequest? { _lastRequest.withLock { $0 } } private static let profileJSON = """ { "displayname": "Dr. Alice Alpha", "io.element.profile.business_tel": "+41 44 123 45 67" } """ private static let responses: [String: (Int, Data)] = [ "/_matrix/client/v3/profile/@alice:healthchat.ch": (200, Data(profileJSON.utf8)) ] override func startLoading() { MockProfileURLProtocol._lastRequest.withLock { $0 = request } guard let url = request.url else { client?.urlProtocol(self, didFailWithError: URLError(.badURL)) return } let isAuthenticated = request.value(forHTTPHeaderField: "Authorization") == "Bearer \(MockProfileURLProtocol.accessToken)" let path = url.path(percentEncoded: false) let (statusCode, data) = isAuthenticated ? MockProfileURLProtocol.responses[path] ?? (404, Data()) : (401, Data()) guard let response = HTTPURLResponse(url: url, statusCode: statusCode, httpVersion: nil, headerFields: nil) else { client?.urlProtocol(self, didFailWithError: URLError(.badServerResponse)) return } client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) client?.urlProtocol(self, didLoad: data) client?.urlProtocolDidFinishLoading(self) } override func stopLoading() { } override class func canonicalRequest(for request: URLRequest) -> URLRequest { request } override class func canInit(with request: URLRequest) -> Bool { true } }