Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.wire.kalium.logic.feature.service.ObserveAllServicesUseCase
import com.wire.kalium.logic.feature.service.ObserveIsServiceMemberUseCase
import com.wire.kalium.logic.feature.service.SearchServicesByNameUseCase
import com.wire.kalium.logic.feature.service.ServiceScope
import com.wire.kalium.logic.feature.service.SyncServicesUseCase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand Down Expand Up @@ -58,6 +59,11 @@ class ServicesModule {
fun provideObserveAllServicesUseCase(serviceScope: ServiceScope): ObserveAllServicesUseCase =
serviceScope.observeAllServices

@ViewModelScoped
@Provides
fun provideSyncServicesUseCase(serviceScope: ServiceScope): SyncServicesUseCase =
serviceScope.syncServices

@ViewModelScoped
@Provides
fun provideSearchServicesByNameUseCase(serviceScope: ServiceScope): SearchServicesByNameUseCase =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import com.wire.kalium.logic.feature.featureConfig.AppsAllowedResult
import com.wire.kalium.logic.feature.featureConfig.ObserveIsAppsAllowedForUsageUseCase
import com.wire.kalium.logic.feature.service.ObserveAllServicesUseCase
import com.wire.kalium.logic.feature.service.SearchServicesByNameUseCase
import com.wire.kalium.logic.feature.service.SyncServicesUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
Expand All @@ -55,6 +56,7 @@ import kotlinx.coroutines.launch
class SearchAppsViewModel @AssistedInject constructor(
@Assisted val protocolInfo: Conversation.ProtocolInfo?,
private val getAllServices: ObserveAllServicesUseCase,
private val syncServices: SyncServicesUseCase,
private val getAllApps: ObserveAllAppsUseCase,
private val contactMapper: ContactMapper,
private val searchServicesByName: SearchServicesByNameUseCase,
Expand All @@ -63,6 +65,7 @@ class SearchAppsViewModel @AssistedInject constructor(
private val observeSelfUser: ObserveSelfUserUseCase
) : ViewModel() {
private val searchQueryTextFlow = MutableStateFlow(String.EMPTY)
private var servicesSynced = false
var state: SearchServicesState by mutableStateOf(SearchServicesState(isLoading = true))
private set

Expand Down Expand Up @@ -113,6 +116,10 @@ class SearchAppsViewModel @AssistedInject constructor(
val result = if (showNewApps) {
if (query.isEmpty()) getAllApps() else searchAppsByName(query)
} else {
if (!servicesSynced) {
servicesSynced = true
launch { syncServices() }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, shouldn't we wait until services are synced instead of launching sync in a coroutine and then returning services while it's still syncing?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the idea of this is to not wait, right now the app will just wait even tho the list of services is stored locally and probably didn't change

}
if (query.isEmpty()) getAllServices() else searchServicesByName(query)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ import com.wire.kalium.logic.feature.app.SearchAppsByNameUseCase
import com.wire.kalium.logic.feature.featureConfig.AppsAllowedProtocol
import com.wire.kalium.logic.feature.featureConfig.AppsAllowedResult
import com.wire.kalium.logic.feature.featureConfig.ObserveIsAppsAllowedForUsageUseCase
import com.wire.kalium.common.error.NetworkFailure
import com.wire.kalium.common.functional.Either
import com.wire.kalium.logic.feature.service.ObserveAllServicesUseCase
import com.wire.kalium.logic.feature.service.SearchServicesByNameUseCase
import com.wire.kalium.logic.feature.service.SyncServicesUseCase
import com.wire.kalium.logic.feature.user.ObserveSelfUserUseCase
import io.mockk.MockKAnnotations
import io.mockk.coEvery
Expand Down Expand Up @@ -266,6 +269,66 @@ class SearchAppsViewModelTest {
assertEquals(1, viewModel.state.result.size)
}

@Test
fun `given services branch is used across multiple searches, when init view model, then syncServices is called exactly once`() =
runTest {
// given
val query = "Service Name"
val (arrangement, viewModel) = Arrangement()
.withAppsAllowedForUsage(AppsAllowedResult.Enabled(AppsAllowedProtocol.PROTEUS))
.withGetAllServices(listOf(SERVICE_DETAILS))
.withSearchServicesByName(query, listOf(SERVICE_DETAILS))
.arrange(protocolInfo = null)

// when
advanceUntilIdle()
viewModel.searchQueryChanged(query)
advanceUntilIdle()
viewModel.searchQueryChanged(String.EMPTY)
advanceUntilIdle()

// then
coVerify(exactly = 1) {
arrangement.syncServices()
}
}

@Test
fun `given apps branch is used, when init view model, then syncServices is never called`() =
runTest {
// given
val (arrangement, _) = Arrangement()
.withAppsAllowedForUsage(AppsAllowedResult.Enabled(AppsAllowedProtocol.MLS))
.withGetAllApps(listOf(SERVICE_DETAILS))
.arrange(protocolInfo = null)

// when
advanceUntilIdle()

// then
coVerify(exactly = 0) {
arrangement.syncServices()
}
}

@Test
fun `given syncServices fails, when services branch is used, then observed services are still emitted`() =
runTest {
// given
val (_, viewModel) = Arrangement()
.withAppsAllowedForUsage(AppsAllowedResult.Enabled(AppsAllowedProtocol.PROTEUS))
.withGetAllServices(listOf(SERVICE_DETAILS, SERVICE_DETAILS2))
.withSyncServicesFailing()
.arrange(protocolInfo = null)

// when
advanceUntilIdle()

// then
assertEquals(2, viewModel.state.result.size)
assertFalse(viewModel.state.isLoading)
}

@Test
fun `given Apps feature flag is PROTEUS enabled, when searching for Apps by name, then load searched Services`() =
runTest {
Expand Down Expand Up @@ -340,6 +403,9 @@ class SearchAppsViewModelTest {
@MockK
lateinit var getAllServices: ObserveAllServicesUseCase

@MockK
lateinit var syncServices: SyncServicesUseCase

@MockK
lateinit var getAllApps: ObserveAllAppsUseCase

Expand All @@ -362,6 +428,7 @@ class SearchAppsViewModelTest {
MockKAnnotations.init(this, relaxUnitFun = true)

coEvery { getAllServices() } returns flowOf(emptyList())
coEvery { syncServices() } returns Either.Right(Unit)
coEvery { getAllApps() } returns flowOf(emptyList())
coEvery { searchServicesByName(any()) } returns flowOf(emptyList())
coEvery { searchAppsByName(any()) } returns flowOf(emptyList())
Expand All @@ -375,6 +442,7 @@ class SearchAppsViewModelTest {
fun arrange(protocolInfo: Conversation.ProtocolInfo?) = this to SearchAppsViewModel(
protocolInfo = protocolInfo,
getAllServices = getAllServices,
syncServices = syncServices,
getAllApps = getAllApps,
contactMapper = contactMapper,
searchServicesByName = searchServicesByName,
Expand Down Expand Up @@ -402,5 +470,9 @@ class SearchAppsViewModelTest {
fun withSearchServicesByName(query: String, result: List<ServiceDetails>) = apply {
coEvery { searchServicesByName(query) } returns flowOf(result)
}

fun withSyncServicesFailing() = apply {
coEvery { syncServices() } returns Either.Left(NetworkFailure.NoNetworkConnection(cause = null))
}
}
}
Loading