Replace "Mealie" with "Mealient" everywhere
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package gq.kirmanak.mealient.data.auth.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_PASSWORD
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_TOKEN
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_USERNAME
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.body
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.enqueueSuccessfulAuthResponse
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.enqueueUnsuccessfulAuthResponse
|
||||
import gq.kirmanak.mealient.data.test.MockServerTest
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import org.junit.Test
|
||||
import retrofit2.HttpException
|
||||
import javax.inject.Inject
|
||||
|
||||
@ExperimentalSerializationApi
|
||||
@ExperimentalCoroutinesApi
|
||||
@HiltAndroidTest
|
||||
class AuthDataSourceImplTest : MockServerTest() {
|
||||
@Inject
|
||||
lateinit var subject: AuthDataSourceImpl
|
||||
|
||||
@Test
|
||||
fun `when authentication is successful then token is correct`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
val token = subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
assertThat(token).isEqualTo(TEST_TOKEN)
|
||||
}
|
||||
|
||||
@Test(expected = HttpException::class)
|
||||
fun `when authentication isn't successful then throws`(): Unit = runBlocking {
|
||||
mockServer.enqueueUnsuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when authentication is requested then body is correct`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
val body = mockServer.takeRequest().body()
|
||||
assertThat(body).isEqualTo("username=$TEST_USERNAME&password=$TEST_PASSWORD")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when authentication is requested then path is correct`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
val path = mockServer.takeRequest().path
|
||||
assertThat(path).isEqualTo("/api/auth/token")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package gq.kirmanak.mealient.data.auth.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_PASSWORD
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_TOKEN
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_USERNAME
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.enqueueSuccessfulAuthResponse
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.enqueueUnsuccessfulAuthResponse
|
||||
import gq.kirmanak.mealient.data.test.MockServerTest
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import retrofit2.HttpException
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidTest
|
||||
class AuthRepoImplTest : MockServerTest() {
|
||||
@Inject
|
||||
lateinit var subject: AuthRepoImpl
|
||||
|
||||
@Test
|
||||
fun `when not authenticated then first auth status is false`() = runBlocking {
|
||||
assertThat(subject.authenticationStatuses().first()).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when authenticated then first auth status is true`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
assertThat(subject.authenticationStatuses().first()).isTrue()
|
||||
}
|
||||
|
||||
@Test(expected = HttpException::class)
|
||||
fun `when authentication fails then authenticate throws`() = runBlocking {
|
||||
mockServer.enqueueUnsuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when authenticated then getToken returns token`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
assertThat(subject.getToken()).isEqualTo(TEST_TOKEN)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when authenticated then getBaseUrl returns url`() = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
subject.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
assertThat(subject.getBaseUrl()).isEqualTo(serverUrl)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package gq.kirmanak.mealient.data.auth.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_TOKEN
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_URL
|
||||
import gq.kirmanak.mealient.data.test.HiltRobolectricTest
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
|
||||
@ExperimentalCoroutinesApi
|
||||
@HiltAndroidTest
|
||||
class AuthStorageImplTest : HiltRobolectricTest() {
|
||||
@Inject
|
||||
lateinit var subject: AuthStorageImpl
|
||||
|
||||
@Test
|
||||
fun `when storing auth data then doesn't throw`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when reading url after storing data then returns url`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
assertThat(subject.getBaseUrl()).isEqualTo(TEST_URL)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when reading token after storing data then returns token`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
assertThat(subject.getToken()).isEqualTo(TEST_TOKEN)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when reading token without storing data then returns null`() = runBlocking {
|
||||
assertThat(subject.getToken()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when reading url without storing data then returns null`() = runBlocking {
|
||||
assertThat(subject.getBaseUrl()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when didn't store auth data then first token is null`() = runBlocking {
|
||||
assertThat(subject.tokenObservable().first()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when stored auth data then first token is correct`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
assertThat(subject.tokenObservable().first()).isEqualTo(TEST_TOKEN)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAuthData then first token is null`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
subject.clearAuthData()
|
||||
assertThat(subject.tokenObservable().first()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAuthData then getToken returns null`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
subject.clearAuthData()
|
||||
assertThat(subject.getToken()).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAuthData then getBaseUrl returns null`() = runBlocking {
|
||||
subject.storeAuthData(TEST_TOKEN, TEST_URL)
|
||||
subject.clearAuthData()
|
||||
assertThat(subject.getBaseUrl()).isNull()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package gq.kirmanak.mealient.data.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.auth.impl.AUTHORIZATION_HEADER
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_TOKEN
|
||||
import gq.kirmanak.mealient.data.test.MockServerTest
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidTest
|
||||
class OkHttpBuilderTest : MockServerTest() {
|
||||
|
||||
@Inject
|
||||
lateinit var subject: OkHttpBuilder
|
||||
|
||||
@Test
|
||||
fun `when token null then no auth header`() {
|
||||
val client = subject.buildOkHttp(null)
|
||||
val header = sendRequestAndExtractAuthHeader(client)
|
||||
assertThat(header).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when token isn't null then auth header contains token`() {
|
||||
val client = subject.buildOkHttp(TEST_TOKEN)
|
||||
val header = sendRequestAndExtractAuthHeader(client)
|
||||
assertThat(header).isEqualTo("Bearer $TEST_TOKEN")
|
||||
}
|
||||
|
||||
private fun sendRequestAndExtractAuthHeader(client: OkHttpClient): String? {
|
||||
mockServer.enqueue(MockResponse())
|
||||
val request = Request.Builder().url(serverUrl).get().build()
|
||||
client.newCall(request).execute()
|
||||
return mockServer.takeRequest().getHeader(AUTHORIZATION_HEADER)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package gq.kirmanak.mealient.data.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import org.junit.Test
|
||||
|
||||
class RoomTypeConvertersTest {
|
||||
@Test
|
||||
fun `when localDateTimeToTimestamp then correctly converts`() {
|
||||
val input = LocalDateTime.parse("2021-11-13T15:56:33")
|
||||
val actual = RoomTypeConverters.localDateTimeToTimestamp(input)
|
||||
assertThat(actual).isEqualTo(1636818993000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when timestampToLocalDateTime then correctly converts`() {
|
||||
val expected = LocalDateTime.parse("2021-11-13T15:58:38")
|
||||
val actual = RoomTypeConverters.timestampToLocalDateTime(1636819118000)
|
||||
assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when localDateToTimeStamp then correctly converts`() {
|
||||
val input = LocalDate.parse("2021-11-13")
|
||||
val actual = RoomTypeConverters.localDateToTimeStamp(input)
|
||||
assertThat(actual).isEqualTo(1636761600000)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when timestampToLocalDate then correctly converts`() {
|
||||
val expected = LocalDate.parse("2021-11-13")
|
||||
val actual = RoomTypeConverters.timestampToLocalDate(1636761600000)
|
||||
assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package gq.kirmanak.mealient.data.recipes.db
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.AppDb
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.CategoryEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.CategoryRecipeEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.TagEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.TagRecipeEntity
|
||||
import gq.kirmanak.mealient.data.test.HiltRobolectricTest
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.BREAD_INGREDIENT
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.CAKE_BREAD_RECIPE_INGREDIENT_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.CAKE_RECIPE_SUMMARY_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.FULL_PORRIDGE_INFO_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.GET_CAKE_RESPONSE
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.GET_PORRIDGE_RESPONSE
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.MIX_CAKE_RECIPE_INSTRUCTION_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.MIX_INSTRUCTION
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.PORRIDGE_RECIPE_SUMMARY_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.RECIPE_SUMMARY_CAKE
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.RECIPE_SUMMARY_PORRIDGE
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.TEST_RECIPE_SUMMARIES
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidTest
|
||||
class RecipeStorageImplTest : HiltRobolectricTest() {
|
||||
|
||||
@Inject
|
||||
lateinit var subject: RecipeStorageImpl
|
||||
|
||||
@Inject
|
||||
lateinit var appDb: AppDb
|
||||
|
||||
@Test
|
||||
fun `when saveRecipes then saves tags`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
val actualTags = appDb.recipeDao().queryAllTags()
|
||||
assertThat(actualTags).containsExactly(
|
||||
TagEntity(localId = 1, name = "gluten"),
|
||||
TagEntity(localId = 2, name = "allergic"),
|
||||
TagEntity(localId = 3, name = "milk")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipes then saves categories`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
val actual = appDb.recipeDao().queryAllCategories()
|
||||
assertThat(actual).containsExactly(
|
||||
CategoryEntity(localId = 1, name = "dessert"),
|
||||
CategoryEntity(localId = 2, name = "tasty"),
|
||||
CategoryEntity(localId = 3, name = "porridge")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipes then saves recipes`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
val actualTags = appDb.recipeDao().queryAllRecipes()
|
||||
assertThat(actualTags).containsExactly(
|
||||
CAKE_RECIPE_SUMMARY_ENTITY,
|
||||
PORRIDGE_RECIPE_SUMMARY_ENTITY
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipes then saves category recipes`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
val actual = appDb.recipeDao().queryAllCategoryRecipes()
|
||||
assertThat(actual).containsExactly(
|
||||
CategoryRecipeEntity(categoryId = 1, recipeId = 1),
|
||||
CategoryRecipeEntity(categoryId = 2, recipeId = 1),
|
||||
CategoryRecipeEntity(categoryId = 3, recipeId = 2),
|
||||
CategoryRecipeEntity(categoryId = 2, recipeId = 2)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipes then saves tag recipes`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
val actual = appDb.recipeDao().queryAllTagRecipes()
|
||||
assertThat(actual).containsExactly(
|
||||
TagRecipeEntity(tagId = 1, recipeId = 1),
|
||||
TagRecipeEntity(tagId = 2, recipeId = 1),
|
||||
TagRecipeEntity(tagId = 3, recipeId = 2),
|
||||
TagRecipeEntity(tagId = 1, recipeId = 2),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when refreshAll then old recipes aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE))
|
||||
val actual = appDb.recipeDao().queryAllRecipes()
|
||||
assertThat(actual).containsExactly(CAKE_RECIPE_SUMMARY_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when refreshAll then old category recipes aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE))
|
||||
val actual = appDb.recipeDao().queryAllCategoryRecipes()
|
||||
assertThat(actual).containsExactly(
|
||||
CategoryRecipeEntity(categoryId = 1, recipeId = 1),
|
||||
CategoryRecipeEntity(categoryId = 2, recipeId = 1),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when refreshAll then old tag recipes aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.refreshAll(listOf(RECIPE_SUMMARY_CAKE))
|
||||
val actual = appDb.recipeDao().queryAllTagRecipes()
|
||||
assertThat(actual).containsExactly(
|
||||
TagRecipeEntity(tagId = 1, recipeId = 1),
|
||||
TagRecipeEntity(tagId = 2, recipeId = 1),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAllLocalData then recipes aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.clearAllLocalData()
|
||||
val actual = appDb.recipeDao().queryAllRecipes()
|
||||
assertThat(actual).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAllLocalData then categories aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.clearAllLocalData()
|
||||
val actual = appDb.recipeDao().queryAllCategories()
|
||||
assertThat(actual).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when clearAllLocalData then tags aren't preserved`(): Unit = runBlocking {
|
||||
subject.saveRecipes(TEST_RECIPE_SUMMARIES)
|
||||
subject.clearAllLocalData()
|
||||
val actual = appDb.recipeDao().queryAllTags()
|
||||
assertThat(actual).isEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipeInfo then saves recipe info`(): Unit = runBlocking {
|
||||
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
subject.saveRecipeInfo(GET_CAKE_RESPONSE)
|
||||
val actual = appDb.recipeDao().queryFullRecipeInfo(1)
|
||||
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipeInfo with two then saves second`(): Unit = runBlocking {
|
||||
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE))
|
||||
subject.saveRecipeInfo(GET_CAKE_RESPONSE)
|
||||
subject.saveRecipeInfo(GET_PORRIDGE_RESPONSE)
|
||||
val actual = appDb.recipeDao().queryFullRecipeInfo(2)
|
||||
assertThat(actual).isEqualTo(FULL_PORRIDGE_INFO_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipeInfo secondly then overwrites ingredients`(): Unit = runBlocking {
|
||||
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
subject.saveRecipeInfo(GET_CAKE_RESPONSE)
|
||||
val newRecipe = GET_CAKE_RESPONSE.copy(recipeIngredients = listOf(BREAD_INGREDIENT))
|
||||
subject.saveRecipeInfo(newRecipe)
|
||||
val actual = appDb.recipeDao().queryFullRecipeInfo(1)?.recipeIngredients
|
||||
val expected = listOf(CAKE_BREAD_RECIPE_INGREDIENT_ENTITY.copy(localId = 3))
|
||||
assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when saveRecipeInfo secondly then overwrites instructions`(): Unit = runBlocking {
|
||||
subject.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
subject.saveRecipeInfo(GET_CAKE_RESPONSE)
|
||||
val newRecipe = GET_CAKE_RESPONSE.copy(recipeInstructions = listOf(MIX_INSTRUCTION))
|
||||
subject.saveRecipeInfo(newRecipe)
|
||||
val actual = appDb.recipeDao().queryFullRecipeInfo(1)?.recipeInstructions
|
||||
val expected = listOf(MIX_CAKE_RECIPE_INSTRUCTION_ENTITY.copy(localId = 3))
|
||||
assertThat(actual).isEqualTo(expected)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package gq.kirmanak.mealient.data.recipes.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.AppDb
|
||||
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||
import gq.kirmanak.mealient.data.recipes.db.RecipeStorage
|
||||
import gq.kirmanak.mealient.data.test.MockServerWithAuthTest
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.FULL_CAKE_INFO_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.RECIPE_SUMMARY_CAKE
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.enqueueSuccessfulGetRecipe
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.enqueueUnsuccessfulRecipeResponse
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltAndroidTest
|
||||
class RecipeRepoImplTest : MockServerWithAuthTest() {
|
||||
@Inject
|
||||
lateinit var subject: RecipeRepo
|
||||
|
||||
@Inject
|
||||
lateinit var storage: RecipeStorage
|
||||
|
||||
@Inject
|
||||
lateinit var appDb: AppDb
|
||||
|
||||
@Test
|
||||
fun `when loadRecipeInfo then loads recipe`(): Unit = runBlocking {
|
||||
storage.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
mockServer.enqueueSuccessfulGetRecipe()
|
||||
val actual = subject.loadRecipeInfo(1, "cake")
|
||||
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when loadRecipeInfo then saves to DB`(): Unit = runBlocking {
|
||||
storage.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
mockServer.enqueueSuccessfulGetRecipe()
|
||||
subject.loadRecipeInfo(1, "cake")
|
||||
val actual = appDb.recipeDao().queryFullRecipeInfo(1)
|
||||
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when loadRecipeInfo with error then loads from DB`(): Unit = runBlocking {
|
||||
storage.saveRecipes(listOf(RECIPE_SUMMARY_CAKE))
|
||||
mockServer.enqueueSuccessfulGetRecipe()
|
||||
subject.loadRecipeInfo(1, "cake")
|
||||
mockServer.enqueueUnsuccessfulRecipeResponse()
|
||||
val actual = subject.loadRecipeInfo(1, "cake")
|
||||
assertThat(actual).isEqualTo(FULL_CAKE_INFO_ENTITY)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package gq.kirmanak.mealient.data.recipes.impl
|
||||
|
||||
import androidx.paging.*
|
||||
import androidx.paging.LoadType.*
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import dagger.hilt.android.testing.HiltAndroidTest
|
||||
import gq.kirmanak.mealient.data.AppDb
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.data.test.MockServerWithAuthTest
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.CAKE_RECIPE_SUMMARY_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.PORRIDGE_RECIPE_SUMMARY_ENTITY
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.TEST_RECIPE_ENTITIES
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.enqueueSuccessfulRecipeSummaryResponse
|
||||
import gq.kirmanak.mealient.data.test.RecipeImplTestData.enqueueUnsuccessfulRecipeResponse
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Test
|
||||
import javax.inject.Inject
|
||||
|
||||
@ExperimentalPagingApi
|
||||
@HiltAndroidTest
|
||||
class RecipesRemoteMediatorTest : MockServerWithAuthTest() {
|
||||
private val pagingConfig = PagingConfig(
|
||||
pageSize = 2,
|
||||
prefetchDistance = 5,
|
||||
enablePlaceholders = false
|
||||
)
|
||||
|
||||
@Inject
|
||||
lateinit var subject: RecipesRemoteMediator
|
||||
|
||||
@Inject
|
||||
lateinit var appDb: AppDb
|
||||
|
||||
@Test
|
||||
fun `when first load with refresh successful then result success`(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
val result = subject.load(REFRESH, pagingState())
|
||||
assertThat(result).isInstanceOf(RemoteMediator.MediatorResult.Success::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when first load with refresh successful then recipes stored`(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
val actual = appDb.recipeDao().queryAllRecipes()
|
||||
assertThat(actual).containsExactly(
|
||||
CAKE_RECIPE_SUMMARY_ENTITY,
|
||||
PORRIDGE_RECIPE_SUMMARY_ENTITY
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when load state prepend then success`(): Unit = runBlocking {
|
||||
val result = subject.load(PREPEND, pagingState())
|
||||
assertThat(result).isInstanceOf(RemoteMediator.MediatorResult.Success::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when load state prepend then end is reached`(): Unit = runBlocking {
|
||||
val result = subject.load(PREPEND, pagingState())
|
||||
assertThat((result as RemoteMediator.MediatorResult.Success).endOfPaginationReached).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when load successful then lastRequestEnd updated`(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
val actual = subject.lastRequestEnd
|
||||
assertThat(actual).isEqualTo(2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when load fails then lastRequestEnd still 0`(): Unit = runBlocking {
|
||||
mockServer.enqueueUnsuccessfulRecipeResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
val actual = subject.lastRequestEnd
|
||||
assertThat(actual).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when load fails then result is error`(): Unit = runBlocking {
|
||||
mockServer.enqueueUnsuccessfulRecipeResponse()
|
||||
val actual = subject.load(REFRESH, pagingState())
|
||||
assertThat(actual).isInstanceOf(RemoteMediator.MediatorResult.Error::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when refresh then request params correct`(): Unit = runBlocking {
|
||||
mockServer.enqueueUnsuccessfulRecipeResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
val actual = mockServer.takeRequest().path
|
||||
assertThat(actual).isEqualTo("/api/recipes/summary?start=0&limit=6")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when append then request params correct`(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
mockServer.takeRequest()
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
subject.load(APPEND, pagingState())
|
||||
val actual = mockServer.takeRequest().path
|
||||
assertThat(actual).isEqualTo("/api/recipes/summary?start=2&limit=2")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when append fails then recipes aren't removed`(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulRecipeSummaryResponse()
|
||||
subject.load(REFRESH, pagingState())
|
||||
mockServer.takeRequest()
|
||||
mockServer.enqueueUnsuccessfulRecipeResponse()
|
||||
subject.load(APPEND, pagingState())
|
||||
val actual = appDb.recipeDao().queryAllRecipes()
|
||||
assertThat(actual).isEqualTo(TEST_RECIPE_ENTITIES)
|
||||
}
|
||||
|
||||
private fun pagingState(
|
||||
pages: List<PagingSource.LoadResult.Page<Int, RecipeSummaryEntity>> = emptyList(),
|
||||
anchorPosition: Int? = null
|
||||
): PagingState<Int, RecipeSummaryEntity> = PagingState(
|
||||
pages = pages,
|
||||
anchorPosition = anchorPosition,
|
||||
config = pagingConfig,
|
||||
leadingPlaceholderCount = 0
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package gq.kirmanak.mealient.data.test
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import okhttp3.mockwebserver.RecordedRequest
|
||||
import java.nio.charset.Charset
|
||||
|
||||
object AuthImplTestData {
|
||||
const val TEST_USERNAME = "TEST_USERNAME"
|
||||
const val TEST_PASSWORD = "TEST_PASSWORD"
|
||||
const val TEST_TOKEN = "TEST_TOKEN"
|
||||
const val SUCCESSFUL_AUTH_RESPONSE =
|
||||
"{\"access_token\":\"$TEST_TOKEN\",\"token_type\":\"TEST_TOKEN_TYPE\"}"
|
||||
const val UNSUCCESSFUL_AUTH_RESPONSE =
|
||||
"{\"detail\":\"Unauthorized\"}"
|
||||
const val TEST_URL = "TEST_URL"
|
||||
|
||||
fun RecordedRequest.body() = body.readString(Charset.defaultCharset())
|
||||
|
||||
fun MockWebServer.enqueueUnsuccessfulAuthResponse() {
|
||||
val response = MockResponse()
|
||||
.setBody(UNSUCCESSFUL_AUTH_RESPONSE)
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setResponseCode(401)
|
||||
enqueue(response)
|
||||
}
|
||||
|
||||
fun MockWebServer.enqueueSuccessfulAuthResponse() {
|
||||
val response = MockResponse()
|
||||
.setBody(SUCCESSFUL_AUTH_RESPONSE)
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setResponseCode(200)
|
||||
enqueue(response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package gq.kirmanak.mealient.data.test
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import dagger.hilt.android.testing.HiltAndroidRule
|
||||
import dagger.hilt.android.testing.HiltTestApplication
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Rule
|
||||
import org.junit.runner.RunWith
|
||||
import org.robolectric.annotation.Config
|
||||
import timber.log.Timber
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@Config(application = HiltTestApplication::class, manifest = Config.NONE)
|
||||
abstract class HiltRobolectricTest {
|
||||
companion object {
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setupTimber() {
|
||||
Timber.plant(object : Timber.Tree() {
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
println(message)
|
||||
t?.printStackTrace()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@get:Rule
|
||||
var hiltRule = HiltAndroidRule(this)
|
||||
|
||||
@Before
|
||||
fun inject() {
|
||||
hiltRule.inject()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package gq.kirmanak.mealient.data.test
|
||||
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
|
||||
abstract class MockServerTest : HiltRobolectricTest() {
|
||||
lateinit var mockServer: MockWebServer
|
||||
lateinit var serverUrl: String
|
||||
|
||||
@Before
|
||||
fun startMockServer() {
|
||||
mockServer = MockWebServer().apply {
|
||||
start()
|
||||
}
|
||||
serverUrl = mockServer.url("/").toString()
|
||||
}
|
||||
|
||||
@After
|
||||
fun stopMockServer() {
|
||||
mockServer.shutdown()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package gq.kirmanak.mealient.data.test
|
||||
|
||||
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_PASSWORD
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.TEST_USERNAME
|
||||
import gq.kirmanak.mealient.data.test.AuthImplTestData.enqueueSuccessfulAuthResponse
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Before
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class MockServerWithAuthTest : MockServerTest() {
|
||||
@Inject
|
||||
lateinit var authRepo: AuthRepo
|
||||
|
||||
@Before
|
||||
fun authenticate(): Unit = runBlocking {
|
||||
mockServer.enqueueSuccessfulAuthResponse()
|
||||
authRepo.authenticate(TEST_USERNAME, TEST_PASSWORD, serverUrl)
|
||||
mockServer.takeRequest()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,410 @@
|
||||
package gq.kirmanak.mealient.data.test
|
||||
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeIngredientEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeInstructionEntity
|
||||
import gq.kirmanak.mealient.data.recipes.db.entity.RecipeSummaryEntity
|
||||
import gq.kirmanak.mealient.data.recipes.impl.FullRecipeInfo
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeIngredientResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeInstructionResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeResponse
|
||||
import gq.kirmanak.mealient.data.recipes.network.response.GetRecipeSummaryResponse
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.LocalDateTime
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
|
||||
object RecipeImplTestData {
|
||||
val RECIPE_SUMMARY_CAKE = GetRecipeSummaryResponse(
|
||||
remoteId = 1,
|
||||
name = "Cake",
|
||||
slug = "cake",
|
||||
image = "86",
|
||||
description = "A tasty cake",
|
||||
recipeCategories = listOf("dessert", "tasty"),
|
||||
tags = listOf("gluten", "allergic"),
|
||||
rating = 4,
|
||||
dateAdded = LocalDate.parse("2021-11-13"),
|
||||
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"),
|
||||
)
|
||||
|
||||
val RECIPE_SUMMARY_PORRIDGE = GetRecipeSummaryResponse(
|
||||
remoteId = 2,
|
||||
name = "Porridge",
|
||||
slug = "porridge",
|
||||
image = "89",
|
||||
description = "A tasty porridge",
|
||||
recipeCategories = listOf("porridge", "tasty"),
|
||||
tags = listOf("gluten", "milk"),
|
||||
rating = 5,
|
||||
dateAdded = LocalDate.parse("2021-11-12"),
|
||||
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
|
||||
)
|
||||
|
||||
val TEST_RECIPE_SUMMARIES = listOf(RECIPE_SUMMARY_CAKE, RECIPE_SUMMARY_PORRIDGE)
|
||||
|
||||
const val RECIPE_SUMMARY_SUCCESSFUL = """[
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Cake",
|
||||
"slug": "cake",
|
||||
"image": "86",
|
||||
"description": "A tasty cake",
|
||||
"recipeCategory": ["dessert", "tasty"],
|
||||
"tags": ["gluten", "allergic"],
|
||||
"rating": 4,
|
||||
"dateAdded": "2021-11-13",
|
||||
"dateUpdated": "2021-11-13T15:30:13"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Porridge",
|
||||
"slug": "porridge",
|
||||
"image": "89",
|
||||
"description": "A tasty porridge",
|
||||
"recipeCategory": ["porridge", "tasty"],
|
||||
"tags": ["gluten", "milk"],
|
||||
"rating": 5,
|
||||
"dateAdded": "2021-11-12",
|
||||
"dateUpdated": "2021-10-13T17:35:23"
|
||||
}
|
||||
]"""
|
||||
|
||||
const val RECIPE_SUMMARY_UNSUCCESSFUL = """
|
||||
{"detail":"Unauthorized"}
|
||||
"""
|
||||
|
||||
val CAKE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
|
||||
remoteId = 1,
|
||||
name = "Cake",
|
||||
slug = "cake",
|
||||
image = "86",
|
||||
description = "A tasty cake",
|
||||
rating = 4,
|
||||
dateAdded = LocalDate.parse("2021-11-13"),
|
||||
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13")
|
||||
)
|
||||
|
||||
val PORRIDGE_RECIPE_SUMMARY_ENTITY = RecipeSummaryEntity(
|
||||
remoteId = 2,
|
||||
name = "Porridge",
|
||||
slug = "porridge",
|
||||
image = "89",
|
||||
description = "A tasty porridge",
|
||||
rating = 5,
|
||||
dateAdded = LocalDate.parse("2021-11-12"),
|
||||
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
|
||||
)
|
||||
|
||||
val TEST_RECIPE_ENTITIES = listOf(CAKE_RECIPE_SUMMARY_ENTITY, PORRIDGE_RECIPE_SUMMARY_ENTITY)
|
||||
|
||||
fun MockWebServer.enqueueSuccessfulRecipeSummaryResponse() {
|
||||
val response = MockResponse()
|
||||
.setBody(RECIPE_SUMMARY_SUCCESSFUL)
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setResponseCode(200)
|
||||
enqueue(response)
|
||||
}
|
||||
|
||||
fun MockWebServer.enqueueUnsuccessfulRecipeResponse() {
|
||||
val response = MockResponse()
|
||||
.setBody(RECIPE_SUMMARY_UNSUCCESSFUL)
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setResponseCode(401)
|
||||
enqueue(response)
|
||||
}
|
||||
|
||||
val SUGAR_INGREDIENT = GetRecipeIngredientResponse(
|
||||
title = "Sugar",
|
||||
note = "2 oz of white sugar",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = true,
|
||||
quantity = 1
|
||||
)
|
||||
|
||||
val BREAD_INGREDIENT = GetRecipeIngredientResponse(
|
||||
title = "Bread",
|
||||
note = "2 oz of white bread",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = false,
|
||||
quantity = 2
|
||||
)
|
||||
|
||||
val MILK_INGREDIENT = GetRecipeIngredientResponse(
|
||||
title = "Milk",
|
||||
note = "2 oz of white milk",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = true,
|
||||
quantity = 3
|
||||
)
|
||||
|
||||
val MIX_INSTRUCTION = GetRecipeInstructionResponse(
|
||||
title = "Mix",
|
||||
text = "Mix the ingredients"
|
||||
)
|
||||
|
||||
val BAKE_INSTRUCTION = GetRecipeInstructionResponse(
|
||||
title = "Bake",
|
||||
text = "Bake the ingredients"
|
||||
)
|
||||
|
||||
val BOIL_INSTRUCTION = GetRecipeInstructionResponse(
|
||||
title = "Boil",
|
||||
text = "Boil the ingredients"
|
||||
)
|
||||
|
||||
val GET_CAKE_RESPONSE = GetRecipeResponse(
|
||||
remoteId = 1,
|
||||
name = "Cake",
|
||||
slug = "cake",
|
||||
image = "86",
|
||||
description = "A tasty cake",
|
||||
recipeCategories = listOf("dessert", "tasty"),
|
||||
tags = listOf("gluten", "allergic"),
|
||||
rating = 4,
|
||||
dateAdded = LocalDate.parse("2021-11-13"),
|
||||
dateUpdated = LocalDateTime.parse("2021-11-13T15:30:13"),
|
||||
recipeYield = "4 servings",
|
||||
recipeIngredients = listOf(SUGAR_INGREDIENT, BREAD_INGREDIENT),
|
||||
recipeInstructions = listOf(MIX_INSTRUCTION, BAKE_INSTRUCTION)
|
||||
)
|
||||
|
||||
val GET_CAKE_RESPONSE_BODY = """
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Cake",
|
||||
"slug": "cake",
|
||||
"image": "86",
|
||||
"description": "A tasty cake",
|
||||
"recipeCategory": ["dessert", "tasty"],
|
||||
"tags": ["gluten", "allergic"],
|
||||
"rating": 4,
|
||||
"dateAdded": "2021-11-13",
|
||||
"dateUpdated": "2021-11-13T15:30:13",
|
||||
"recipeYield": "4 servings",
|
||||
"recipeIngredient": [
|
||||
{
|
||||
"title": "Sugar",
|
||||
"note": "2 oz of white sugar",
|
||||
"unit": null,
|
||||
"food": null,
|
||||
"disableAmount": true,
|
||||
"quantity": 1
|
||||
},
|
||||
{
|
||||
"title": "Bread",
|
||||
"note": "2 oz of white bread",
|
||||
"unit": null,
|
||||
"food": null,
|
||||
"disableAmount": false,
|
||||
"quantity": 2
|
||||
}
|
||||
],
|
||||
"recipeInstructions": [
|
||||
{
|
||||
"title": "Mix",
|
||||
"text": "Mix the ingredients"
|
||||
},
|
||||
{
|
||||
"title": "Bake",
|
||||
"text": "Bake the ingredients"
|
||||
}
|
||||
],
|
||||
"nutrition": {
|
||||
"calories": "100",
|
||||
"fatContent": "20",
|
||||
"proteinContent": "30",
|
||||
"carbohydrateContent": "40",
|
||||
"fiberContent": "50",
|
||||
"sodiumContent": "23",
|
||||
"sugarContent": "53"
|
||||
},
|
||||
"tools": [],
|
||||
"totalTime": "12 hours",
|
||||
"prepTime": "1 hour",
|
||||
"performTime": "4 hours",
|
||||
"settings": {
|
||||
"public": true,
|
||||
"showNutrition": true,
|
||||
"showAssets": true,
|
||||
"landscapeView": true,
|
||||
"disableComments": false,
|
||||
"disableAmount": false
|
||||
},
|
||||
"assets": [],
|
||||
"notes": [
|
||||
{
|
||||
"title": "Note title",
|
||||
"text": "Note text"
|
||||
},
|
||||
{
|
||||
"title": "Second note",
|
||||
"text": "Second note text"
|
||||
}
|
||||
],
|
||||
"orgURL": null,
|
||||
"extras": {},
|
||||
"comments": [
|
||||
{
|
||||
"text": "A new comment",
|
||||
"id": 1,
|
||||
"uuid": "476ebc15-f794-4eda-8380-d77bba47f839",
|
||||
"recipeSlug": "test-recipe",
|
||||
"dateAdded": "2021-11-19T22:13:23.862459",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "kirmanak",
|
||||
"admin": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"text": "A second comment",
|
||||
"id": 2,
|
||||
"uuid": "20498eba-9639-4acd-ba0a-4829ee06915a",
|
||||
"recipeSlug": "test-recipe",
|
||||
"dateAdded": "2021-11-19T22:13:29.912314",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "kirmanak",
|
||||
"admin": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
val GET_PORRIDGE_RESPONSE = GetRecipeResponse(
|
||||
remoteId = 2,
|
||||
name = "Porridge",
|
||||
slug = "porridge",
|
||||
image = "89",
|
||||
description = "A tasty porridge",
|
||||
recipeCategories = listOf("porridge", "tasty"),
|
||||
tags = listOf("gluten", "milk"),
|
||||
rating = 5,
|
||||
dateAdded = LocalDate.parse("2021-11-12"),
|
||||
dateUpdated = LocalDateTime.parse("2021-10-13T17:35:23"),
|
||||
recipeYield = "3 servings",
|
||||
recipeIngredients = listOf(SUGAR_INGREDIENT, MILK_INGREDIENT),
|
||||
recipeInstructions = listOf(MIX_INSTRUCTION, BOIL_INSTRUCTION)
|
||||
)
|
||||
|
||||
val MIX_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
|
||||
localId = 1,
|
||||
recipeId = 1,
|
||||
title = "Mix",
|
||||
text = "Mix the ingredients",
|
||||
)
|
||||
|
||||
val BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
|
||||
localId = 2,
|
||||
recipeId = 1,
|
||||
title = "Bake",
|
||||
text = "Bake the ingredients",
|
||||
)
|
||||
|
||||
val CAKE_RECIPE_ENTITY = RecipeEntity(
|
||||
remoteId = 1,
|
||||
recipeYield = "4 servings"
|
||||
)
|
||||
|
||||
val CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
|
||||
localId = 1,
|
||||
recipeId = 1,
|
||||
title = "Sugar",
|
||||
note = "2 oz of white sugar",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = true,
|
||||
quantity = 1
|
||||
)
|
||||
|
||||
val CAKE_BREAD_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
|
||||
localId = 2,
|
||||
recipeId = 1,
|
||||
title = "Bread",
|
||||
note = "2 oz of white bread",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = false,
|
||||
quantity = 2
|
||||
)
|
||||
|
||||
val FULL_CAKE_INFO_ENTITY = FullRecipeInfo(
|
||||
recipeEntity = CAKE_RECIPE_ENTITY,
|
||||
recipeSummaryEntity = CAKE_RECIPE_SUMMARY_ENTITY,
|
||||
recipeIngredients = listOf(
|
||||
CAKE_SUGAR_RECIPE_INGREDIENT_ENTITY,
|
||||
CAKE_BREAD_RECIPE_INGREDIENT_ENTITY,
|
||||
),
|
||||
recipeInstructions = listOf(
|
||||
MIX_CAKE_RECIPE_INSTRUCTION_ENTITY,
|
||||
BAKE_CAKE_RECIPE_INSTRUCTION_ENTITY,
|
||||
),
|
||||
)
|
||||
|
||||
val PORRIDGE_RECIPE_ENTITY_FULL = RecipeEntity(
|
||||
remoteId = 2,
|
||||
recipeYield = "3 servings"
|
||||
)
|
||||
|
||||
val PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
|
||||
localId = 4,
|
||||
recipeId = 2,
|
||||
title = "Milk",
|
||||
note = "2 oz of white milk",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = true,
|
||||
quantity = 3
|
||||
)
|
||||
|
||||
val PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY = RecipeIngredientEntity(
|
||||
localId = 3,
|
||||
recipeId = 2,
|
||||
title = "Sugar",
|
||||
note = "2 oz of white sugar",
|
||||
unit = "",
|
||||
food = "",
|
||||
disableAmount = true,
|
||||
quantity = 1
|
||||
)
|
||||
|
||||
val PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
|
||||
localId = 3,
|
||||
recipeId = 2,
|
||||
title = "Mix",
|
||||
text = "Mix the ingredients"
|
||||
)
|
||||
|
||||
val PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY = RecipeInstructionEntity(
|
||||
localId = 4,
|
||||
recipeId = 2,
|
||||
title = "Boil",
|
||||
text = "Boil the ingredients"
|
||||
)
|
||||
|
||||
val FULL_PORRIDGE_INFO_ENTITY = FullRecipeInfo(
|
||||
recipeEntity = PORRIDGE_RECIPE_ENTITY_FULL,
|
||||
recipeSummaryEntity = PORRIDGE_RECIPE_SUMMARY_ENTITY,
|
||||
recipeIngredients = listOf(
|
||||
PORRIDGE_SUGAR_RECIPE_INGREDIENT_ENTITY,
|
||||
PORRIDGE_MILK_RECIPE_INGREDIENT_ENTITY,
|
||||
),
|
||||
recipeInstructions = listOf(
|
||||
PORRIDGE_MIX_RECIPE_INSTRUCTION_ENTITY,
|
||||
PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY,
|
||||
)
|
||||
)
|
||||
|
||||
fun MockWebServer.enqueueSuccessfulGetRecipe() {
|
||||
val response = MockResponse()
|
||||
.setResponseCode(200)
|
||||
.setHeader("Content-Type", "application/json")
|
||||
.setBody(GET_CAKE_RESPONSE_BODY)
|
||||
enqueue(response)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user