mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 06:55:59 +00:00
Add HealthChat API and extended profile services (#9)
Expose OpenID tokens and homeserver credentials from the client proxy, and add fork-only services for the HealthChat member directory backend (api.healthchat.ch) plus a service that reads MSC4133 extended profile fields directly from the homeserver. Groundwork for the members tab and the profile screens. Claude-Session: https://claude.ai/code/session_013qdTbAWsZj2quQzEkagXaS
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// 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 Testing
|
||||
|
||||
final class HealthChatOpenIDTokenProviderTests {
|
||||
private let clientProxy = ClientProxyMock(.init())
|
||||
|
||||
@Test
|
||||
func fetchesTokenOnFirstCall() async {
|
||||
clientProxy.requestOpenIDTokenReturnValue = .success(.init(accessToken: "tokenA",
|
||||
matrixServerName: "healthchat.ch",
|
||||
expiresIn: 3600))
|
||||
let provider = HealthChatOpenIDTokenProvider(clientProxy: clientProxy)
|
||||
|
||||
let result = await provider.validToken()
|
||||
|
||||
#expect(result == .success("tokenA"))
|
||||
#expect(clientProxy.requestOpenIDTokenCallsCount == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
func cachesTokenUntilExpiry() async {
|
||||
clientProxy.requestOpenIDTokenReturnValue = .success(.init(accessToken: "tokenA",
|
||||
matrixServerName: "healthchat.ch",
|
||||
expiresIn: 3600))
|
||||
let provider = HealthChatOpenIDTokenProvider(clientProxy: clientProxy)
|
||||
|
||||
_ = await provider.validToken()
|
||||
let result = await provider.validToken()
|
||||
|
||||
#expect(result == .success("tokenA"))
|
||||
#expect(clientProxy.requestOpenIDTokenCallsCount == 1)
|
||||
}
|
||||
|
||||
@Test
|
||||
func refreshesTokenWithinExpiryBuffer() async {
|
||||
clientProxy.requestOpenIDTokenReturnValue = .success(.init(accessToken: "tokenA",
|
||||
matrixServerName: "healthchat.ch",
|
||||
expiresIn: 120))
|
||||
var now = Date(timeIntervalSince1970: 1_000_000)
|
||||
let provider = HealthChatOpenIDTokenProvider(clientProxy: clientProxy) { now }
|
||||
|
||||
_ = await provider.validToken()
|
||||
|
||||
// 59s of validity left is inside the 60s buffer and must trigger a refresh.
|
||||
now = now.addingTimeInterval(61)
|
||||
clientProxy.requestOpenIDTokenReturnValue = .success(.init(accessToken: "tokenB",
|
||||
matrixServerName: "healthchat.ch",
|
||||
expiresIn: 120))
|
||||
let result = await provider.validToken()
|
||||
|
||||
#expect(result == .success("tokenB"))
|
||||
#expect(clientProxy.requestOpenIDTokenCallsCount == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
func invalidateForcesRefetch() async {
|
||||
clientProxy.requestOpenIDTokenReturnValue = .success(.init(accessToken: "tokenA",
|
||||
matrixServerName: "healthchat.ch",
|
||||
expiresIn: 3600))
|
||||
let provider = HealthChatOpenIDTokenProvider(clientProxy: clientProxy)
|
||||
|
||||
_ = await provider.validToken()
|
||||
provider.invalidateToken()
|
||||
_ = await provider.validToken()
|
||||
|
||||
#expect(clientProxy.requestOpenIDTokenCallsCount == 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
func failedRequestReturnsTokenAcquisitionFailure() async {
|
||||
clientProxy.requestOpenIDTokenReturnValue = .failure(.sdkError(ClientProxyMockError.generic))
|
||||
let provider = HealthChatOpenIDTokenProvider(clientProxy: clientProxy)
|
||||
|
||||
let result = await provider.validToken()
|
||||
|
||||
#expect(result == .failure(.tokenAcquisitionFailed))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user