Implement adding recipes through app

This commit is contained in:
Kirill Kamakin
2022-05-26 13:29:10 +02:00
parent 986d8f377f
commit e18f726da5
37 changed files with 1105 additions and 78 deletions

View File

@@ -0,0 +1,46 @@
package gq.kirmanak.mealient.data.add.impl
import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.add.models.AddRecipeRequest
import gq.kirmanak.mealient.data.network.NetworkError
import gq.kirmanak.mealient.data.network.ServiceFactory
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import kotlinx.serialization.SerializationException
import org.junit.Before
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class AddRecipeDataSourceImplTest {
@MockK
lateinit var serviceProvider: ServiceFactory<AddRecipeService>
@MockK
lateinit var service: AddRecipeService
lateinit var subject: AddRecipeDataSourceImpl
@Before
fun setUp() {
MockKAnnotations.init(this)
coEvery { serviceProvider.provideService(any()) } returns service
subject = AddRecipeDataSourceImpl(serviceProvider)
}
@Test(expected = NetworkError.NotMealie::class)
fun `when addRecipe fails then maps error`() = runTest {
coEvery { service.addRecipe(any()) } throws SerializationException()
subject.addRecipe(AddRecipeRequest())
}
@Test
fun `when addRecipe succeeds then returns response`() = runTest {
coEvery { service.addRecipe(any()) } returns "response"
assertThat(subject.addRecipe(AddRecipeRequest())).isEqualTo("response")
}
}

View File

@@ -0,0 +1,73 @@
package gq.kirmanak.mealient.data.add.models
import com.google.common.truth.Truth.assertThat
import org.junit.Test
class AddRecipeRequestTest {
@Test
fun `when construct from input then fills fields correctly`() {
val input = AddRecipeInput.newBuilder()
.setRecipeName("Recipe name")
.setRecipeDescription("Recipe description")
.setRecipeYield("Recipe yield")
.addAllRecipeIngredients(listOf("Recipe ingredient 1", "Recipe ingredient 2"))
.addAllRecipeInstructions(listOf("Recipe instruction 1", "Recipe instruction 2"))
.setIsRecipePublic(false)
.setAreCommentsDisabled(true)
.build()
val expected = AddRecipeRequest(
name = "Recipe name",
description = "Recipe description",
recipeYield = "Recipe yield",
recipeIngredient = listOf(
AddRecipeIngredient(note = "Recipe ingredient 1"),
AddRecipeIngredient(note = "Recipe ingredient 2")
),
recipeInstructions = listOf(
AddRecipeInstruction(text = "Recipe instruction 1"),
AddRecipeInstruction(text = "Recipe instruction 2")
),
settings = AddRecipeSettings(
public = false,
disableComments = true,
)
)
assertThat(AddRecipeRequest(input)).isEqualTo(expected)
}
@Test
fun `when toInput then fills fields correctly`() {
val request = AddRecipeRequest(
name = "Recipe name",
description = "Recipe description",
recipeYield = "Recipe yield",
recipeIngredient = listOf(
AddRecipeIngredient(note = "Recipe ingredient 1"),
AddRecipeIngredient(note = "Recipe ingredient 2")
),
recipeInstructions = listOf(
AddRecipeInstruction(text = "Recipe instruction 1"),
AddRecipeInstruction(text = "Recipe instruction 2")
),
settings = AddRecipeSettings(
public = false,
disableComments = true,
)
)
val expected = AddRecipeInput.newBuilder()
.setRecipeName("Recipe name")
.setRecipeDescription("Recipe description")
.setRecipeYield("Recipe yield")
.addAllRecipeIngredients(listOf("Recipe ingredient 1", "Recipe ingredient 2"))
.addAllRecipeInstructions(listOf("Recipe instruction 1", "Recipe instruction 2"))
.setIsRecipePublic(false)
.setAreCommentsDisabled(true)
.build()
assertThat(request.toInput()).isEqualTo(expected)
}
}

View File

@@ -0,0 +1,87 @@
package gq.kirmanak.mealient.ui.add
import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.add.AddRecipeRepo
import gq.kirmanak.mealient.data.add.models.AddRecipeRequest
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
import io.mockk.impl.annotations.MockK
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import kotlinx.coroutines.withTimeoutOrNull
import org.junit.After
import org.junit.Before
import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class AddRecipeViewModelTest {
@MockK(relaxUnitFun = true)
lateinit var addRecipeRepo: AddRecipeRepo
lateinit var subject: AddRecipeViewModel
@Before
fun setUp() {
MockKAnnotations.init(this)
Dispatchers.setMain(UnconfinedTestDispatcher())
subject = AddRecipeViewModel(addRecipeRepo)
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `when saveRecipe fails then addRecipeResult is false`() = runTest {
coEvery { addRecipeRepo.saveRecipe() } throws IllegalStateException()
subject.saveRecipe()
assertThat(subject.addRecipeResult.first()).isFalse()
}
@Test
fun `when saveRecipe succeeds then addRecipeResult is true`() = runTest {
coEvery { addRecipeRepo.saveRecipe() } returns "recipe-slug"
subject.saveRecipe()
assertThat(subject.addRecipeResult.first()).isTrue()
}
@Test
fun `when preserve then doesn't update UI`() {
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(AddRecipeRequest())
subject.preserve(AddRecipeRequest())
coVerify(inverse = true) { addRecipeRepo.addRecipeRequestFlow }
}
@Test
fun `when preservedAddRecipeRequest without loadPreservedRequest then empty`() = runTest {
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(AddRecipeRequest())
val actual = withTimeoutOrNull(10) { subject.preservedAddRecipeRequest.firstOrNull() }
assertThat(actual).isNull()
}
@Test
fun `when loadPreservedRequest then updates preservedAddRecipeRequest`() = runTest {
val expected = AddRecipeRequest()
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(expected)
subject.loadPreservedRequest()
assertThat(subject.preservedAddRecipeRequest.first()).isSameInstanceAs(expected)
}
@Test
fun `when clear then updates preservedAddRecipeRequest`() = runTest {
val expected = AddRecipeRequest()
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(expected)
subject.clear()
assertThat(subject.preservedAddRecipeRequest.first()).isSameInstanceAs(expected)
}
}