smartlist: fix search for swarm conversations
This patch:
- fixes search for conversation with more than one participant
- adds unit tests
Gitlab: #261
Change-Id: I55274fe8423f5a9c242f28d502782a244610c1c6
diff --git a/Ring/RingTests/JamiSearchViewModelTests.swift b/Ring/RingTests/JamiSearchViewModelTests.swift
new file mode 100644
index 0000000..24a0276
--- /dev/null
+++ b/Ring/RingTests/JamiSearchViewModelTests.swift
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2023 Savoir-faire Linux Inc.
+ *
+ * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+import XCTest
+import RxRelay
+@testable import Ring
+
+final class JamiSearchViewModelTests: XCTestCase {
+
+ var conversationVM: ConversationViewModel!
+ var injectionBag: InjectionBag!
+ var dataSource: TestableFilteredDataSource!
+ var searchViewModel: JamiSearchViewModel!
+
+ override func setUpWithError() throws {
+ try super.setUpWithError()
+ let dBManager = DBManager(profileHepler: ProfileDataHelper(),
+ conversationHelper: ConversationDataHelper(),
+ interactionHepler: InteractionDataHelper(),
+ dbConnections: DBContainer())
+ let daemonService = DaemonService(dRingAdaptor: DRingAdapter())
+ let nameService = NameService(withNameRegistrationAdapter: NameRegistrationAdapter())
+ let presenceService = PresenceService(withPresenceAdapter: PresenceAdapter())
+ let videoService = VideoService(withVideoAdapter: VideoAdapter())
+ let audioService = AudioService(withAudioAdapter: AudioAdapter())
+ let systemService = SystemService(withSystemAdapter: SystemAdapter())
+ let networkService = NetworkService()
+ let callsProvider: CallsProviderDelegate = CallsProviderDelegate()
+ let callService: CallsService = CallsService(withCallsAdapter: CallsAdapter(), dbManager: dBManager)
+ let accountService: AccountsService = AccountsService(withAccountAdapter: AccountAdapter(), dbManager: dBManager)
+ let contactsService: ContactsService = ContactsService(withContactsAdapter: ContactsAdapter(), dbManager: dBManager)
+ let profileService: ProfilesService =
+ ProfilesService(withProfilesAdapter: ProfilesAdapter(), dbManager: dBManager)
+ let dataTransferService: DataTransferService =
+ DataTransferService(withDataTransferAdapter: DataTransferAdapter(),
+ dbManager: dBManager)
+ let conversationsService: ConversationsService =
+ ConversationsService(withConversationsAdapter: ConversationsAdapter(), dbManager: dBManager)
+ let locationSharingService: LocationSharingService =
+ LocationSharingService(dbManager: dBManager)
+ let requestsService: RequestsService =
+ RequestsService(withRequestsAdapter: RequestsAdapter(), dbManager: dBManager)
+
+ injectionBag = InjectionBag(withDaemonService: daemonService,
+ withAccountService: accountService,
+ withNameService: nameService,
+ withConversationService: conversationsService,
+ withContactsService: contactsService,
+ withPresenceService: presenceService,
+ withNetworkService: networkService,
+ withCallService: callService,
+ withVideoService: videoService,
+ withAudioService: audioService,
+ withDataTransferService: dataTransferService,
+ withProfileService: profileService,
+ withCallsProvider: callsProvider,
+ withLocationSharingService: locationSharingService,
+ withRequestsService: requestsService,
+ withSystemService: systemService)
+ conversationVM = ConversationViewModel(with: injectionBag)
+ conversationVM.conversation = BehaviorRelay(value: ConversationModel())
+ dataSource = TestableFilteredDataSource(conversations: [conversationVM])
+ searchViewModel = JamiSearchViewModel(with: injectionBag, source: dataSource)
+ }
+
+ override func tearDownWithError() throws {
+ try super.tearDownWithError()
+ conversationVM = nil
+ injectionBag = nil
+ dataSource = nil
+ searchViewModel = nil
+ }
+
+ func createSwarmConversation(jamiId: String, type: ConversationType) -> ConversationModel {
+ let conversation = ConversationModel(withId: "", accountId: "", info: [:])
+ conversation.type = type
+ let participants = [["uri": jamiId]]
+ conversation.addParticipantsFromArray(participantsInfo: participants, accountURI: "")
+ return conversation
+ }
+
+ func createSwarmInfo(jamiId: String, name: String, containsSearchQuery: Bool, hasParticipantWithRegisteredName: Bool) -> TestableSwarmInfo {
+ let participant = ParticipantInfo(jamiId: jamiId, role: .admin)
+ participant.registeredName.accept(name)
+ let swarmInfo = TestableSwarmInfo(participants: [participant], containsSearchQuery: containsSearchQuery, hasParticipantWithRegisteredName: hasParticipantWithRegisteredName)
+ return swarmInfo
+ }
+
+ func testConversationExists_ForOneToOneConversation_QueryIsHash_Exists() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId1
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+
+ }
+
+ func testConversationExists_ForOneToOneConversation_QueryIsHash_DoesNotExist() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId2
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationExists_ForOneToOneConversation_QueryIsRegisteredName_Exists() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: true, hasParticipantWithRegisteredName: true)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testConversationExists_PrivateConversation_QueryIsRegisteredName_Exists() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: true, hasParticipantWithRegisteredName: true)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationExists_PrivateConversation_QueryIsRegisteredName_DoesNotExist() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: false, hasParticipantWithRegisteredName: false)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName2
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationExists_PrivateConversation_QueryIsHash_DoesNotExist() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId2
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationExists_PrivateConversation_QueryIsHash_Exists() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId1
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationExists_ForOneToOneConversation_QueryIsRegisteredName_DoesNotExist() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: false, hasParticipantWithRegisteredName: false)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName2
+ let result = searchViewModel.isConversationExists(for: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationMatch_OneToOneConversation_QueryIsHash_Match() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId1
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testConversationMatch_OneToOneConversation_QueryIsRegisteredName_Match() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: true, hasParticipantWithRegisteredName: true)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testConversationMatch_PrivateConversation_QueryIsRegisteredName_Match() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: true, hasParticipantWithRegisteredName: true)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationMatch_SwarmConversation_QueryIsRegisteredName_DoesNotMatch() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: false, hasParticipantWithRegisteredName: false)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1 + "1"
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationMatch_SipConversation_Match() {
+ // Arrange
+ let uri = JamiURI(schema: .sip, infoHash: sipTestNumber1)
+ let conversation = ConversationModel(withParticipantUri: uri, accountId: "", hash: sipTestNumber1)
+ conversationVM.conversation.accept(conversation)
+ conversationVM.userName.accept(sipTestNumber1)
+ // Act
+ let searchQuery = sipTestNumber1
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testConversationMatch_SipConversation_DoesNotMatch() {
+ // Arrange
+ let uri = JamiURI(schema: .sip, infoHash: sipTestNumber1)
+ let conversation = ConversationModel(withParticipantUri: uri, accountId: "", hash: sipTestNumber1)
+ conversationVM.conversation.accept(conversation)
+ conversationVM.userName.accept(sipTestNumber1)
+ // Act
+ let searchQuery = sipTestNumber1 + "1"
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationMatch_PrivateConversaion_QueryIsHash() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ // Act
+ let searchQuery = jamiId1
+ let result = searchViewModel.isConversation(conversationVM, match: searchQuery)
+ // Assert
+ XCTAssertFalse(result)
+ }
+
+ func testConversationContains_PrivateConversation_QueryIsRegisteredName_Contains() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .invitesOnly)
+ conversationVM.conversation.accept(conversation)
+ let swarmInfo = self.createSwarmInfo(jamiId: jamiId1, name: registeredName1, containsSearchQuery: true, hasParticipantWithRegisteredName: true)
+ conversationVM.swarmInfo = swarmInfo
+ // Act
+ let searchQuery = registeredName1
+ let result = searchViewModel.isConversation(conversationVM, contains: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testConversationContains_SipConversation_Contains() {
+ // Arrange
+ let uri = JamiURI(schema: .sip, infoHash: sipTestNumber1)
+ let conversation = ConversationModel(withParticipantUri: uri, accountId: "", hash: sipTestNumber1)
+ conversationVM.conversation.accept(conversation)
+ conversationVM.userName.accept(sipTestNumber1)
+ // Act
+ let searchQuery = sipTestNumber1
+ let result = searchViewModel.isConversation(conversationVM, contains: searchQuery)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testTemporaryConversationExist_True() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM = ConversationViewModel(with: injectionBag)
+ conversationVM.conversation = BehaviorRelay(value: conversation)
+ searchViewModel.temporaryConversation.accept(conversationVM)
+ // Act
+ let result = searchViewModel.temporaryConversationExists(for: jamiId1)
+ // Assert
+ XCTAssertTrue(result)
+ }
+
+ func testTemporaryConversationExist_False() {
+ // Arrange
+ let conversation = self.createSwarmConversation(jamiId: jamiId1, type: .oneToOne)
+ conversationVM = ConversationViewModel(with: injectionBag)
+ conversationVM.conversation = BehaviorRelay(value: conversation)
+ searchViewModel.temporaryConversation.accept(conversationVM)
+ // Act
+ let result = searchViewModel.temporaryConversationExists(for: jamiId2)
+ // Assert
+ XCTAssertFalse(result)
+ }
+}