Skip to content

Commit

Permalink
knock requests list tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 committed Dec 13, 2024
1 parent 36bfd18 commit 8eb5f82
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn
title: L10n.screenKnockRequestsListDeclineAlertTitle,
message: L10n.screenKnockRequestsListDeclineAlertDescription(request.userID),
primaryButton: .init(title: L10n.screenKnockRequestsListDeclineAlertConfirmButtonTitle,
role: .destructive,
action: { [weak self] in self?.decline(request: request) }),
role: .destructive) { [weak self] in self?.decline(request: request) },
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
case .ban(let eventID):
guard let request = getRequest(eventID: eventID) else {
Expand All @@ -67,8 +66,7 @@ class KnockRequestsListScreenViewModel: KnockRequestsListScreenViewModelType, Kn
state.bindings.alertInfo = .init(id: .declineAndBan,
title: L10n.screenKnockRequestsListBanAlertTitle,
primaryButton: .init(title: L10n.screenKnockRequestsListBanAlertConfirmButtonTitle,
role: .destructive,
action: { [weak self] in self?.declineAndBan(request: request) }),
role: .destructive) { [weak self] in self?.declineAndBan(request: request) },
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview {

static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([]))

static let singleRequestViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello"))]))

static let viewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello")),
// swiftlint:disable:next line_length
JoinRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org", displayName: "Bob", avatarURL: nil, timestamp: "Now", reason: "Hello this one is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason")),
JoinRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil, timestamp: "Now", reason: nil)),
JoinRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org", displayName: "Dan", avatarURL: nil, timestamp: "Now", reason: "Hello! It's a me! Dan!"))]))
Expand All @@ -97,10 +100,20 @@ struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview {
NavigationStack {
KnockRequestsListScreen(context: viewModel.context)
}
.snapshotPreferences(delay: 0.2)

NavigationStack {
KnockRequestsListScreen(context: singleRequestViewModel.context)
}
.previewDisplayName("Single Request")
.snapshotPreferences(delay: 0.2)

NavigationStack {
KnockRequestsListScreen(context: emptyViewModel.context)
}
.previewDisplayName("Empty state")
.snapshotPreferences(delay: 0.2)

NavigationStack {
KnockRequestsListScreen(context: loadingViewModel.context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,8 @@ private struct SingleKnockRequestBannerContent: View {
Button(L10n.screenRoomSingleKnockRequestViewButtonTitle, action: onViewAll)
.buttonStyle(.compound(.secondary, size: .medium))
if let onAccept {
Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle, action: {
onAccept(request.eventID)
})
.buttonStyle(.compound(.primary, size: .medium))
Button(L10n.screenRoomSingleKnockRequestAcceptButtonTitle) { onAccept(request.eventID) }
.buttonStyle(.compound(.primary, size: .medium))
}
}
.padding(.top, request.reason == nil ? 0 : 2)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
203 changes: 202 additions & 1 deletion UnitTests/Sources/KnockRequestsListScreenViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,209 @@ class KnockRequestsListScreenViewModelTests: XCTestCase {
}

override func setUpWithError() throws {
viewModel = KnockRequestsListScreenViewModel(roomProxy: JoinedRoomProxyMock(.init()),
AppSettings.resetAllSettings()
}

func testLoadingState() async throws {
let roomProxyMock = JoinedRoomProxyMock(.init(joinRequestsState: .loading, joinRule: .knock))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

let deferred = deferFulfillment(context.$viewState) { state in
!state.shouldDisplayRequests &&
state.isKnockableRoom &&
state.canAccept &&
!state.canBan &&
!state.canDecline &&
state.isLoading &&
!state.shouldDisplayEmptyView
}
try await deferred.fulfill()
}

func testEmptyState() async throws {
let roomProxyMock = JoinedRoomProxyMock(.init(joinRequestsState: .loaded([]), joinRule: .knock))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

let deferred = deferFulfillment(context.$viewState) { state in
!state.shouldDisplayRequests &&
state.isKnockableRoom &&
state.canAccept &&
!state.canBan &&
!state.canDecline &&
!state.isLoading &&
state.shouldDisplayEmptyView
}
try await deferred.fulfill()
}

func testLoadedState() async throws {
let roomProxyMock = JoinedRoomProxyMock(.init(members: [.mockAdmin],
joinRequestsState: .loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")),
JoinRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")),
JoinRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")),
JoinRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]),
ownUserID: RoomMemberProxyMock.mockAdmin.userID,
joinRule: .knock))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

var deferred = deferFulfillment(context.$viewState) { state in
state.shouldDisplayRequests &&
state.isKnockableRoom &&
state.canAccept &&
state.canBan &&
state.canDecline &&
!state.isLoading &&
!state.shouldDisplayEmptyView &&
state.displayedRequests.count == 4 &&
state.handledEventIDs.isEmpty &&
state.shouldDisplayAcceptAllButton
}
try await deferred.fulfill()

deferred = deferFulfillment(context.$viewState) { state in
state.shouldDisplayRequests &&
state.handledEventIDs == ["1"] &&
!state.shouldDisplayEmptyView &&
state.displayedRequests.count == 3 &&
state.shouldDisplayAcceptAllButton
}
context.send(viewAction: .acceptRequest(eventID: "1"))
try await deferred.fulfill()

deferred = deferFulfillment(context.$viewState) { state in
state.bindings.alertInfo?.id == .declineRequest
}
context.send(viewAction: .declineRequest(eventID: "2"))
try await deferred.fulfill()

guard let declineAlertInfo = context.alertInfo else {
XCTFail("Can't be nil")
return
}
deferred = deferFulfillment(context.$viewState) { state in
state.shouldDisplayRequests &&
state.handledEventIDs == ["1", "2"] &&
!state.shouldDisplayEmptyView &&
state.displayedRequests.count == 2 &&
state.shouldDisplayAcceptAllButton
}
declineAlertInfo.primaryButton.action?()
try await deferred.fulfill()

deferred = deferFulfillment(context.$viewState) { state in
state.bindings.alertInfo?.id == .declineAndBan
}
context.send(viewAction: .ban(eventID: "3"))
try await deferred.fulfill()

guard let banAlertInfo = context.alertInfo else {
XCTFail("Can't be nil")
return
}
deferred = deferFulfillment(context.$viewState) { state in
state.shouldDisplayRequests &&
state.handledEventIDs == ["1", "2", "3"] &&
!state.shouldDisplayEmptyView &&
state.displayedRequests.count == 1 &&
!state.shouldDisplayAcceptAllButton
}
banAlertInfo.primaryButton.action?()
try await deferred.fulfill()
}

func testAcceptAll() async throws {
let roomProxyMock = JoinedRoomProxyMock(.init(joinRequestsState: .loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")),
JoinRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")),
JoinRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")),
JoinRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]),
joinRule: .knock))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

