mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-10-31 16:24:11 +00:00
00f08ab2dc
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
150 lines
5.2 KiB
Swift
150 lines
5.2 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 ExtendedProfileTests {
|
|
@Test
|
|
func decodesFullProfile() throws {
|
|
let json = """
|
|
{
|
|
"displayname": "Dr. Alice Alpha",
|
|
"avatar_url": "mxc://healthchat.ch/abc123",
|
|
"io.element.profile.title": "Dr. med.",
|
|
"io.element.profile.first_name": "Alice",
|
|
"io.element.profile.last_name": "Alpha",
|
|
"io.element.profile.specialization": "Physiotherapie",
|
|
"io.element.profile.practice_name": "Praxis Alpha",
|
|
"io.element.profile.further_info": "Multi\\nline",
|
|
"io.element.profile.business_email": "praxis@example.ch",
|
|
"io.element.profile.business_tel": "+41 44 123 45 67",
|
|
"io.element.profile.business_street": "Friedaustrasse",
|
|
"io.element.profile.business_street_nr": "17",
|
|
"io.element.profile.business_plz": "8003",
|
|
"io.element.profile.business_city": "Zürich",
|
|
"io.element.profile.website": "https://example.ch"
|
|
}
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.displayName == "Dr. Alice Alpha")
|
|
#expect(profile.avatarURL == URL(string: "mxc://healthchat.ch/abc123"))
|
|
#expect(profile.title == "Dr. med.")
|
|
#expect(profile.firstName == "Alice")
|
|
#expect(profile.lastName == "Alpha")
|
|
#expect(profile.specialty == "Physiotherapie")
|
|
#expect(profile.practiceName == "Praxis Alpha")
|
|
#expect(profile.furtherInfo == "Multi\nline")
|
|
#expect(profile.businessEmail == "praxis@example.ch")
|
|
#expect(profile.businessTel == "+41 44 123 45 67")
|
|
#expect(profile.street == "Friedaustrasse")
|
|
#expect(profile.houseNumber == "17")
|
|
#expect(profile.postalCode == "8003")
|
|
#expect(profile.city == "Zürich")
|
|
#expect(profile.website == "https://example.ch")
|
|
#expect(profile.hasContent)
|
|
}
|
|
|
|
@Test
|
|
func decodesLegacyAddressKeysAsFallback() throws {
|
|
let json = """
|
|
{
|
|
"io.element.profile.street": "Altweg",
|
|
"io.element.profile.house_number": "3",
|
|
"io.element.profile.postal_code": "9000"
|
|
}
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.street == "Altweg")
|
|
#expect(profile.houseNumber == "3")
|
|
#expect(profile.postalCode == "9000")
|
|
}
|
|
|
|
@Test
|
|
func canonicalKeyPresenceWinsOverLegacyEvenWhenEmpty() throws {
|
|
let json = """
|
|
{
|
|
"io.element.profile.business_street": "",
|
|
"io.element.profile.street": "Altweg"
|
|
}
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.street == nil)
|
|
}
|
|
|
|
@Test
|
|
func emptyAndNonStringValuesBecomeNil() throws {
|
|
let json = """
|
|
{
|
|
"displayname": "Alice",
|
|
"io.element.profile.title": "",
|
|
"io.element.profile.specialization": 5,
|
|
"us.cloke.msc4175.tz": "Europe/Zurich"
|
|
}
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.title == nil)
|
|
#expect(profile.specialty == nil)
|
|
#expect(!profile.hasContent)
|
|
}
|
|
|
|
@Test
|
|
func hasContentWithSingleField() throws {
|
|
let json = """
|
|
{ "io.element.profile.business_tel": "+41 44 123 45 67" }
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.hasContent)
|
|
}
|
|
|
|
@Test
|
|
func formattedAddressWithAllComponents() throws {
|
|
let json = """
|
|
{
|
|
"io.element.profile.business_street": "Friedaustrasse",
|
|
"io.element.profile.business_street_nr": "17",
|
|
"io.element.profile.business_plz": "8003",
|
|
"io.element.profile.business_city": "Zürich"
|
|
}
|
|
"""
|
|
|
|
let profile = try JSONDecoder().decode(ExtendedProfile.self, from: Data(json.utf8))
|
|
|
|
#expect(profile.formattedAddress == "Friedaustrasse 17, 8003 Zürich")
|
|
}
|
|
|
|
@Test
|
|
func formattedAddressWithPartialComponents() throws {
|
|
let cityOnly = try JSONDecoder().decode(ExtendedProfile.self, from: Data("""
|
|
{
|
|
"io.element.profile.business_plz": "8003",
|
|
"io.element.profile.business_city": "Zürich"
|
|
}
|
|
""".utf8))
|
|
#expect(cityOnly.formattedAddress == "8003 Zürich")
|
|
|
|
let streetOnly = try JSONDecoder().decode(ExtendedProfile.self, from: Data("""
|
|
{ "io.element.profile.business_street": "Friedaustrasse" }
|
|
""".utf8))
|
|
#expect(streetOnly.formattedAddress == "Friedaustrasse")
|
|
|
|
let empty = try JSONDecoder().decode(ExtendedProfile.self, from: Data("{}".utf8))
|
|
#expect(empty.formattedAddress == nil)
|
|
}
|
|
}
|