Skip to content

Commit 47c0a02

Browse files
committed
Add Message Composer View Model Tests
1 parent f57903a commit 47c0a02

File tree

3 files changed

+247
-2
lines changed

3 files changed

+247
-2
lines changed

StreamChatSwiftUITests/Infrastructure/Mocks/ChatMessageControllerSUI_Mock.swift

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public class ChatMessageControllerSUI_Mock: ChatMessageController {
1313
currentUserId: UserId = "ID",
1414
cid: ChannelId? = nil,
1515
messageId: String = "MockMessage"
16-
) -> ChatMessageController_Mock {
16+
) -> ChatMessageControllerSUI_Mock {
1717
if let authenticationRepository = chatClient.authenticationRepository as? AuthenticationRepository_Mock {
1818
authenticationRepository.mockedCurrentUserId = currentUserId
1919
}
@@ -59,6 +59,30 @@ public class ChatMessageControllerSUI_Mock: ChatMessageController {
5959
override public func synchronize(_ completion: ((Error?) -> Void)? = nil) {
6060
synchronize_callCount += 1
6161
}
62+
63+
var updateDraftReply_callCount = 0
64+
var updateDraftReply_text: String?
65+
66+
override public func updateDraftReply(
67+
text: String,
68+
isSilent: Bool = false,
69+
attachments: [AnyAttachmentPayload] = [],
70+
mentionedUserIds: [UserId] = [],
71+
quotedMessageId: MessageId? = nil,
72+
showReplyInChannel: Bool = false,
73+
command: Command? = nil,
74+
extraData: [String: RawJSON] = [:],
75+
completion: ((Result<DraftMessage, any Error>) -> Void)? = nil
76+
) {
77+
updateDraftReply_callCount += 1
78+
updateDraftReply_text = text
79+
}
80+
81+
var deleteDraftReply_callCount = 0
82+
83+
override public func deleteDraftReply(completion: (((any Error)?) -> Void)? = nil) {
84+
deleteDraftReply_callCount += 1
85+
}
6286
}
6387

6488
public extension ChatMessageControllerSUI_Mock {

StreamChatSwiftUITests/Tests/ChatChannel/ChatChannelDataSource_Tests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,19 @@ class ChatChannelDataSource_Tests: StreamChatTestCase {
210210
return threadDataSource
211211
}
212212

213+
private func makeMessageThreadDataSource(
214+
messages: [ChatMessage],
215+
messageController: ChatMessageControllerSUI_Mock
216+
) -> MessageThreadDataSource {
217+
let channelController = makeChannelController(messages: messages)
218+
let threadDataSource = MessageThreadDataSource(
219+
channelController: channelController,
220+
messageController: messageController
221+
)
222+
223+
return threadDataSource
224+
}
225+
213226
private func makeChannelController(messages: [ChatMessage]) -> ChatChannelController_Mock {
214227
let channelController = ChatChannelTestHelpers.makeChannelController(
215228
chatClient: chatClient,

StreamChatSwiftUITests/Tests/ChatChannel/MessageComposerViewModel_Tests.swift

Lines changed: 209 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
@testable import StreamChat
66
@testable import StreamChatSwiftUI
77
@testable import StreamChatTestTools
8+
import SwiftUI
89
import XCTest
910

1011
class MessageComposerViewModel_Tests: StreamChatTestCase {
@@ -692,8 +693,215 @@ class MessageComposerViewModel_Tests: StreamChatTestCase {
692693
XCTAssert(viewModel.audioRecordingInfo == .initial)
693694
}
694695

695-
// MARK: - private
696+
// MARK: - Draft Message Tests
697+
698+
func test_messageComposerVM_updateDraftMessage() {
699+
// Given
700+
let channelController = makeChannelController()
701+
let viewModel = makeComposerDraftsViewModel(
702+
channelController: channelController,
703+
messageController: nil
704+
)
705+
let quotedMessage = ChatMessage.mock(id: .unique, cid: .unique, text: "Quoted message", author: .mock(id: .unique))
706+
707+
// When
708+
viewModel.text = "Draft text"
709+
viewModel.updateDraftMessage(quotedMessage: quotedMessage)
710+
711+
// Then
712+
XCTAssertEqual(channelController.updateDraftMessage_text, "Draft text")
713+
XCTAssertEqual(channelController.updateDraftMessage_callCount, 1)
714+
}
715+
716+
func test_messageComposerVM_updateDraftReply() {
717+
// Given
718+
let channelController = makeChannelController()
719+
let messageController = ChatMessageControllerSUI_Mock.mock(
720+
chatClient: chatClient,
721+
cid: .unique,
722+
messageId: .unique
723+
)
724+
let viewModel = makeComposerDraftsViewModel(
725+
channelController: channelController,
726+
messageController: messageController
727+
)
728+
let quotedMessage = ChatMessage.mock(id: .unique, cid: .unique, text: "Quoted message", author: .mock(id: .unique))
729+
730+
// When
731+
viewModel.text = "Draft reply"
732+
viewModel.updateDraftMessage(quotedMessage: quotedMessage)
733+
734+
// Then
735+
XCTAssertEqual(messageController.updateDraftReply_text, "Draft reply")
736+
XCTAssertEqual(messageController.updateDraftReply_callCount, 1)
737+
}
738+
739+
func test_messageComposerVM_whenTextErased_shouldDeleteDraftMessage() {
740+
// Given
741+
let channelController = makeChannelController()
742+
let viewModel = makeComposerDraftsViewModel(
743+
channelController: channelController,
744+
messageController: nil
745+
)
746+
let draftMessage = DraftMessage.mock(text: "text")
747+
748+
// When
749+
viewModel.draftMessage = draftMessage
750+
viewModel.text = ""
751+
752+
// Then
753+
XCTAssertEqual(channelController.deleteDraftMessage_callCount, 1)
754+
}
755+
756+
func test_messageComposerVM_whenTextErased_deleteDraftReply() {
757+
// Given
758+
let channelController = makeChannelController()
759+
let messageController = ChatMessageControllerSUI_Mock.mock(
760+
chatClient: chatClient,
761+
cid: .unique,
762+
messageId: .unique
763+
)
764+
let viewModel = makeComposerDraftsViewModel(
765+
channelController: channelController,
766+
messageController: messageController
767+
)
768+
let draftMessage = DraftMessage.mock(text: "reply")
769+
770+
// When
771+
viewModel.draftMessage = draftMessage
772+
viewModel.text = ""
773+
774+
// Then
775+
XCTAssertEqual(messageController.deleteDraftReply_callCount, 1)
776+
}
777+
778+
func test_messageComposerVM_whenMessagePublished_deleteDraftMessage() {
779+
// Given
780+
let channelController = makeChannelController()
781+
let viewModel = makeComposerDraftsViewModel(
782+
channelController: channelController,
783+
messageController: nil
784+
)
785+
let draftMessage = DraftMessage.mock(text: "text")
786+
787+
// When
788+
viewModel.draftMessage = draftMessage
789+
viewModel.sendMessage(quotedMessage: nil, editedMessage: nil) {}
790+
791+
// Then
792+
// Sending a message will clear the input, deleting the draft message.
793+
XCTAssertEqual(channelController.deleteDraftMessage_callCount, 1)
794+
}
795+
796+
func test_messageComposerVM_whenMessagePublished_deleteDraftReply() {
797+
// Given
798+
let channelController = makeChannelController()
799+
let messageController = ChatMessageControllerSUI_Mock.mock(
800+
chatClient: chatClient,
801+
cid: .unique,
802+
messageId: .unique
803+
)
804+
let viewModel = makeComposerDraftsViewModel(
805+
channelController: channelController,
806+
messageController: messageController
807+
)
808+
let draftMessage = DraftMessage.mock(text: "reply")
809+
810+
// When
811+
viewModel.draftMessage = draftMessage
812+
viewModel.sendMessage(quotedMessage: nil, editedMessage: nil) {}
813+
814+
// Then
815+
XCTAssertEqual(messageController.deleteDraftReply_callCount, 1)
816+
}
817+
818+
func test_messageComposerVM_draftMessageUpdatedEvent() throws {
819+
// Given
820+
let channelController = makeChannelController()
821+
let viewModel = makeComposerDraftsViewModel(
822+
channelController: channelController,
823+
messageController: nil
824+
)
825+
viewModel.draftMessage = .mock(text: "Draft")
826+
827+
// When
828+
let draftMessage = DraftMessage.mock(text: "Draft from event")
829+
let cid = try XCTUnwrap(channelController.cid)
830+
let event = DraftUpdatedEvent(cid: cid, channel: .mock(cid: cid), draftMessage: draftMessage, createdAt: .unique)
831+
viewModel.eventsController(viewModel.eventsController, didReceiveEvent: event)
832+
833+
// Then
834+
XCTAssertEqual(viewModel.draftMessage?.text, "Draft from event")
835+
}
696836

837+
func test_messageComposerVM_draftReplyUpdatedEvent() throws {
838+
// Given
839+
let channelController = makeChannelController()
840+
let messageController = ChatMessageControllerSUI_Mock.mock(
841+
chatClient: chatClient,
842+
cid: channelController.cid!,
843+
messageId: .unique
844+
)
845+
let viewModel = makeComposerDraftsViewModel(
846+
channelController: channelController,
847+
messageController: messageController
848+
)
849+
viewModel.draftMessage = .mock(text: "Draft")
850+
851+
// When
852+
let draftMessage = DraftMessage.mock(
853+
threadId: messageController.messageId,
854+
text: "Draft reply from event"
855+
)
856+
let cid = try XCTUnwrap(channelController.cid)
857+
let event = DraftUpdatedEvent(cid: cid, channel: .mock(cid: cid), draftMessage: draftMessage, createdAt: .unique)
858+
viewModel.eventsController(viewModel.eventsController, didReceiveEvent: event)
859+
860+
// Then
861+
XCTAssertEqual(viewModel.draftMessage?.text, "Draft reply from event")
862+
}
863+
864+
func test_messageComposerVM_draftReplyUpdatedEventFromOtherThread_shouldNotUpdate() throws {
865+
// Given
866+
let channelController = makeChannelController()
867+
let messageController = ChatMessageControllerSUI_Mock.mock(
868+
chatClient: chatClient,
869+
cid: channelController.cid!,
870+
messageId: .unique
871+
)
872+
let viewModel = makeComposerDraftsViewModel(
873+
channelController: channelController,
874+
messageController: messageController
875+
)
876+
viewModel.draftMessage = .mock(text: "Draft")
877+
878+
// When
879+
let draftMessage = DraftMessage.mock(
880+
threadId: .unique,
881+
text: "Draft reply from event"
882+
)
883+
let cid = try XCTUnwrap(channelController.cid)
884+
let event = DraftUpdatedEvent(cid: cid, channel: .mock(cid: cid), draftMessage: draftMessage, createdAt: .unique)
885+
viewModel.eventsController(viewModel.eventsController, didReceiveEvent: event)
886+
887+
// Then
888+
XCTAssertEqual(viewModel.draftMessage?.text, "Draft")
889+
}
890+
891+
// MARK: - private
892+
893+
private func makeComposerDraftsViewModel(
894+
channelController: ChatChannelController,
895+
messageController: ChatMessageController?
896+
) -> MessageComposerViewModel {
897+
let viewModel = MessageComposerViewModel(
898+
channelController: channelController,
899+
messageController: messageController
900+
)
901+
viewModel.utils = .init(messageListConfig: .init(draftMessagesEnabled: true))
902+
return viewModel
903+
}
904+
697905
private func makeComposerViewModel() -> MessageComposerViewModel {
698906
MessageComposerTestUtils.makeComposerViewModel(chatClient: chatClient)
699907
}

0 commit comments

Comments
 (0)