Skip to content

Commit

Permalink
fix: new clients info after logout [WPB-6126] (#2366)
Browse files Browse the repository at this point in the history
  • Loading branch information
saleniuk authored Jan 16, 2024
1 parent abde2b3 commit e688160
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,17 @@ import com.wire.kalium.logic.functional.mapToRightOr
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map

/**
* Observes new Clients for all the users that are logged in on device
* returns [NewClientResult] which may be:
* [NewClientResult.InCurrentAccount] if new Clients appears for the user that is currently used.
* [NewClientResult.InOtherAccount] if new Clients appears for the user that is logged in on device, but not currently used.
* [NewClientResult.Empty] if there are no new Clients for any of the logged-in Users.
* [NewClientResult.Error] in case of error, in most cases it means that the user for which new Client appeared
* is no longer logged it on the device.
*
Expand All @@ -59,6 +61,7 @@ class ObserveNewClientsUseCaseImpl internal constructor(
.flatMapLatest { validAccs ->
val users = validAccs.map { it.first }
observeAllNewClients(users)
.map { it.filter { (_, clients) -> clients.isNotEmpty() } }
.map { groupByUser ->
if (groupByUser.isEmpty()) return@map NewClientResult.Empty

Expand All @@ -82,19 +85,23 @@ class ObserveNewClientsUseCaseImpl internal constructor(
}.getOrElse(NewClientResult.Error)
}
}
.filter {
// if newClients list is empty mean no NewClients - do not emit anything
(it is NewClientResult.InCurrentAccount && it.newClients.isNotEmpty()) ||
(it is NewClientResult.InOtherAccount && it.newClients.isNotEmpty()) ||
it is NewClientResult.Error
.map {
when {
it is NewClientResult.InCurrentAccount && it.newClients.isEmpty() -> NewClientResult.Empty
it is NewClientResult.InOtherAccount && it.newClients.isEmpty() -> NewClientResult.Empty
else -> it
}
}
.distinctUntilChanged()

private suspend fun observeNewClientsForUser(userId: UserId) = clientRepositoryProvider.provide(userId)
.observeNewClients()
.mapToRightOr(listOf())
.map { it to userId }

private suspend fun observeAllNewClients(validAccs: List<SelfUser>): Flow<Map<UserId, List<Client>>> {
if (validAccs.isEmpty()) return flowOf(emptyMap())

val observeNewClientsFlows = validAccs.map { selfUser -> observeNewClientsForUser(selfUser.id) }

return combine(observeNewClientsFlows) { newClientsListWithUserId ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
* Copyright (C) 2024 Wire Swiss GmbH
*
* 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
Expand Down Expand Up @@ -40,7 +40,10 @@ import io.mockative.mock
import io.mockative.once
import io.mockative.verify
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
Expand All @@ -51,7 +54,7 @@ class ObserveNewClientsUseCaseTest {
@Test
fun givenNewClientAndCurrentSessionError_thenNewClientErrorResult() = runTest {
val (_, observeNewClients) = Arrangement()
.withoutValidAccounts(listOf(TestUser.SELF to null))
.withValidAccounts(listOf(TestUser.SELF to null))
.withCurrentSession(Either.Left(StorageFailure.DataNotFound))
.withNewClientsForUser1(listOf(TestClient.CLIENT))
.arrange()
Expand All @@ -65,7 +68,7 @@ class ObserveNewClientsUseCaseTest {
@Test
fun givenNewClientForCurrentUser_thenNewClientInCurrentUserResult() = runTest {
val (_, observeNewClients) = Arrangement()
.withoutValidAccounts(listOf(TestUser.SELF to null))
.withValidAccounts(listOf(TestUser.SELF to null))
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(listOf(TestClient.CLIENT))
.arrange()
Expand All @@ -80,7 +83,7 @@ class ObserveNewClientsUseCaseTest {
@Test
fun givenNewClientForOtherUser_thenNewClientInOtherUserResult() = runTest {
val (arrangement, observeNewClients) = Arrangement()
.withoutValidAccounts(listOf(TestUser.SELF to null, TestUser.SELF.copy(id = TestUser.OTHER_USER_ID) to null))
.withValidAccounts(listOf(TestUser.SELF to null, TestUser.SELF.copy(id = TestUser.OTHER_USER_ID) to null))
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(listOf())
.withNewClientsForUser2(listOf(TestClient.CLIENT))
Expand Down Expand Up @@ -109,7 +112,7 @@ class ObserveNewClientsUseCaseTest {
val client1 = TestClient.CLIENT
val client2 = TestClient.CLIENT.copy(id = ClientId("other_client"))
val (_, observeNewClients) = Arrangement()
.withoutValidAccounts(listOf(TestUser.SELF to null, TestUser.SELF.copy(id = TestUser.OTHER_USER_ID) to null))
.withValidAccounts(listOf(TestUser.SELF to null, TestUser.SELF.copy(id = TestUser.OTHER_USER_ID) to null))
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(listOf(client1))
.withNewClientsForUser2(listOf(client2))
Expand All @@ -127,7 +130,7 @@ class ObserveNewClientsUseCaseTest {
val client1 = TestClient.CLIENT
val client2 = TestClient.CLIENT.copy(id = ClientId("other_client"))
val (_, observeNewClients) = Arrangement()
.withoutValidAccounts(listOf(TestUser.SELF to null))
.withValidAccounts(listOf(TestUser.SELF to null))
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(listOf(client1, client2))
.arrange()
Expand All @@ -139,6 +142,53 @@ class ObserveNewClientsUseCaseTest {
}
}

@Test
fun givenNoNewClients_thenEmptyResult() = runTest {
val (_, observeNewClients) = Arrangement()
.withValidAccounts(listOf(TestUser.SELF to null))
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(emptyList())
.arrange()

observeNewClients().test {
assertEquals(NewClientResult.Empty, awaitItem())

awaitComplete()
}
}

@Test
fun givenNoAccountsLoggedIn_thenEmptyResult() = runTest {
val (_, observeNewClients) = Arrangement()
.withValidAccounts(emptyList())
.arrange()

observeNewClients().test {
assertEquals(NewClientResult.Empty, awaitItem())

awaitComplete()
}
}
@Test
fun givenNewClientForCurrentUser_whenUserIsBeingLoggedOut_thenChangeToEmptyResult() = runTest {
val validAccountsFlow = MutableStateFlow(listOf(TestUser.SELF to null))
val (_, observeNewClients) = Arrangement()
.withValidAccountsFlow(validAccountsFlow)
.withCurrentSession(Either.Right(TEST_ACCOUNT_INFO))
.withNewClientsForUser1(listOf(TestClient.CLIENT))
.arrange()

observeNewClients().test {
assertEquals(NewClientResult.InCurrentAccount(listOf(TestClient.CLIENT), TestUser.USER_ID), awaitItem())

validAccountsFlow.value = emptyList()
advanceUntilIdle()
assertEquals(NewClientResult.Empty, awaitItem())

cancel()
}
}

companion object {
val TEST_ACCOUNT_INFO: AccountInfo = AccountInfo.Valid(userId = TestUser.USER_ID)
}
Expand Down Expand Up @@ -198,12 +248,18 @@ class ObserveNewClientsUseCaseTest {
.then { flowOf(Either.Right(result)) }
}

fun withoutValidAccounts(result: List<Pair<SelfUser, Team?>>) = apply {
fun withValidAccounts(result: List<Pair<SelfUser, Team?>>) = apply {
given(observeValidAccounts)
.function(observeValidAccounts::invoke)
.whenInvoked()
.thenReturn(flowOf(result))
}
fun withValidAccountsFlow(flowResult: Flow<List<Pair<SelfUser, Team?>>>) = apply {
given(observeValidAccounts)
.function(observeValidAccounts::invoke)
.whenInvoked()
.thenReturn(flowResult)
}

fun arrange() = this to observeNewClientsUseCase
}
Expand Down

0 comments on commit e688160

Please sign in to comment.