Implement adding recipes through app
This commit is contained in:
@@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user