Handle server info inside of AuthDataSource

This commit is contained in:
Kirill Kamakin
2022-10-30 13:40:43 +01:00
parent 039ba20c83
commit 94c030c04d
7 changed files with 55 additions and 57 deletions

View File

@@ -1,23 +1,23 @@
package gq.kirmanak.mealient.data.add
data class AddRecipeInfo(
val name: String = "",
val description: String = "",
val recipeYield: String = "",
val recipeIngredient: List<AddRecipeIngredientInfo> = emptyList(),
val recipeInstructions: List<AddRecipeInstructionInfo> = emptyList(),
val settings: AddRecipeSettingsInfo = AddRecipeSettingsInfo(),
val name: String,
val description: String,
val recipeYield: String,
val recipeIngredient: List<AddRecipeIngredientInfo>,
val recipeInstructions: List<AddRecipeInstructionInfo>,
val settings: AddRecipeSettingsInfo,
)
data class AddRecipeSettingsInfo(
val disableComments: Boolean = false,
val public: Boolean = true,
val disableComments: Boolean,
val public: Boolean,
)
data class AddRecipeIngredientInfo(
val note: String = "",
val note: String,
)
data class AddRecipeInstructionInfo(
val text: String = "",
val text: String,
)

View File

@@ -1,15 +1,8 @@
package gq.kirmanak.mealient.data.auth
import gq.kirmanak.mealient.data.baseurl.ServerVersion
interface AuthDataSource {
/**
* Tries to acquire authentication token using the provided credentials
*/
suspend fun authenticate(
username: String,
password: String,
baseUrl: String,
serverVersion: ServerVersion,
): String
suspend fun authenticate(username: String, password: String): String
}

View File

