diff --git a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift index 435e5ea3e..7c2b9a81c 100644 --- a/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift +++ b/ElementX/Sources/Mocks/Generated/GeneratedMocks.swift @@ -16618,15 +16618,15 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } //MARK: - joinedParents - var joinedParentsRoomIDUnderlyingCallsCount = 0 - var joinedParentsRoomIDCallsCount: Int { + var joinedParentsChildIDUnderlyingCallsCount = 0 + var joinedParentsChildIDCallsCount: Int { get { if Thread.isMainThread { - return joinedParentsRoomIDUnderlyingCallsCount + return joinedParentsChildIDUnderlyingCallsCount } else { var returnValue: Int? = nil DispatchQueue.main.sync { - returnValue = joinedParentsRoomIDUnderlyingCallsCount + returnValue = joinedParentsChildIDUnderlyingCallsCount } return returnValue! @@ -16634,29 +16634,29 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } set { if Thread.isMainThread { - joinedParentsRoomIDUnderlyingCallsCount = newValue + joinedParentsChildIDUnderlyingCallsCount = newValue } else { DispatchQueue.main.sync { - joinedParentsRoomIDUnderlyingCallsCount = newValue + joinedParentsChildIDUnderlyingCallsCount = newValue } } } } - var joinedParentsRoomIDCalled: Bool { - return joinedParentsRoomIDCallsCount > 0 + var joinedParentsChildIDCalled: Bool { + return joinedParentsChildIDCallsCount > 0 } - var joinedParentsRoomIDReceivedRoomID: String? - var joinedParentsRoomIDReceivedInvocations: [String] = [] + var joinedParentsChildIDReceivedChildID: String? + var joinedParentsChildIDReceivedInvocations: [String] = [] - var joinedParentsRoomIDUnderlyingReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! - var joinedParentsRoomIDReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! { + var joinedParentsChildIDUnderlyingReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! + var joinedParentsChildIDReturnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>! { get { if Thread.isMainThread { - return joinedParentsRoomIDUnderlyingReturnValue + return joinedParentsChildIDUnderlyingReturnValue } else { var returnValue: Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>? = nil DispatchQueue.main.sync { - returnValue = joinedParentsRoomIDUnderlyingReturnValue + returnValue = joinedParentsChildIDUnderlyingReturnValue } return returnValue! @@ -16664,26 +16664,26 @@ class SpaceServiceProxyMock: SpaceServiceProxyProtocol, @unchecked Sendable { } set { if Thread.isMainThread { - joinedParentsRoomIDUnderlyingReturnValue = newValue + joinedParentsChildIDUnderlyingReturnValue = newValue } else { DispatchQueue.main.sync { - joinedParentsRoomIDUnderlyingReturnValue = newValue + joinedParentsChildIDUnderlyingReturnValue = newValue } } } } - var joinedParentsRoomIDClosure: ((String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>)? + var joinedParentsChildIDClosure: ((String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError>)? - func joinedParents(roomID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { - joinedParentsRoomIDCallsCount += 1 - joinedParentsRoomIDReceivedRoomID = roomID + func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { + joinedParentsChildIDCallsCount += 1 + joinedParentsChildIDReceivedChildID = childID DispatchQueue.main.async { - self.joinedParentsRoomIDReceivedInvocations.append(roomID) + self.joinedParentsChildIDReceivedInvocations.append(childID) } - if let joinedParentsRoomIDClosure = joinedParentsRoomIDClosure { - return await joinedParentsRoomIDClosure(roomID) + if let joinedParentsChildIDClosure = joinedParentsChildIDClosure { + return await joinedParentsChildIDClosure(childID) } else { - return joinedParentsRoomIDReturnValue + return joinedParentsChildIDReturnValue } } } diff --git a/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift b/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift index b8794140c..a8ab9dbc5 100644 --- a/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift +++ b/ElementX/Sources/Mocks/SpaceServiceProxyMock.swift @@ -22,7 +22,7 @@ extension SpaceServiceProxyMock { self.init() joinedSpacesPublisher = .init(configuration.joinedSpaces) - joinedParentsRoomIDReturnValue = .success(configuration.joinedParentSpaces) + joinedParentsChildIDReturnValue = .success(configuration.joinedParentSpaces) spaceRoomListSpaceIDClosure = { spaceID in if let spaceRoomList = configuration.spaceRoomLists[spaceID] { .success(spaceRoomList) diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift index 2df859168..49be05d8e 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenModels.swift @@ -7,7 +7,6 @@ // import Foundation -import MatrixRustSDK enum SecurityAndPrivacyScreenViewModelAction { case displayEditAddressScreen @@ -39,14 +38,11 @@ struct SecurityAndPrivacyScreenViewState: BindableState { var canEditHistoryVisibility = false var joinedParentSpaces: [SpaceRoomProxyProtocol] = [] + /// The count of the intersection between the set of joined parent spaces and the set of spaces in the current access type var selectableSpacesCount: Int { Set(joinedParentSpaces.map(\.id) + currentSettings.accessType.spaceIDs).count } - private var desiredJoinedParentSpaces: [SpaceRoomProxyProtocol] { - joinedParentSpaces.filter { bindings.desiredSettings.accessType.spaceIDs.contains($0.id) } - } - private var hasChanges: Bool { currentSettings != bindings.desiredSettings } @@ -111,13 +107,9 @@ struct SecurityAndPrivacyScreenViewState: BindableState { var spaceSelection: SpaceSelection { if selectableSpacesCount > 1 { .multiple - } else if let desiredJoinedParent = desiredJoinedParentSpaces.first { - // The parent space is joined by the user and is also currently selected - .singleJoined(desiredJoinedParent) } else if let joinedParent = joinedParentSpaces.first { - // The parent space is joined by the user but is not currently selected .singleJoined(joinedParent) - } else if let unknownSpaceID = bindings.desiredSettings.accessType.spaceIDs.first { + } else if let unknownSpaceID = currentSettings.accessType.spaceIDs.first { // The space is not joined by the user but is currently selected .singleUnknown(id: unknownSpaceID) } else { diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift index 9cf28aabb..27d2b3176 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/SecurityAndPrivacyScreenViewModel.swift @@ -47,7 +47,7 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType, setupRoomDirectoryVisibility() setupSubscriptions() Task { - switch await clientProxy.spaceService.joinedParents(roomID: roomProxy.id) { + switch await clientProxy.spaceService.joinedParents(childID: roomProxy.id) { case .success(let joinedParentSpaces): state.joinedParentSpaces = joinedParentSpaces case .failure: diff --git a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift index 7d85835cf..a45399517 100644 --- a/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift +++ b/ElementX/Sources/Screens/SecurityAndPrivacyScreen/View/SecurityAndPrivacyScreen.swift @@ -242,7 +242,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: [space]))), userIndicatorController: UserIndicatorControllerMock(), - appSettings: AppSettings()) + appSettings: appSettings) }() static let multipleSpacesMembersViewModel = { @@ -259,7 +259,7 @@ struct SecurityAndPrivacyScreen_Previews: PreviewProvider, TestablePreview { clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", spaceServiceConfiguration: .init(joinedParentSpaces: spaces))), userIndicatorController: UserIndicatorControllerMock(), - appSettings: AppSettings()) + appSettings: appSettings) }() static let askToJoinViewModel = { diff --git a/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift b/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift index 585d33cb3..c4a641005 100644 --- a/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift +++ b/ElementX/Sources/Services/Spaces/SpaceServiceProxy.swift @@ -49,11 +49,11 @@ class SpaceServiceProxy: SpaceServiceProxyProtocol { } } - func joinedParents(roomID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { + func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> { do { - return try await .success(spaceService.joinedParentsOfChild(childId: roomID).map(SpaceRoomProxy.init)) + return try await .success(spaceService.joinedParentsOfChild(childId: childID).map(SpaceRoomProxy.init)) } catch { - MXLog.error("Failed to get joined parents for \(roomID): \(error)") + MXLog.error("Failed to get joined parents for \(childID): \(error)") return .failure(.sdkError(error)) } } diff --git a/ElementX/Sources/Services/Spaces/SpaceServiceProxyProtocol.swift b/ElementX/Sources/Services/Spaces/SpaceServiceProxyProtocol.swift index 7bca600ce..35a862a5d 100644 --- a/ElementX/Sources/Services/Spaces/SpaceServiceProxyProtocol.swift +++ b/ElementX/Sources/Services/Spaces/SpaceServiceProxyProtocol.swift @@ -19,6 +19,6 @@ protocol SpaceServiceProxyProtocol { func spaceRoomList(spaceID: String) async -> Result func leaveSpace(spaceID: String) async -> Result - /// Returns all the parent spaces of a room that user has joined. - func joinedParents(roomID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> + /// Returns all the parent spaces of a child that user has joined. + func joinedParents(childID: String) async -> Result<[SpaceRoomProxyProtocol], SpaceServiceProxyError> } diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-en-GB.png new file mode 100644 index 000000000..b3c6ffb56 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16615769f99c92cccb78bd85195c8a853050b91051847432bab85218fae918a7 +size 168851 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-pseudo.png new file mode 100644 index 000000000..72f5d29f9 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPad-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f9c1a75e0d349da93fe984d753b7a5d7d87d7c1e569a472ef791b1cd2fe09c2 +size 207133 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-en-GB.png new file mode 100644 index 000000000..75c35f064 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:daa486a48c54f6cb612065f63c8b020140374b0858b99dc4c174853d8c58ef50 +size 116280 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-pseudo.png new file mode 100644 index 000000000..5a7ba2137 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Multiple-Spaces-members-iPhone-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2176626e57e5427a9328dee7e04bcb0c88435c67c6c4d78e9f27639b67d8faf0 +size 169819 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-en-GB.png deleted file mode 100644 index 85925013f..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-en-GB.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c10a822751f52c6dfd8a5983af1bb880ab940335f3162790d15625c80b347f4f -size 200593 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-pseudo.png deleted file mode 100644 index b0fe5ac6f..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPad-pseudo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8b22a70b9ae221e2d2f533cb487092b2de92ca7b697a9f040263da7867dfcd62 -size 246336 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-en-GB.png deleted file mode 100644 index 54cecfe5e..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-en-GB.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:fc11a77156dd88cda02776fa819bc685d55ee9ed1c7139b9baedca9c5460ba3f -size 137487 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-pseudo.png deleted file mode 100644 index 7e97fc7da..000000000 --- a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Restricted-room-iPhone-pseudo.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:12aa5240ae6480e73aa483eae15cd7b259b527bed7dd02e7101b7ab1e38be77c -size 165861 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-en-GB.png new file mode 100644 index 000000000..2654496bd --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c8692d0ac775372370d78d5be13fd0d4f1c52abfd8b0f139743d57f40fdd9d1 +size 155663 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-pseudo.png new file mode 100644 index 000000000..ad9a8e468 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPad-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2533b636d1d9bae4ed280b5d07bd3bb0222b0b6b0fca8a5c11c327dac93f37e0 +size 186317 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-en-GB.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-en-GB.png new file mode 100644 index 000000000..e1bce3404 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-en-GB.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:695aabf1d7b8ed63450e6b4bcc869e03b0e65db75b63dbb2da6f6a858b9e866f +size 102182 diff --git a/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-pseudo.png b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-pseudo.png new file mode 100644 index 000000000..7c954aab4 --- /dev/null +++ b/PreviewTests/Sources/__Snapshots__/PreviewTests/securityAndPrivacyScreen.Space-members-iPhone-pseudo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:16dc1a670bb862ffb6f1707b6e95bf7109613a0a7d76b677329b389a6decceb3 +size 144655 diff --git a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift index 3801136cb..063b37acb 100644 --- a/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift +++ b/UnitTests/Sources/SecurityAndPrivacyScreenViewModelTests.swift @@ -6,6 +6,7 @@ // Please see LICENSE files in the repository root for full details. // +import MatrixRustSDK import XCTest @testable import ElementX @@ -13,8 +14,95 @@ import XCTest @MainActor class SecurityAndPrivacyScreenViewModelTests: XCTestCase { var viewModel: SecurityAndPrivacyScreenViewModelProtocol! + var roomProxy: JoinedRoomProxyMock! var context: SecurityAndPrivacyScreenViewModelType.Context { viewModel.context } + + override func tearDown() { + viewModel = nil + roomProxy = nil + AppSettings.resetAllSettings() + } + + func testSetSingleJoinedSpaceMembersAccess() async throws { + let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let space = singleRoom[0] + setupViewModel(isSpaceSettingsEnabled: true, joinedParentSpaces: singleRoom, joinRule: .public) + + let deferred = deferFulfillment(context.$viewState) { $0.joinedParentSpaces.count == 1 } + try await deferred.fulfill() + + XCTAssertEqual(context.viewState.currentSettings.accessType, .anyone) + XCTAssertTrue(context.viewState.isSaveDisabled) + XCTAssertTrue(context.viewState.isSpaceMembersOptionSelectable) + guard case .singleJoined = context.viewState.spaceSelection else { + XCTFail("Expected spaceSelection to be .singleSpace") + return + } + + context.send(viewAction: .selectedSpaceMembersAccess) + XCTAssertEqual(context.desiredSettings.accessType, .spaceUsers(spaceIDs: [space.id])) + XCTAssertNil(context.viewState.accessSectionFooter) + XCTAssertFalse(context.viewState.isSaveDisabled) + + let expectation = expectation(description: "Join rule has updated") + roomProxy.updateJoinRuleClosure = { value in + XCTAssertEqual(value, .restricted(rules: [.roomMembership(roomId: space.id)])) + expectation.fulfill() + return .success(()) + } + context.send(viewAction: .save) + await fulfillment(of: [expectation]) + } + + func testSingleUnknownSpaceMembersAccessCanBeReselected() async throws { + let singleRoom = [SpaceRoomProxyProtocol].mockSingleRoom + let space = singleRoom[0] + setupViewModel(isSpaceSettingsEnabled: true, joinedParentSpaces: [], joinRule: .restricted(rules: [.roomMembership(roomId: space.id)])) + + let deferred = deferFulfillment(context.$viewState) { $0.joinedParentSpaces.count == 0 } + try await deferred.fulfill() + + XCTAssertEqual(context.viewState.currentSettings.accessType, .spaceUsers(spaceIDs: [space.id])) + XCTAssertEqual(context.desiredSettings, context.viewState.currentSettings) + XCTAssertTrue(context.viewState.isSpaceMembersOptionSelectable) + XCTAssertNil(context.viewState.accessSectionFooter) + XCTAssertTrue(context.viewState.isSaveDisabled) + guard case .singleUnknown = context.viewState.spaceSelection else { + XCTFail("Expected spaceSelection to be .singleSpace") + return + } + + context.desiredSettings.accessType = .anyone + XCTAssertTrue(context.viewState.isSpaceMembersOptionSelectable) + XCTAssertFalse(context.viewState.isSaveDisabled) + + context.send(viewAction: .selectedSpaceMembersAccess) + XCTAssertTrue(context.viewState.isSaveDisabled) + XCTAssertEqual(context.desiredSettings.accessType, .spaceUsers(spaceIDs: [space.id])) + guard case .singleUnknown = context.viewState.spaceSelection else { + XCTFail("Expected spaceSelection to be .singleSpace") + return + } + } + + private func setupViewModel(isSpaceSettingsEnabled: Bool, + joinedParentSpaces: [SpaceRoomProxyProtocol], + joinRule: JoinRule) { + let appSettings = AppSettings() + appSettings.spaceSettingsEnabled = isSpaceSettingsEnabled + roomProxy = JoinedRoomProxyMock(.init(isEncrypted: false, + canonicalAlias: "#room:matrix.org", + members: .allMembersAsCreator, + joinRule: joinRule, + isVisibleInPublicDirectory: true)) + + viewModel = SecurityAndPrivacyScreenViewModel(roomProxy: roomProxy, + clientProxy: ClientProxyMock(.init(userIDServerName: "matrix.org", + spaceServiceConfiguration: .init(joinedParentSpaces: joinedParentSpaces))), + userIndicatorController: UserIndicatorControllerMock(), + appSettings: appSettings) + } }