Skip to content

Commit

Permalink
feat: more errors handling for personal migration #WPB-14281 (#3134)
Browse files Browse the repository at this point in the history
* feat: more errors handling for personal migration WPB-14281

* test fix

* dektet

* test cleanup
  • Loading branch information
damian-kaczmarek authored Nov 29, 2024
1 parent 4d95d50 commit 4c476f7
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ package com.wire.kalium.logic.feature.user.migration
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.id.TeamId
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.NetworkFailure
import com.wire.kalium.logic.data.user.UserRepository
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.network.exceptions.KaliumException

/**
* Use case to migrate user personal account to team account.
Expand All @@ -33,7 +35,20 @@ interface MigrateFromPersonalToTeamUseCase {

sealed class MigrateFromPersonalToTeamResult {
data object Success : MigrateFromPersonalToTeamResult()
data class Error(val failure: CoreFailure) : MigrateFromPersonalToTeamResult()
data class Error(val failure: MigrateFromPersonalToTeamFailure) :
MigrateFromPersonalToTeamResult()
}

sealed class MigrateFromPersonalToTeamFailure {

data class UnknownError(val coreFailure: CoreFailure) : MigrateFromPersonalToTeamFailure()
class UserAlreadyInTeam : MigrateFromPersonalToTeamFailure() {
companion object {
const val ERROR_LABEL = "user-already-in-a-team"
}
}

data object NoNetwork : MigrateFromPersonalToTeamFailure()
}

internal class MigrateFromPersonalToTeamUseCaseImpl internal constructor(
Expand All @@ -44,14 +59,43 @@ internal class MigrateFromPersonalToTeamUseCaseImpl internal constructor(
override suspend operator fun invoke(
teamName: String,
): MigrateFromPersonalToTeamResult {
return userRepository.migrateUserToTeam(teamName)
.fold(
{ error -> return MigrateFromPersonalToTeamResult.Error(error) },
{ user ->
userRepository.updateTeamId(selfUserId, TeamId(user.teamId))
invalidateTeamId()
MigrateFromPersonalToTeamResult.Success
return userRepository.migrateUserToTeam(teamName).fold({ error ->
return when (error) {
is NetworkFailure.ServerMiscommunication -> {
if (error.kaliumException is KaliumException.InvalidRequestError) {
val response = error.kaliumException.errorResponse
if (response.label == MigrateFromPersonalToTeamFailure.UserAlreadyInTeam.ERROR_LABEL) {
MigrateFromPersonalToTeamResult.Error(
MigrateFromPersonalToTeamFailure.UserAlreadyInTeam()
)
} else {
MigrateFromPersonalToTeamResult.Error(
MigrateFromPersonalToTeamFailure.UnknownError(error)
)
}
} else {
MigrateFromPersonalToTeamResult.Error(
MigrateFromPersonalToTeamFailure.UnknownError(error)
)
}
}
)

is NetworkFailure.NoNetworkConnection -> {
MigrateFromPersonalToTeamResult.Error(MigrateFromPersonalToTeamFailure.NoNetwork)
}

else -> {
MigrateFromPersonalToTeamResult.Error(
MigrateFromPersonalToTeamFailure.UnknownError(
error
)
)
}
}
}, { user ->
userRepository.updateTeamId(selfUserId, TeamId(user.teamId))
invalidateTeamId()
MigrateFromPersonalToTeamResult.Success
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,45 +59,45 @@ class MigrateFromPersonalToTeamUseCaseTest {
}

@Test
fun givenRepositoryFailsWithNoNetworkConnection_whenMigratingUserToTeam_thenShouldPropagateFailure() =
fun givenRepositoryFailsWithNoNetworkConnection_whenMigratingUserToTeam_thenShouldPropagateNoNetworkFailure() =
runTest {
val coreFailure = NetworkFailure.NoNetworkConnection(null)
val (_, useCase) = Arrangement().withMigrationReturning(Either.Left(coreFailure))
val (_, useCase) = Arrangement()
.withMigrationNoNetworkFailure()
.arrange()

val result = useCase(teamName = "teamName")

assertIs<MigrateFromPersonalToTeamResult.Error>(result)
assertIs<NetworkFailure.NoNetworkConnection>(result.failure)
assertIs<MigrateFromPersonalToTeamFailure.NoNetwork>(result.failure)
}

@Test
fun givenRepositoryFailsWithUserAlreadyInTeam_whenMigratingUserToTeam_thenShouldPropagateFailure() =
fun givenRepositoryFailsWithUserAlreadyInTeam_whenMigratingUserToTeam_thenShouldPropagateUserAlreadyInTeamFailure() =
runTest {
val (_, useCase) = Arrangement().withUserAlreadyInTeamRepository().arrange()
val (_, useCase) = Arrangement()
.withUserAlreadyInTeamFailure()
.arrange()

val result = useCase(teamName = "teamName")

assertIs<MigrateFromPersonalToTeamResult.Error>(result)
assertIs<NetworkFailure.ServerMiscommunication>(result.failure)
val serverMiscommunication = result.failure as NetworkFailure.ServerMiscommunication
val invalidRequestError =
serverMiscommunication.kaliumException as KaliumException.InvalidRequestError
val errorLabel = invalidRequestError.errorResponse.label

assertEquals("user-already-in-a-team", errorLabel)
assertIs<MigrateFromPersonalToTeamFailure.UserAlreadyInTeam>(result.failure)
}

@Test
fun givenRepositoryFailsWithNotFound_whenMigratingUserToTeam_thenShouldPropagateFailure() =
fun givenRepositoryFailsWithUnknownError_whenMigratingUserToTeam_thenShouldPropagateUnknownFailure() =
runTest {
val (_, useCase) = Arrangement().withMigrationFailure().arrange()
val (_, useCase) = Arrangement()
.withMigrationUserNotFoundFailure()
.arrange()

val result = useCase(teamName = "teamName")

assertIs<MigrateFromPersonalToTeamResult.Error>(result)
assertIs<NetworkFailure.ServerMiscommunication>(result.failure)
val serverMiscommunication = result.failure as NetworkFailure.ServerMiscommunication
assertIs<MigrateFromPersonalToTeamFailure.UnknownError>(result.failure)
val coreFailure =
(result.failure as MigrateFromPersonalToTeamFailure.UnknownError).coreFailure
val serverMiscommunication = coreFailure as NetworkFailure.ServerMiscommunication
val invalidRequestError =
serverMiscommunication.kaliumException as KaliumException.InvalidRequestError
val errorLabel = invalidRequestError.errorResponse.label
Expand All @@ -120,53 +120,51 @@ class MigrateFromPersonalToTeamUseCaseTest {
)
}

suspend fun withUserAlreadyInTeamRepository() = apply {
coEvery { userRepository.migrateUserToTeam(any()) }.returns(
Either.Left(
NetworkFailure.ServerMiscommunication(
KaliumException.InvalidRequestError(
ErrorResponse(
HttpStatusCode.Forbidden.value,
message = "Switching teams is not allowed",
label = "user-already-in-a-team",
)
suspend fun withUserAlreadyInTeamFailure() = withMigrationReturning(
Either.Left(
NetworkFailure.ServerMiscommunication(
KaliumException.InvalidRequestError(
ErrorResponse(
HttpStatusCode.Forbidden.value,
message = "Switching teams is not allowed",
label = "user-already-in-a-team",
)
)
)
)
}
)

suspend fun withMigrationFailure() = apply {
coEvery { userRepository.migrateUserToTeam(any()) }.returns(
Either.Left(
NetworkFailure.ServerMiscommunication(
KaliumException.InvalidRequestError(
ErrorResponse(
HttpStatusCode.NotFound.value,
message = "User not found",
label = "not-found",
)

suspend fun withMigrationUserNotFoundFailure() = withMigrationReturning(
Either.Left(
NetworkFailure.ServerMiscommunication(
KaliumException.InvalidRequestError(
ErrorResponse(
HttpStatusCode.NotFound.value,
message = "User not found",
label = "not-found",
)
)
)
)
}
)

suspend fun withMigrationReturning(result: Either<CoreFailure, CreateUserTeam>) =
apply {
coEvery { userRepository.migrateUserToTeam(any()) }.returns(result)
}
suspend fun withMigrationNoNetworkFailure() = withMigrationReturning(
Either.Left(NetworkFailure.NoNetworkConnection(null))
)

suspend fun withMigrationReturning(result: Either<CoreFailure, CreateUserTeam>) = apply {
coEvery { userRepository.migrateUserToTeam(any()) }.returns(result)
}

suspend fun withUpdateTeamIdReturning(result: Either<StorageFailure, Unit>) = apply {
coEvery { userRepository.updateTeamId(any(), any()) }.returns(result)
}

fun arrange() = this to MigrateFromPersonalToTeamUseCaseImpl(
selfUserId = TestUser.SELF.id,
fun arrange() = this to MigrateFromPersonalToTeamUseCaseImpl(selfUserId = TestUser.SELF.id,
userRepository = userRepository,
invalidateTeamId = {
isCachedTeamIdInvalidated = true
}
)
})
}
}

0 comments on commit 4c476f7

Please sign in to comment.