Remove recipe from local db when deleted

This commit is contained in:
Kirill Kamakin
2022-12-16 20:24:40 +01:00
parent 28fa19c988
commit 226097d096
9 changed files with 31 additions and 37 deletions

View File

@@ -20,5 +20,5 @@ interface RecipeRepo {
suspend fun updateIsRecipeFavorite(recipeSlug: String, isFavorite: Boolean): Result<Unit> suspend fun updateIsRecipeFavorite(recipeSlug: String, isFavorite: Boolean): Result<Unit>
suspend fun deleteRecipe(recipeSlug: String): Result<Unit> suspend fun deleteRecipe(entity: RecipeSummaryEntity): Result<Unit>
} }

View File

@@ -19,4 +19,6 @@ interface RecipeStorage {
suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity? suspend fun queryRecipeInfo(recipeId: String): FullRecipeEntity?
suspend fun updateFavoriteRecipes(favorites: List<String>) suspend fun updateFavoriteRecipes(favorites: List<String>)
suspend fun deleteRecipe(entity: RecipeSummaryEntity)
} }

View File

@@ -80,4 +80,9 @@ class RecipeStorageImpl @Inject constructor(
recipeDao.setNonFavorite(favorites) recipeDao.setNonFavorite(favorites)
} }
} }
override suspend fun deleteRecipe(entity: RecipeSummaryEntity) {
logger.v { "deleteRecipeBySlug() called with: entity = $entity" }
recipeDao.deleteRecipe(entity)
}
} }

View File

@@ -78,15 +78,20 @@ class RecipeRepoImpl @Inject constructor(
): Result<Unit> = runCatchingExceptCancel { ): Result<Unit> = runCatchingExceptCancel {
logger.v { "updateIsRecipeFavorite() called with: recipeSlug = $recipeSlug, isFavorite = $isFavorite" } logger.v { "updateIsRecipeFavorite() called with: recipeSlug = $recipeSlug, isFavorite = $isFavorite" }
dataSource.updateIsRecipeFavorite(recipeSlug, isFavorite) dataSource.updateIsRecipeFavorite(recipeSlug, isFavorite)
mediator.onFavoritesChange() val favorites = dataSource.getFavoriteRecipes()
storage.updateFavoriteRecipes(favorites)
pagingSourceFactory.invalidate()
}.onFailure { }.onFailure {
logger.e(it) { "Can't update recipe's is favorite status" } logger.e(it) { "Can't update recipe's is favorite status" }
} }
override suspend fun deleteRecipe(recipeSlug: String): Result<Unit> = runCatchingExceptCancel { override suspend fun deleteRecipe(
logger.v { "deleteRecipe() called with: recipeSlug = $recipeSlug" } entity: RecipeSummaryEntity
dataSource.deleteRecipe(recipeSlug) ): Result<Unit> = runCatchingExceptCancel {
// TODO update local db logger.v { "deleteRecipe() called with: entity = $entity" }
dataSource.deleteRecipe(entity.slug)
storage.deleteRecipe(entity)
pagingSourceFactory.invalidate()
}.onFailure { }.onFailure {
logger.e(it) { "Can't delete recipe" } logger.e(it) { "Can't delete recipe" }
} }

View File

@@ -83,10 +83,4 @@ class RecipesRemoteMediator @Inject constructor(
recipes.size recipes.size
} }
suspend fun onFavoritesChange() {
logger.v { "onFavoritesChange() called" }
val favorites = network.getFavoriteRecipes()
storage.updateFavoriteRecipes(favorites)
pagingSourceFactory.invalidate()
}
} }

View File