@@ -1,6 +1,7 @@
package gq.kirmanak.mealient.data.auth.impl
import gq.kirmanak.mealient.data.auth.AuthDataSource
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.data.baseurl.ServerVersion
import gq.kirmanak.mealient.datasource.v0.MealieDataSourceV0
import gq.kirmanak.mealient.datasource.v1.MealieDataSourceV1
@@ -9,6 +10,7 @@ import javax.inject.Singleton
@Singleton
class AuthDataSourceImpl @Inject constructor(
private val serverInfoRepo: ServerInfoRepo,
private val v0Source: MealieDataSourceV0,
private val v1Source: MealieDataSourceV1,
) : AuthDataSource {
@@ -16,10 +18,11 @@ class AuthDataSourceImpl @Inject constructor(
override suspend fun authenticate(
username: String,
password: String,
baseUrl: String,
serverVersion: ServerVersion,
): String = when (serverVersion) {
ServerVersion.V0 -> v0Source.authenticate(baseUrl, username, password)
ServerVersion.V1 -> v1Source.authenticate(baseUrl, username, password)
): String {
val baseUrl = serverInfoRepo.requireUrl()
return when (serverInfoRepo.getVersion()) {
ServerVersion.V0 -> v0Source.authenticate(baseUrl, username, password)
ServerVersion.V1 -> v1Source.authenticate(baseUrl, username, password)
}
}
}

View File

@@ -3,7 +3,6 @@ package gq.kirmanak.mealient.data.auth.impl
import gq.kirmanak.mealient.data.auth.AuthDataSource
import gq.kirmanak.mealient.data.auth.AuthRepo
import gq.kirmanak.mealient.data.auth.AuthStorage
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
import gq.kirmanak.mealient.logging.Logger
import kotlinx.coroutines.flow.Flow
@@ -15,7 +14,6 @@ import javax.inject.Singleton
class AuthRepoImpl @Inject constructor(
private val authStorage: AuthStorage,
private val authDataSource: AuthDataSource,
private val serverInfoRepo: ServerInfoRepo,
private val logger: Logger,
) : AuthRepo {
@@ -24,11 +22,9 @@ class AuthRepoImpl @Inject constructor(
override suspend fun authenticate(email: String, password: String) {
logger.v { "authenticate() called with: email = $email, password = $password" }
val version = serverInfoRepo.getVersion()
val url = serverInfoRepo.requireUrl()
authDataSource.authenticate(email, password, url, version)
.let { AUTH_HEADER_FORMAT.format(it) }
.let { authStorage.setAuthHeader(it) }
val token = authDataSource.authenticate(email, password)
val header = AUTH_HEADER_FORMAT.format(token)
authStorage.setAuthHeader(header)
authStorage.setEmail(email)
authStorage.setPassword(password)
}

View File

@@ -42,7 +42,7 @@ class AuthRepoImplTest {
@Before
fun setUp() {
MockKAnnotations.init(this)
subject = AuthRepoImpl(storage, dataSource, serverInfoRepo, logger)
subject = AuthRepoImpl(storage, dataSource, logger)
}
@Test
@@ -54,14 +54,7 @@ class AuthRepoImplTest {
@Test
fun `when authenticate successfully then saves to storage`() = runTest {
coEvery { serverInfoRepo.getVersion() } returns TEST_SERVER_VERSION
coEvery {
dataSource.authenticate(
eq(TEST_USERNAME),
eq(TEST_PASSWORD),
eq(TEST_BASE_URL),
eq(TEST_SERVER_VERSION),
)
} returns TEST_TOKEN
coEvery { dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD)) } returns TEST_TOKEN
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
subject.authenticate(TEST_USERNAME, TEST_PASSWORD)
coVerifyAll {
@@ -74,7 +67,7 @@ class AuthRepoImplTest {
@Test
fun `when authenticate fails then does not change storage`() = runTest {
coEvery { dataSource.authenticate(any(), any(), any(), any()) } throws RuntimeException()
coEvery { dataSource.authenticate(any(), any()) } throws RuntimeException()
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
runCatchingExceptCancel { subject.authenticate("invalid", "") }
confirmVerified(storage)
@@ -113,17 +106,9 @@ class AuthRepoImplTest {
coEvery { storage.getPassword() } returns TEST_PASSWORD
coEvery { serverInfoRepo.getVersion() } returns TEST_SERVER_VERSION
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
coEvery {
dataSource.authenticate(
eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL), eq(TEST_SERVER_VERSION)
)
} returns TEST_TOKEN
coEvery { dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD)) } returns TEST_TOKEN
subject.invalidateAuthHeader()
coVerifyAll {
dataSource.authenticate(
eq(TEST_USERNAME), eq(TEST_PASSWORD), eq(TEST_BASE_URL), eq(TEST_SERVER_VERSION)
)
}
coVerifyAll { dataSource.authenticate(eq(TEST_USERNAME), eq(TEST_PASSWORD)) }
}
@Test
@@ -131,7 +116,7 @@ class AuthRepoImplTest {
coEvery { storage.getEmail() } returns "invalid"
coEvery { storage.getPassword() } returns ""
coEvery { serverInfoRepo.requireUrl() } returns TEST_BASE_URL
coEvery { dataSource.authenticate(any(), any(), any(), any()) } throws RuntimeException()
coEvery { dataSource.authenticate(any(), any()) } throws RuntimeException()
subject.invalidateAuthHeader()
coVerify { storage.setEmail(null) }
}

View File

@@ -1,5 +1,9 @@
package gq.kirmanak.mealient.test
import gq.kirmanak.mealient.data.add.AddRecipeInfo
import gq.kirmanak.mealient.data.add.AddRecipeIngredientInfo
import gq.kirmanak.mealient.data.add.AddRecipeInstructionInfo
import gq.kirmanak.mealient.data.add.AddRecipeSettingsInfo
import gq.kirmanak.mealient.data.recipes.network.FullRecipeInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeIngredientInfo
import gq.kirmanak.mealient.data.recipes.network.RecipeInstructionInfo
@@ -174,4 +178,21 @@ object RecipeImplTestData {
PORRIDGE_BOIL_RECIPE_INSTRUCTION_ENTITY,
)
)
val PORRIDGE_ADD_RECIPE_INFO = AddRecipeInfo(
name = "Porridge",
description = "Tasty breakfast",
recipeYield = "5 servings",
recipeIngredient = listOf(
AddRecipeIngredientInfo("Milk"),
AddRecipeIngredientInfo("Sugar"),
AddRecipeIngredientInfo("Salt"),
AddRecipeIngredientInfo("Porridge"),
),
recipeInstructions = listOf(
AddRecipeInstructionInfo("Mix"),
AddRecipeInstructionInfo("Cook"),
),
settings = AddRecipeSettingsInfo(disableComments = false, public = true),
)
}

View File

@@ -1,9 +1,9 @@
package gq.kirmanak.mealient.ui.add
import com.google.common.truth.Truth.assertThat
import gq.kirmanak.mealient.data.add.AddRecipeInfo
import gq.kirmanak.mealient.data.add.AddRecipeRepo
import gq.kirmanak.mealient.logging.Logger
import gq.kirmanak.mealient.test.RecipeImplTestData.PORRIDGE_ADD_RECIPE_INFO
import io.mockk.MockKAnnotations
import io.mockk.coEvery
import io.mockk.coVerify
@@ -61,21 +61,21 @@ class AddRecipeViewModelTest {
@Test
fun `when preserve then doesn't update UI`() {
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(AddRecipeInfo())
subject.preserve(AddRecipeInfo())
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(PORRIDGE_ADD_RECIPE_INFO)
subject.preserve(PORRIDGE_ADD_RECIPE_INFO)
coVerify(inverse = true) { addRecipeRepo.addRecipeRequestFlow }
}
@Test
fun `when preservedAddRecipeRequest without loadPreservedRequest then empty`() = runTest {
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(AddRecipeInfo())
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(PORRIDGE_ADD_RECIPE_INFO)
val actual = withTimeoutOrNull(10) { subject.preservedAddRecipeRequest.firstOrNull() }
assertThat(actual).isNull()
}
@Test
fun `when loadPreservedRequest then updates preservedAddRecipeRequest`() = runTest {
val expected = AddRecipeInfo()
val expected = PORRIDGE_ADD_RECIPE_INFO
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(expected)
subject.loadPreservedRequest()
assertThat(subject.preservedAddRecipeRequest.first()).isSameInstanceAs(expected)
@@ -83,7 +83,7 @@ class AddRecipeViewModelTest {
@Test
fun `when clear then updates preservedAddRecipeRequest`() = runTest {
val expected = AddRecipeInfo()
val expected = PORRIDGE_ADD_RECIPE_INFO
coEvery { addRecipeRepo.addRecipeRequestFlow } returns flowOf(expected)
subject.clear()
assertThat(subject.preservedAddRecipeRequest.first()).isSameInstanceAs(expected)