Skip to content

Commit

Permalink
fixup! add ComposerToolBarViewModelTests for canSend
Browse files Browse the repository at this point in the history
  • Loading branch information
BillCarsonFr committed Jan 15, 2025
1 parent 85509d1 commit f7003cb
Showing 1 changed file with 176 additions and 1 deletion.
177 changes: 176 additions & 1 deletion UnitTests/Sources/ComposerToolbarViewModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Combine
@testable import ElementX
import MatrixRustSDK
import XCTest

import WysiwygComposer
Expand Down Expand Up @@ -93,7 +94,9 @@ class ComposerToolbarViewModelTests: XCTestCase {
let suggestions: [SuggestionItem] = [.user(item: MentionSuggestionItem(id: "@user_mention_1:matrix.org", displayName: "User 1", avatarURL: nil, range: .init())),
.user(item: MentionSuggestionItem(id: "@user_mention_2:matrix.org", displayName: "User 2", avatarURL: .mockMXCAvatar, range: .init()))]
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init(suggestions: suggestions))
viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,

viewModel = ComposerToolbarViewModel(roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(configuration: .init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
Expand Down Expand Up @@ -632,6 +635,177 @@ class ComposerToolbarViewModelTests: XCTestCase {
XCTAssertEqual(viewModel.context.plainComposerText, NSAttributedString(string: sharedText))
}

// MARK: - Identity Violation

func testVerificationViolationDisablesComposer() {
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init())

let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test"))
let roomMemberProxyMock = RoomMemberProxyMock(with: .init(userID: "@alice:localhost", membership: .join))

roomProxyMock.getMemberUserIDClosure = { _ in
.success(roomMemberProxyMock)
}

let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([IdentityStatusChange(userId: "@alice:localhost", changedTo: .verificationViolation)])

roomProxyMock.underlyingIdentityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()

viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(configuration: .init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
analyticsService: ServiceLocator.shared.analytics,
composerDraftService: draftServiceMock)

let expectation1 = expectation(description: "Composer is disabled")
let cancellable = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if !canSend {
expectation1.fulfill()
}
}

wait(for: [expectation1], timeout: 2.0)
cancellable.cancel()

let expectation2 = expectation(description: "Composer is enabled")
let cancellable2 = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if canSend {
expectation2.fulfill()
}
}

mockSubject.send([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinned)])

wait(for: [expectation2], timeout: 2.0)
cancellable2.cancel()
}

func testMultipleViolation() {
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init())

let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test"))

let aliceRoomMemberProxyMock = RoomMemberProxyMock(with: .init(userID: "@alice:localhost", membership: .join))
let bobRoomMemberProxyMock = RoomMemberProxyMock(with: .init(userID: "@bob:localhost", membership: .join))

roomProxyMock.getMemberUserIDClosure = { userId in
if userId == "@alice:localhost" {
return .success(aliceRoomMemberProxyMock)
} else if userId == "@bob:localhost" {
return .success(bobRoomMemberProxyMock)
} else {
return .failure(.sdkError(ClientProxyMockError.generic))
}
}

// There are 2 violations, ensure that resolving the first one is not enough
let mockSubject = CurrentValueSubject<[IdentityStatusChange], Never>([
IdentityStatusChange(userId: "@alice:localhost", changedTo: .verificationViolation),
IdentityStatusChange(userId: "@bob:localhost", changedTo: .verificationViolation)
])

roomProxyMock.underlyingIdentityStatusChangesPublisher = mockSubject.asCurrentValuePublisher()

viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(configuration: .init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
analyticsService: ServiceLocator.shared.analytics,
composerDraftService: draftServiceMock)

let expectation1 = expectation(description: "Composer is disabled")
let cancellable = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if !canSend {
expectation1.fulfill()
}
}

wait(for: [expectation1], timeout: 2.0)
cancellable.cancel()

let expectation2 = expectation(description: "Composer is still disabled")
let cancellable2 = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if !canSend {
expectation2.fulfill()
}
}

mockSubject.send([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinned)])

wait(for: [expectation2], timeout: 2.0)
cancellable2.cancel()

let expectation3 = expectation(description: "Composer is now enabled")
let cancellable3 = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if canSend {
expectation3.fulfill()
}
}

mockSubject.send([IdentityStatusChange(userId: "@bob:localhost", changedTo: .pinned)])

wait(for: [expectation3], timeout: 2.0)
cancellable3.cancel()
}

func testPinViolationDoesNotDisableComposer() {
let mockCompletionSuggestionService = CompletionSuggestionServiceMock(configuration: .init())

let roomProxyMock = JoinedRoomProxyMock(.init(name: "Test"))
let roomMemberProxyMock = RoomMemberProxyMock(with: .init(userID: "@alice:localhost", membership: .join))

roomProxyMock.getMemberUserIDClosure = { _ in
.success(roomMemberProxyMock)
}

roomProxyMock.underlyingIdentityStatusChangesPublisher = CurrentValueSubject([IdentityStatusChange(userId: "@alice:localhost", changedTo: .pinViolation)]).asCurrentValuePublisher()

viewModel = ComposerToolbarViewModel(roomProxy: roomProxyMock,
wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: mockCompletionSuggestionService,
mediaProvider: MediaProviderMock(configuration: .init()),
mentionDisplayHelper: ComposerMentionDisplayHelper.mock,
analyticsService: ServiceLocator.shared.analytics,
composerDraftService: draftServiceMock)

let expectation = expectation(description: "Composer should be enabled")
let cancellable = viewModel
.context
.$viewState
.map(\.canSend)
.sink { canSend in
if canSend {
expectation.fulfill()
}
}

wait(for: [expectation], timeout: 2.0)
cancellable.cancel()
}

// MARK: - Helpers

private func setUpViewModel(initialText: String? = nil, loadDraftClosure: (() async -> Result<ComposerDraftProxy?, ComposerDraftServiceError>)? = nil) {
Expand All @@ -643,6 +817,7 @@ class ComposerToolbarViewModelTests: XCTestCase {
}

viewModel = ComposerToolbarViewModel(initialText: initialText,
roomProxy: JoinedRoomProxyMock(.init()),
wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: completionSuggestionServiceMock,
mediaProvider: MediaProviderMock(configuration: .init()),
Expand Down

0 comments on commit f7003cb

Please sign in to comment.