@@ -71,7 +71,7 @@ class RecipesListViewModel @Inject constructor(
fun onDeleteConfirm(recipeSummaryEntity: RecipeSummaryEntity) { fun onDeleteConfirm(recipeSummaryEntity: RecipeSummaryEntity) {
logger.v { "onDeleteConfirm() called with: recipeSummaryEntity = $recipeSummaryEntity" } logger.v { "onDeleteConfirm() called with: recipeSummaryEntity = $recipeSummaryEntity" }
viewModelScope.launch { viewModelScope.launch {
val result = recipeRepo.deleteRecipe(recipeSummaryEntity.slug) val result = recipeRepo.deleteRecipe(recipeSummaryEntity)
_deleteRecipeResult.emit(result) _deleteRecipeResult.emit(result)
} }
} }

View File

@@ -70,19 +70,25 @@ class RecipeRepoTest : BaseUnitTest() {
@Test @Test
fun `when remove favorite recipe expect correct sequence`() = runTest { fun `when remove favorite recipe expect correct sequence`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } returns listOf("porridge")
subject.updateIsRecipeFavorite("cake", false) subject.updateIsRecipeFavorite("cake", false)
coVerify { coVerify {
dataSource.updateIsRecipeFavorite(eq("cake"), eq(false)) dataSource.updateIsRecipeFavorite(eq("cake"), eq(false))
remoteMediator.onFavoritesChange() dataSource.getFavoriteRecipes()
storage.updateFavoriteRecipes(eq(listOf("porridge")))
pagingSourceFactory.invalidate()
} }
} }
@Test @Test
fun `when add favorite recipe expect correct sequence`() = runTest { fun `when add favorite recipe expect correct sequence`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } returns listOf("porridge", "cake")
subject.updateIsRecipeFavorite("porridge", true) subject.updateIsRecipeFavorite("porridge", true)
coVerify { coVerify {
dataSource.updateIsRecipeFavorite(eq("porridge"), eq(true)) dataSource.updateIsRecipeFavorite(eq("porridge"), eq(true))
remoteMediator.onFavoritesChange() dataSource.getFavoriteRecipes()
storage.updateFavoriteRecipes(eq(listOf("porridge", "cake")))
pagingSourceFactory.invalidate()
} }
} }
@@ -92,7 +98,7 @@ class RecipeRepoTest : BaseUnitTest() {
dataSource.updateIsRecipeFavorite(any(), any()) dataSource.updateIsRecipeFavorite(any(), any())
} throws Unauthorized(IOException()) } throws Unauthorized(IOException())
subject.updateIsRecipeFavorite("porridge", true) subject.updateIsRecipeFavorite("porridge", true)
coVerify(inverse = true) { remoteMediator.onFavoritesChange() } coVerify(inverse = true) { dataSource.getFavoriteRecipes() }
} }
@Test @Test

View File

@@ -144,27 +144,6 @@ class RecipesRemoteMediatorTest : BaseUnitTest() {
coVerify { storage.refreshAll(TEST_RECIPE_SUMMARY_ENTITIES) } coVerify { storage.refreshAll(TEST_RECIPE_SUMMARY_ENTITIES) }
} }
@Test
fun `when favorites change expect network call`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } returns listOf("cake", "porridge")
subject.onFavoritesChange()
coVerify { dataSource.getFavoriteRecipes() }
}
@Test
fun `when favorites change expect storage update`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } returns listOf("cake", "porridge")
subject.onFavoritesChange()
coVerify { storage.updateFavoriteRecipes(eq(listOf("cake", "porridge"))) }
}
@Test
fun `when favorites change expect factory invalidation`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } returns listOf("cake", "porridge")
subject.onFavoritesChange()
coVerify { pagingSourceFactory.invalidate() }
}
@Test @Test
fun `when recipe update requested but favorite fails expect non-zero updates`() = runTest { fun `when recipe update requested but favorite fails expect non-zero updates`() = runTest {
coEvery { dataSource.getFavoriteRecipes() } throws Unauthorized(IOException()) coEvery { dataSource.getFavoriteRecipes() } throws Unauthorized(IOException())

View File

@@ -46,4 +46,7 @@ interface RecipeDao {
@Query("UPDATE recipe_summaries SET is_favorite = 0 WHERE slug NOT IN (:favorites)") @Query("UPDATE recipe_summaries SET is_favorite = 0 WHERE slug NOT IN (:favorites)")
suspend fun setNonFavorite(favorites: List<String>) suspend fun setNonFavorite(favorites: List<String>)
@Delete
suspend fun deleteRecipe(entity: RecipeSummaryEntity)
} }