mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
e5bfc3a26d
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
174 lines
5.8 KiB
Swift
174 lines
5.8 KiB
Swift
//
|
|
// 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 HealthChatAPIModelsTests {
|
|
@Test
|
|
func decodesMemberFromFullJSON() throws {
|
|
let json = """
|
|
{
|
|
"userId": "@alice:healthchat.ch",
|
|
"displayName": "Dr. Alice Alpha",
|
|
"avatarMxcUrl": "mxc://healthchat.ch/abc123",
|
|
"title": "Dr. med.",
|
|
"firstName": "Alice",
|
|
"lastName": "Alpha",
|
|
"specialty": "Physiotherapie",
|
|
"practiceName": "Praxis Alpha",
|
|
"businessCity": "Zürich",
|
|
"businessEmail": "praxis@example.ch",
|
|
"businessTel": "+41 44 123 45 67",
|
|
"furtherInfo": "Info",
|
|
"street": "Friedaustrasse",
|
|
"houseNumber": "17",
|
|
"postalCode": "8003",
|
|
"website": "https://example.ch",
|
|
"isApproved": true,
|
|
"someFutureField": { "nested": true }
|
|
}
|
|
"""
|
|
|
|
let member = try JSONDecoder().decode(HealthChatMember.self, from: Data(json.utf8))
|
|
|
|
#expect(member.userID == "@alice:healthchat.ch")
|
|
#expect(member.id == "@alice:healthchat.ch")
|
|
#expect(member.displayName == "Dr. Alice Alpha")
|
|
#expect(member.avatarURL == URL(string: "mxc://healthchat.ch/abc123"))
|
|
#expect(member.title == "Dr. med.")
|
|
#expect(member.firstName == "Alice")
|
|
#expect(member.lastName == "Alpha")
|
|
#expect(member.specialty == "Physiotherapie")
|
|
#expect(member.practiceName == "Praxis Alpha")
|
|
#expect(member.businessCity == "Zürich")
|
|
#expect(member.businessEmail == "praxis@example.ch")
|
|
#expect(member.businessTel == "+41 44 123 45 67")
|
|
#expect(member.furtherInfo == "Info")
|
|
#expect(member.street == "Friedaustrasse")
|
|
#expect(member.houseNumber == "17")
|
|
#expect(member.postalCode == "8003")
|
|
#expect(member.website == "https://example.ch")
|
|
#expect(member.isApproved)
|
|
}
|
|
|
|
@Test
|
|
func decodesMinimalMemberWithDefaults() throws {
|
|
let json = """
|
|
{ "userId": "@bob:healthchat.ch" }
|
|
"""
|
|
|
|
let member = try JSONDecoder().decode(HealthChatMember.self, from: Data(json.utf8))
|
|
|
|
#expect(member.userID == "@bob:healthchat.ch")
|
|
#expect(member.displayName == nil)
|
|
#expect(member.avatarURL == nil)
|
|
#expect(member.isApproved)
|
|
}
|
|
|
|
@Test
|
|
func emptyStringsBecomeNil() throws {
|
|
let json = """
|
|
{
|
|
"userId": "@bob:healthchat.ch",
|
|
"displayName": "",
|
|
"avatarMxcUrl": "",
|
|
"businessTel": ""
|
|
}
|
|
"""
|
|
|
|
let member = try JSONDecoder().decode(HealthChatMember.self, from: Data(json.utf8))
|
|
|
|
#expect(member.displayName == nil)
|
|
#expect(member.avatarURL == nil)
|
|
#expect(member.businessTel == nil)
|
|
}
|
|
|
|
@Test
|
|
func decodesMembersResponse() throws {
|
|
let json = """
|
|
{
|
|
"users": [{ "userId": "@alice:healthchat.ch" }],
|
|
"totalCount": 1,
|
|
"searchQuery": "",
|
|
"isApproved": true,
|
|
"pendingMessage": null
|
|
}
|
|
"""
|
|
|
|
let response = try JSONDecoder().decode(HealthChatMembersResponse.self, from: Data(json.utf8))
|
|
|
|
#expect(response.users.count == 1)
|
|
#expect(response.users.first?.userID == "@alice:healthchat.ch")
|
|
#expect(response.isApproved)
|
|
#expect(response.pendingMessage == nil)
|
|
}
|
|
|
|
@Test
|
|
func decodesPendingMembersResponse() throws {
|
|
let json = """
|
|
{
|
|
"users": [],
|
|
"isApproved": false,
|
|
"pendingMessage": "Ihr Konto wird geprüft"
|
|
}
|
|
"""
|
|
|
|
let response = try JSONDecoder().decode(HealthChatMembersResponse.self, from: Data(json.utf8))
|
|
|
|
#expect(response.users.isEmpty)
|
|
#expect(!response.isApproved)
|
|
#expect(response.pendingMessage == "Ihr Konto wird geprüft")
|
|
}
|
|
|
|
@Test
|
|
func profileUpdateEncodesOnlySetFields() throws {
|
|
var update = HealthChatProfileUpdate()
|
|
update.businessTel = "+41 44 123 45 67"
|
|
update.specialty = "Physiotherapie"
|
|
update.furtherInfo = ""
|
|
|
|
let data = try JSONEncoder().encode(update)
|
|
let object = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any])
|
|
|
|
#expect(object.keys.sorted() == ["businessTel", "furtherInfo", "specialty"])
|
|
#expect(object["businessTel"] as? String == "+41 44 123 45 67")
|
|
#expect(object["specialty"] as? String == "Physiotherapie")
|
|
#expect(object["furtherInfo"] as? String == "")
|
|
}
|
|
|
|
@Test
|
|
func decodesProfileCompleteness() throws {
|
|
let json = """
|
|
{
|
|
"isComplete": false,
|
|
"missingFields": ["Fachgebiet", "Ort"],
|
|
"message": "Profil unvollständig",
|
|
"hasProfilePhoto": true
|
|
}
|
|
"""
|
|
|
|
let completeness = try JSONDecoder().decode(HealthChatProfileCompleteness.self, from: Data(json.utf8))
|
|
|
|
#expect(!completeness.isComplete)
|
|
#expect(completeness.missingFields == ["Fachgebiet", "Ort"])
|
|
#expect(completeness.message == "Profil unvollständig")
|
|
#expect(completeness.hasProfilePhoto)
|
|
}
|
|
|
|
@Test
|
|
func decodesProfileCompletenessWithDefaults() throws {
|
|
let completeness = try JSONDecoder().decode(HealthChatProfileCompleteness.self, from: Data("{}".utf8))
|
|
|
|
#expect(!completeness.isComplete)
|
|
#expect(completeness.missingFields.isEmpty)
|
|
#expect(completeness.message == nil)
|
|
#expect(!completeness.hasProfilePhoto)
|
|
}
|
|
}
|