Display the list of rooms with user-defined notification settings (#1535)

This commit is contained in:
Nicolas Mauri
2023-08-22 14:33:39 +02:00
committed by GitHub
parent db1903ec05
commit b1ea23c925
34 changed files with 760 additions and 129 deletions
@@ -23,12 +23,15 @@ import XCTest
class NotificationSettingsEditScreenViewModelTests: XCTestCase {
private var viewModel: NotificationSettingsEditScreenViewModelProtocol!
private var notificationSettingsProxy: NotificationSettingsProxyMock!
private var userSession: UserSessionProtocol!
private var context: NotificationSettingsEditScreenViewModelType.Context {
viewModel.context
}
@MainActor override func setUpWithError() throws {
let clientProxy = MockClientProxy(userID: "@a:b.com")
userSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider())
notificationSettingsProxy = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .allMessages
}
@@ -42,7 +45,8 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
return .mentionsAndKeywordsOnly
}
}
viewModel = NotificationSettingsEditScreenViewModel(isDirect: false,
viewModel = NotificationSettingsEditScreenViewModel(chatType: .groupChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferred = deferFulfillment(viewModel.context.$viewState.map(\.defaultMode)
@@ -67,7 +71,8 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
func testSetModeAllMessages() async throws {
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .mentionsAndKeywordsOnly
viewModel = NotificationSettingsEditScreenViewModel(isDirect: false,
viewModel = NotificationSettingsEditScreenViewModel(chatType: .groupChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferred = deferFulfillment(viewModel.context.$viewState.map(\.defaultMode)
.first(where: { !$0.isNil }))
@@ -107,7 +112,8 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
}
func testSetModeMentions() async throws {
viewModel = NotificationSettingsEditScreenViewModel(isDirect: false,
viewModel = NotificationSettingsEditScreenViewModel(chatType: .groupChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferred = deferFulfillment(viewModel.context.$viewState.map(\.defaultMode)
.first(where: { !$0.isNil }))
@@ -149,7 +155,8 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
func testSetModeDirectChats() async throws {
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .mentionsAndKeywordsOnly
// Initialize for direct chats
viewModel = NotificationSettingsEditScreenViewModel(isDirect: true,
viewModel = NotificationSettingsEditScreenViewModel(chatType: .oneToOneChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferred = deferFulfillment(viewModel.context.$viewState.map(\.defaultMode)
.first(where: { !$0.isNil }))
@@ -182,7 +189,8 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
func testSetModeFailure() async throws {
notificationSettingsProxy.getDefaultRoomNotificationModeIsEncryptedIsOneToOneReturnValue = .mentionsAndKeywordsOnly
notificationSettingsProxy.setDefaultRoomNotificationModeIsEncryptedIsOneToOneModeThrowableError = NotificationSettingsError.Generic(message: "error")
viewModel = NotificationSettingsEditScreenViewModel(isDirect: true,
viewModel = NotificationSettingsEditScreenViewModel(chatType: .oneToOneChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferred = deferFulfillment(viewModel.context.$viewState.map(\.defaultMode)
.first(where: { !$0.isNil }))
@@ -200,4 +208,21 @@ class NotificationSettingsEditScreenViewModelTests: XCTestCase {
XCTAssertEqual(pendingModes, [nil, .allMessages, nil])
XCTAssertNotNil(context.viewState.bindings.alertInfo)
}
func testSelectRoom() async throws {
let roomID = "!roomidentifier:matrix.org"
viewModel = NotificationSettingsEditScreenViewModel(chatType: .oneToOneChat,
userSession: userSession,
notificationSettingsProxy: notificationSettingsProxy)
let deferredActions = deferFulfillment(viewModel.actions.first())
context.send(viewAction: .selectRoom(roomIdentifier: roomID))
let sentActions = try await deferredActions.fulfill()
let expectedAction = NotificationSettingsEditScreenViewModelAction.requestRoomNotificationSettingsPresentation(roomID: roomID)
guard case let .requestRoomNotificationSettingsPresentation(roomID: receivedRoomID) = sentActions, receivedRoomID == roomID else {
XCTFail("Expected action \(expectedAction), but was \(sentActions)")
return
}
}
}
@@ -24,6 +24,7 @@ class NotificationSettingsScreenViewModelTests: XCTestCase {
private var viewModel: NotificationSettingsScreenViewModelProtocol!
private var context: NotificationSettingsScreenViewModelType.Context!
private var appSettings: AppSettings!
private var userSession: UserSessionProtocol!
private var userNotificationCenter: UserNotificationCenterMock!
private var notificationSettingsProxy: NotificationSettingsProxyMock!
@@ -38,7 +39,11 @@ class NotificationSettingsScreenViewModelTests: XCTestCase {
notificationSettingsProxy.isRoomMentionEnabledReturnValue = true
notificationSettingsProxy.isCallEnabledReturnValue = true
viewModel = NotificationSettingsScreenViewModel(appSettings: appSettings,
let clientProxy = MockClientProxy(userID: "@a:b.com")
userSession = MockUserSession(clientProxy: clientProxy, mediaProvider: MockMediaProvider())
viewModel = NotificationSettingsScreenViewModel(userSession: userSession,
appSettings: appSettings,
userNotificationCenter: userNotificationCenter,
notificationSettingsProxy: notificationSettingsProxy,
isModallyPresented: false)
@@ -14,6 +14,7 @@
// limitations under the License.
//
import Combine
import MatrixRustSDK
import XCTest
@@ -25,18 +26,21 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
var roomProxyMock: RoomProxyMock!
var notificationSettingsProxyMock: NotificationSettingsProxyMock!
var context: RoomNotificationSettingsScreenViewModelType.Context { viewModel.context }
var cancellables: Set<AnyCancellable> = []
override func setUpWithError() throws {
roomProxyMock = RoomProxyMock(with: .init(displayName: "Test", joinedMembersCount: 0))
notificationSettingsProxyMock = NotificationSettingsProxyMock(with: NotificationSettingsProxyMockConfiguration())
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
}
func testInitialStateDefaultMode() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: true))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
let deferred = deferFulfillment(context.$viewState.map(\.notificationSettingsState)
.first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
@@ -48,7 +52,8 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
func testInitialStateCustomMode() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: false))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
let deferred = deferFulfillment(context.$viewState.map(\.notificationSettingsState)
.first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
@@ -60,7 +65,8 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
func testInitialStateFailure() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneThrowableError = NotificationSettingsError.Generic(message: "error")
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
let deferred = deferFulfillment(context.$viewState.map(\.notificationSettingsState)
.first(where: \.isError))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
@@ -77,7 +83,8 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
func testToggleAllCustomSettingOff() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: false))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
let deferred = deferFulfillment(context.$viewState.map(\.notificationSettingsState)
.first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
@@ -98,7 +105,8 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
func testToggleAllCustomSettingOffOn() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: true))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
var deferred = deferFulfillment(context.$viewState.map(\.notificationSettingsState).first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
try await deferred.fulfill()
@@ -116,7 +124,8 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
func testSetCustomMode() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: false))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock)
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: false)
let deferredState = deferFulfillment(context.$viewState.map(\.notificationSettingsState).first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
try await deferredState.fulfill()
@@ -151,4 +160,70 @@ class RoomNotificationSettingsScreenViewModelTests: XCTestCase {
XCTAssertEqual(notificationSettingsProxyMock.setNotificationModeRoomIdModeCallsCount, 3)
}
}
func testDeleteCustomSettingTapped() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: false))
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: true)
let deferredState = deferFulfillment(context.$viewState.map(\.notificationSettingsState).first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
try await deferredState.fulfill()
var actionSent: RoomNotificationSettingsScreenViewModelAction?
viewModel.actions
.sink { value in
actionSent = value
}
.store(in: &cancellables)
let deferredViewState = deferFulfillment(context.$viewState
.map(\.deletingCustomSetting)
.removeDuplicates()
.collect(3).first())
context.send(viewAction: .deleteCustomSettingTapped)
let states = try await deferredViewState.fulfill()
// `deletingCustomSetting` must be set to `true` when deleting, and reset to `false` afterwards.
XCTAssertEqual(states, [false, true, false])
// the `dismiss` action must have been sent
XCTAssertEqual(actionSent, .dismiss)
// `restoreDefaultNotificationMode` should have been called
XCTAssert(notificationSettingsProxyMock.restoreDefaultNotificationModeRoomIdCalled)
XCTAssertEqual(notificationSettingsProxyMock.restoreDefaultNotificationModeRoomIdReceivedInvocations, [roomProxyMock.id])
// and no alert is expected
XCTAssertNil(context.alertInfo)
}
func testDeleteCustomSettingTappedFailure() async throws {
notificationSettingsProxyMock.getNotificationSettingsRoomIdIsEncryptedIsOneToOneReturnValue = RoomNotificationSettingsProxyMock(with: .init(mode: .mentionsAndKeywordsOnly, isDefault: false))
notificationSettingsProxyMock.restoreDefaultNotificationModeRoomIdThrowableError = NotificationSettingsError.Generic(message: "error")
viewModel = RoomNotificationSettingsScreenViewModel(notificationSettingsProxy: notificationSettingsProxyMock,
roomProxy: roomProxyMock,
displayAsUserDefinedRoomSettings: true)
let deferredState = deferFulfillment(context.$viewState.map(\.notificationSettingsState).first(where: \.isLoaded))
notificationSettingsProxyMock.callbacks.send(.settingsDidChange)
try await deferredState.fulfill()
var actionSent: RoomNotificationSettingsScreenViewModelAction?
viewModel.actions
.sink { value in
actionSent = value
}
.store(in: &cancellables)
let deferredViewState = deferFulfillment(context.$viewState
.map(\.deletingCustomSetting)
.removeDuplicates()
.collect(3).first())
context.send(viewAction: .deleteCustomSettingTapped)
let states = try await deferredViewState.fulfill()
// `deletingCustomSetting` must be set to `true` when deleting, and reset to `false` afterwards.
XCTAssertEqual(states, [false, true, false])
// an alert is expected
XCTAssertEqual(context.alertInfo?.id, .restoreDefaultFailed)
// the `dismiss` action must not have been sent
XCTAssertNil(actionSent)
}
}