var deferred = deferFulfillment(context.$viewState) { state in
state.shouldDisplayRequests &&
state.isKnockableRoom &&
state.canAccept &&
!state.canBan &&
!state.canDecline &&
!state.isLoading &&
!state.shouldDisplayEmptyView &&
state.displayedRequests.count == 4 &&
state.handledEventIDs.isEmpty &&
state.shouldDisplayAcceptAllButton
}
try await deferred.fulfill()

deferred = deferFulfillment(context.$viewState) { state in
state.bindings.alertInfo?.id == .acceptAllRequests
}
context.send(viewAction: .acceptAllRequests)
try await deferred.fulfill()

guard let alertInfo = context.alertInfo else {
XCTFail("Can't be nil")
return
}

deferred = deferFulfillment(context.$viewState) { state in
!state.shouldDisplayRequests &&
state.handledEventIDs == ["1", "2", "3", "4"] &&
!state.isLoading &&
state.shouldDisplayEmptyView
}
alertInfo.primaryButton.action?()
try await deferred.fulfill()
}

func testLoadedStateBecomesEmptyIfTheJoinRuleIsNotKnocking() async throws {
// If there is a sudden change in the rule, but the requests are still published, we want to hide all of them and show the empty view
let roomProxyMock = JoinedRoomProxyMock(.init(members: [.mockAdmin],
joinRequestsState: .loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")),
JoinRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")),
JoinRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")),
JoinRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]),
ownUserID: RoomMemberProxyMock.mockAdmin.userID,
joinRule: .invite))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

let deferred = deferFulfillment(context.$viewState) { state in
!state.shouldDisplayRequests &&
state.shouldDisplayEmptyView &&
!state.isLoading &&
!state.isKnockableRoom
}
try await deferred.fulfill()
}

func testLoadedStateBecomesEmptyIfPermissionsAreRemoved() async throws {
// If there is a sudden change in permissions, and the user can't do any other action, we hide all the requests and shoe the empty view
let roomProxyMock = JoinedRoomProxyMock(.init(joinRequestsState: .loaded([JoinRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org")),
JoinRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org")),
JoinRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org")),
JoinRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org"))]),
canUserInvite: false,
joinRule: .knock))
viewModel = KnockRequestsListScreenViewModel(roomProxy: roomProxyMock,
mediaProvider: MediaProviderMock(),
userIndicatorController: UserIndicatorControllerMock())

let deferred = deferFulfillment(context.$viewState) { state in
!state.shouldDisplayRequests &&
state.shouldDisplayEmptyView &&
!state.canAccept &&
!state.canBan &&
!state.canDecline &&
!state.isLoading
}
try await deferred.fulfill()
}
}
5 changes: 4 additions & 1 deletion UnitTests/Sources/RoomDetailsViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,11 @@ class RoomDetailsScreenViewModelTests: XCTestCase {
let deferred = deferFulfillment(context.$viewState) { state in
state.knockRequestsCount == 2 && state.canSeeKnockingRequests
}

try await deferred.fulfill()

let deferredAction = deferFulfillment(viewModel.actions) { $0 == .displayKnockingRequests }
context.send(viewAction: .processTapRequestsToJoin)
try await deferredAction.fulfill()
}

func testKnockRequestsCounterIsLoading() async throws {
Expand Down

0 comments on commit 8eb5f82

Please sign in to comment.