You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/SessionMessagingKitTests/Database/Models/GroupMemberSpec.swift

203 lines
10 KiB
Swift

// Copyright © 2025 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import SessionUtilitiesKit
import Quick
import Nimble
@testable import SessionMessagingKit
class GroupMemberSpec: QuickSpec {
override class func spec() {
// MARK: - a GroupMember
describe("a GroupMember") {
// MARK: -- when ProfileAssociated
context("when ProfileAssociated") {
// MARK: ---- is sorted correctly
it("is sorted correctly") {
let userSessionId: SessionId = SessionId(.standard, hex: TestConstants.publicKey)
var members: [WithProfile<GroupMember>] = (0..<100).map { index in
WithProfile(
value: GroupMember(
groupId: "TestGroupId",
profileId: "05_(Id\(index < 10 ? "0" : "")\(index))",
role: .standard,
roleStatus: .accepted,
isHidden: false
),
profile: Profile(
id: "05_(Id\(index < 10 ? "0" : "")\(index))",
name: "Name\(index < 10 ? "0" : "")\(index)"
),
currentUserSessionId: userSessionId
)
}
// Update some names so that we can test the name sorting (case, special chars
// non-english, etc.)
members.with(1, name: "Test3")
members.with(2, name: "zName")
members.with(3, name: "test2")
members.with(4, name: "$#@$Name")
members.with(5, name: "TeSt1")
members.with(6, name: "BName")
members.with(7, name: "")
members.with(8, name: "")
// Provide a bunch of different statuses
var statusRandomGenerator: ARC4RandomNumberGenerator = ARC4RandomNumberGenerator(seed: 1234)
let remainingMembers: Double = Double(members.count - 10)
let numberOfStatuses: Int = Int(floor(remainingMembers / Double(GroupMember.RoleStatus.allCases.count)))
let allStatuses: [GroupMember.RoleStatus] = GroupMember.RoleStatus.allCases
.duplicated(count: numberOfStatuses)
.shuffled(using: &statusRandomGenerator)
allStatuses.enumerated().forEach { index, status in
members.with(10 + index, roleStatus: status)
}
// Make a bunch of the users admins
(40..<80).forEach { index in
members.with(index, role: .admin)
}
// Remove some profiles so we can check those
(80..<90).forEach { index in
members.with(index, removedProfile: true)
}
// Make a few of them the current user to check where they get placed
members.with(20, profileId: userSessionId.hexString, name: "You1")
members.with(50, profileId: userSessionId.hexString, name: "You2")
members.with(70, profileId: userSessionId.hexString, name: "You3")
members.with(95, profileId: userSessionId.hexString, name: "You4")
members.with(98, profileId: userSessionId.hexString, name: "You5")
// Sort the members and check that the values are in the expected orders
let sortedMembers: [WithProfile<GroupMember>] = members.sorted()
expect(sortedMembers.map { $0.profile?.name ?? $0.profileId }).to(equal([
"05_(Id87)", "Name15", "Name18", "05_(Id81)", "05_(Id84)",
"Name91", "Name93", "05_(Id80)", "05_(Id82)", "05_(Id89)",
"05_(Id86)", "05_(Id83)", "05_(Id88)", "Name90", "Name40",
"Name44", "Name45", "Name48", "Name49", "Name57",
"Name60", "Name61", "Name67", "Name10", "Name17",
"Name19", "Name23", "Name26", "Name33", "Name39",
"Name63", "Name64", "Name68", "Name72", "Name76",
"Name32", "Name38", "Name43", "Name55", "Name59",
"Name73", "Name75", "Name79", "Name11", "Name16",
"Name22", "Name28", "Name31", "Name36", "Name53",
"Name54", "Name77", "You1", "Name21", "Name25",
"Name30", "Name34", "Name41", "Name51", "Name62",
"Name65", "Name66", "Name74", "Name12", "Name24",
"Name27", "Name29", "Name35", "You2", "Name56",
"Name58", "Name71", "You3", "Name42", "Name46",
"Name47", "Name52", "Name69", "Name78", "You4",
"You5", "05_(Id85)", "$#@$Name", "BName", "Name00",
"Name09", "Name13", "Name14", "Name37", "Name92",
"Name94", "Name96", "Name97", "Name99", "TeSt1",
"test2", "Test3", "zName", "", ""
]))
expect(sortedMembers.map { $0.value.role }).to(equal([
.standard, .standard, .standard, .standard, .standard,
.standard, .standard, .standard, .standard, .standard,
.standard, .standard, .standard, .standard, .admin,
.admin, .admin, .admin, .admin, .admin,
.admin, .admin, .admin, .standard, .standard,
.standard, .standard, .standard, .standard, .standard,
.admin, .admin, .admin, .admin, .admin,
.standard, .standard, .admin, .admin, .admin,
.admin, .admin, .admin, .standard, .standard,
.standard, .standard, .standard, .standard, .admin,
.admin, .admin, .standard, .standard, .standard,
.standard, .standard, .admin, .admin, .admin,
.admin, .admin, .admin, .standard, .standard,
.standard, .standard, .standard, .admin, .admin,
.admin, .admin, .admin, .admin, .admin,
.admin, .admin, .admin, .admin, .standard,
.standard, .standard, .standard, .standard, .standard,
.standard, .standard, .standard, .standard, .standard,
.standard, .standard, .standard, .standard, .standard,
.standard, .standard, .standard, .standard, .standard
]))
expect(sortedMembers.map { $0.value.roleStatus }).to(equal([
.failed, .failed, .failed, .sending, .sending,
.sending, .sending, .pending, .pending, .pending,
.unknown, .pendingRemoval, .pendingRemoval, .pendingRemoval, .failed,
.failed, .failed, .failed, .failed, .failed,
.failed, .failed, .failed, .notSentYet, .notSentYet,
.notSentYet, .notSentYet, .notSentYet, .notSentYet, .notSentYet,
.notSentYet, .notSentYet, .notSentYet, .notSentYet, .notSentYet,
.sending, .sending, .sending, .sending, .sending,
.sending, .sending, .sending, .pending, .pending,
.pending, .pending, .pending, .pending, .pending,
.pending, .pending, .unknown, .unknown, .unknown,
.unknown, .unknown, .unknown, .unknown, .unknown,
.unknown, .unknown, .unknown, .pendingRemoval, .pendingRemoval,
.pendingRemoval, .pendingRemoval, .pendingRemoval, .pendingRemoval, .pendingRemoval,
.pendingRemoval, .pendingRemoval, .accepted, .accepted, .accepted,
.accepted, .accepted, .accepted, .accepted, .accepted,
.accepted, .accepted, .accepted, .accepted, .accepted,
.accepted, .accepted, .accepted, .accepted, .accepted,
.accepted, .accepted, .accepted, .accepted, .accepted,
.accepted, .accepted, .accepted, .accepted, .accepted
]))
let indexesOfCurrentUser: [Int] = sortedMembers.enumerated().reduce(into: []) { result, next in
guard next.element.profileId == userSessionId.hexString else { return }
result.append(next.offset)
}
expect(indexesOfCurrentUser).to(equal([
52, 68, 72, 79, 80
]))
}
}
}
}
}
// MARK: - Convenience
private extension Array {
func duplicated(count: Int) -> [Element] {
guard count > 1 else { return self }
var updated: [Element] = self
(0..<(count - 1)).forEach { _ in updated += self }
return updated
}
}
private extension Array where Element == WithProfile<GroupMember> {
mutating func with(
_ index: Int,
profileId: String? = nil,
name: String? = nil,
removedProfile: Bool = false,
role: GroupMember.Role? = nil,
roleStatus: GroupMember.RoleStatus? = nil
) {
let current: WithProfile<GroupMember> = self[index]
self[index] = WithProfile(
value: GroupMember(
groupId: "TestGroupId",
profileId: (profileId ?? current.profileId),
role: (role ?? current.value.role),
roleStatus: (roleStatus ?? current.value.roleStatus),
isHidden: false
),
profile: (removedProfile ? nil :
current.profile.map { currentProfile in
Profile(
id: (profileId ?? current.profileId),
name: (name ?? currentProfile.name)
)
}
),
currentUserSessionId: current.currentUserSessionId
)
}
}