Merge pull request #90 from kirmanak/allow-server-change
Allow changing server URL through UI
This commit is contained in:
@@ -5,14 +5,16 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.net.toUri
|
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import androidx.navigation.NavDirections
|
||||||
import androidx.navigation.fragment.NavHostFragment
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||||
import com.google.android.material.shape.CornerFamily
|
import com.google.android.material.shape.CornerFamily
|
||||||
import com.google.android.material.shape.MaterialShapeDrawable
|
import com.google.android.material.shape.MaterialShapeDrawable
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
import gq.kirmanak.mealient.NavGraphDirections
|
||||||
import gq.kirmanak.mealient.R
|
import gq.kirmanak.mealient.R
|
||||||
import gq.kirmanak.mealient.databinding.MainActivityBinding
|
import gq.kirmanak.mealient.databinding.MainActivityBinding
|
||||||
import gq.kirmanak.mealient.extensions.observeOnce
|
import gq.kirmanak.mealient.extensions.observeOnce
|
||||||
@@ -20,9 +22,9 @@ import gq.kirmanak.mealient.logging.Logger
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity(R.layout.main_activity) {
|
||||||
|
|
||||||
private lateinit var binding: MainActivityBinding
|
private val binding: MainActivityBinding by viewBinding(MainActivityBinding::bind, R.id.drawer)
|
||||||
private val viewModel by viewModels<MainActivityViewModel>()
|
private val viewModel by viewModels<MainActivityViewModel>()
|
||||||
private val title: String by lazy { getString(R.string.app_name) }
|
private val title: String by lazy { getString(R.string.app_name) }
|
||||||
private val uiState: MainActivityUiState get() = viewModel.uiState
|
private val uiState: MainActivityUiState get() = viewModel.uiState
|
||||||
@@ -37,7 +39,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
logger.v { "onCreate() called with: savedInstanceState = $savedInstanceState" }
|
logger.v { "onCreate() called with: savedInstanceState = $savedInstanceState" }
|
||||||
splashScreen.setKeepOnScreenCondition { viewModel.startDestination.value == null }
|
splashScreen.setKeepOnScreenCondition { viewModel.startDestination.value == null }
|
||||||
binding = MainActivityBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
configureToolbar()
|
configureToolbar()
|
||||||
configureNavGraph()
|
configureNavGraph()
|
||||||
@@ -64,12 +65,13 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
|
private fun onNavigationItemSelected(menuItem: MenuItem): Boolean {
|
||||||
logger.v { "onNavigationItemSelected() called with: menuItem = $menuItem" }
|
logger.v { "onNavigationItemSelected() called with: menuItem = $menuItem" }
|
||||||
menuItem.isChecked = true
|
menuItem.isChecked = true
|
||||||
val deepLink = when (menuItem.itemId) {
|
val directions = when (menuItem.itemId) {
|
||||||
R.id.add_recipe -> ADD_RECIPE_DEEP_LINK
|
R.id.add_recipe -> NavGraphDirections.actionGlobalAddRecipeFragment()
|
||||||
R.id.recipes_list -> RECIPES_LIST_DEEP_LINK
|
R.id.recipes_list -> NavGraphDirections.actionGlobalRecipesFragment()
|
||||||
|
R.id.change_url -> NavGraphDirections.actionGlobalBaseURLFragment()
|
||||||
else -> throw IllegalArgumentException("Unknown menu item id: ${menuItem.itemId}")
|
else -> throw IllegalArgumentException("Unknown menu item id: ${menuItem.itemId}")
|
||||||
}
|
}
|
||||||
navigateDeepLink(deepLink)
|
navigateTo(directions)
|
||||||
binding.drawer.close()
|
binding.drawer.close()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -109,7 +111,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
logger.v { "onOptionsItemSelected() called with: item = $item" }
|
logger.v { "onOptionsItemSelected() called with: item = $item" }
|
||||||
val result = when (item.itemId) {
|
val result = when (item.itemId) {
|
||||||
R.id.login -> {
|
R.id.login -> {
|
||||||
navigateDeepLink(AUTH_DEEP_LINK)
|
navigateTo(NavGraphDirections.actionGlobalAuthenticationFragment())
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
R.id.logout -> {
|
R.id.logout -> {
|
||||||
@@ -121,14 +123,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigateDeepLink(deepLink: String) {
|
private fun navigateTo(directions: NavDirections) {
|
||||||
logger.v { "navigateDeepLink() called with: deepLink = $deepLink" }
|
logger.v { "navigateTo() called with: directions = $directions" }
|
||||||
navController.navigate(deepLink.toUri())
|
navController.navigate(directions)
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val AUTH_DEEP_LINK = "mealient://authenticate"
|
|
||||||
private const val ADD_RECIPE_DEEP_LINK = "mealient://recipe/add"
|
|
||||||
private const val RECIPES_LIST_DEEP_LINK = "mealient://recipe/list"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,10 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||||
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
||||||
import gq.kirmanak.mealient.data.baseurl.VersionDataSource
|
import gq.kirmanak.mealient.data.baseurl.VersionDataSource
|
||||||
|
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||||
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
|
import gq.kirmanak.mealient.datasource.runCatchingExceptCancel
|
||||||
import gq.kirmanak.mealient.logging.Logger
|
import gq.kirmanak.mealient.logging.Logger
|
||||||
import gq.kirmanak.mealient.ui.OperationUiState
|
import gq.kirmanak.mealient.ui.OperationUiState
|
||||||
@@ -16,6 +18,8 @@ import javax.inject.Inject
|
|||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class BaseURLViewModel @Inject constructor(
|
class BaseURLViewModel @Inject constructor(
|
||||||
private val serverInfoRepo: ServerInfoRepo,
|
private val serverInfoRepo: ServerInfoRepo,
|
||||||
|
private val authRepo: AuthRepo,
|
||||||
|
private val recipeRepo: RecipeRepo,
|
||||||
private val versionDataSource: VersionDataSource,
|
private val versionDataSource: VersionDataSource,
|
||||||
private val logger: Logger,
|
private val logger: Logger,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
@@ -33,10 +37,17 @@ class BaseURLViewModel @Inject constructor(
|
|||||||
|
|
||||||
private suspend fun checkBaseURL(baseURL: String) {
|
private suspend fun checkBaseURL(baseURL: String) {
|
||||||
logger.v { "checkBaseURL() called with: baseURL = $baseURL" }
|
logger.v { "checkBaseURL() called with: baseURL = $baseURL" }
|
||||||
|
if (baseURL == serverInfoRepo.getUrl()) {
|
||||||
|
logger.d { "checkBaseURL: new URL matches current" }
|
||||||
|
_uiState.value = OperationUiState.fromResult(Result.success(Unit))
|
||||||
|
return
|
||||||
|
}
|
||||||
val result = runCatchingExceptCancel {
|
val result = runCatchingExceptCancel {
|
||||||
// If it returns proper version info then it must be a Mealie
|
// If it returns proper version info then it must be a Mealie
|
||||||
val version = versionDataSource.getVersionInfo(baseURL).version
|
val version = versionDataSource.getVersionInfo(baseURL).version
|
||||||
serverInfoRepo.storeBaseURL(baseURL, version)
|
serverInfoRepo.storeBaseURL(baseURL, version)
|
||||||
|
authRepo.logout()
|
||||||
|
recipeRepo.clearLocalData()
|
||||||
}
|
}
|
||||||
logger.i { "checkBaseURL: result is $result" }
|
logger.i { "checkBaseURL: result is $result" }
|
||||||
_uiState.value = OperationUiState.fromResult(result)
|
_uiState.value = OperationUiState.fromResult(result)
|
||||||
|
|||||||
@@ -7,4 +7,8 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/add_recipe"
|
android:id="@+id/add_recipe"
|
||||||
android:title="@string/menu_bottom_navigation_add_recipe" />
|
android:title="@string/menu_bottom_navigation_add_recipe" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/change_url"
|
||||||
|
android:title="@string/menu_bottom_navigation_change_url" />
|
||||||
</menu>
|
</menu>
|
||||||
@@ -9,11 +9,8 @@
|
|||||||
android:id="@+id/authenticationFragment"
|
android:id="@+id/authenticationFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.auth.AuthenticationFragment"
|
android:name="gq.kirmanak.mealient.ui.auth.AuthenticationFragment"
|
||||||
android:label="AuthenticationFragment"
|
android:label="AuthenticationFragment"
|
||||||
tools:layout="@layout/fragment_authentication">
|
tools:layout="@layout/fragment_authentication" />
|
||||||
<deepLink
|
|
||||||
android:id="@+id/deepLink"
|
|
||||||
app:uri="mealient://authenticate" />
|
|
||||||
</fragment>
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/recipesFragment"
|
android:id="@+id/recipesFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.recipes.RecipesFragment"
|
android:name="gq.kirmanak.mealient.ui.recipes.RecipesFragment"
|
||||||
@@ -22,10 +19,8 @@
|
|||||||
<action
|
<action
|
||||||
android:id="@+id/action_recipesFragment_to_recipeInfoFragment"
|
android:id="@+id/action_recipesFragment_to_recipeInfoFragment"
|
||||||
app:destination="@id/recipeInfoFragment" />
|
app:destination="@id/recipeInfoFragment" />
|
||||||
<deepLink
|
|
||||||
android:id="@+id/deepLink"
|
|
||||||
app:uri="mealient://recipe/list" />
|
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<dialog
|
<dialog
|
||||||
android:id="@+id/recipeInfoFragment"
|
android:id="@+id/recipeInfoFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.recipes.info.RecipeInfoFragment"
|
android:name="gq.kirmanak.mealient.ui.recipes.info.RecipeInfoFragment"
|
||||||
@@ -35,6 +30,7 @@
|
|||||||
android:name="recipe_id"
|
android:name="recipe_id"
|
||||||
app:argType="string" />
|
app:argType="string" />
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/disclaimerFragment"
|
android:id="@+id/disclaimerFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.disclaimer.DisclaimerFragment"
|
android:name="gq.kirmanak.mealient.ui.disclaimer.DisclaimerFragment"
|
||||||
@@ -46,6 +42,7 @@
|
|||||||
app:popUpTo="@id/nav_graph"
|
app:popUpTo="@id/nav_graph"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/baseURLFragment"
|
android:id="@+id/baseURLFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.baseurl.BaseURLFragment"
|
android:name="gq.kirmanak.mealient.ui.baseurl.BaseURLFragment"
|
||||||
@@ -57,13 +54,26 @@
|
|||||||
app:popUpTo="@id/nav_graph"
|
app:popUpTo="@id/nav_graph"
|
||||||
app:popUpToInclusive="true" />
|
app:popUpToInclusive="true" />
|
||||||
</fragment>
|
</fragment>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/addRecipeFragment"
|
android:id="@+id/addRecipeFragment"
|
||||||
android:name="gq.kirmanak.mealient.ui.add.AddRecipeFragment"
|
android:name="gq.kirmanak.mealient.ui.add.AddRecipeFragment"
|
||||||
android:label="fragment_add_recipe"
|
android:label="fragment_add_recipe"
|
||||||
tools:layout="@layout/fragment_add_recipe">
|
tools:layout="@layout/fragment_add_recipe" />
|
||||||
<deepLink
|
|
||||||
android:id="@+id/deepLink"
|
<action
|
||||||
app:uri="mealient://recipe/add" />
|
android:id="@+id/action_global_authenticationFragment"
|
||||||
</fragment>
|
app:destination="@id/authenticationFragment" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_recipesFragment"
|
||||||
|
app:destination="@id/recipesFragment" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_addRecipeFragment"
|
||||||
|
app:destination="@id/addRecipeFragment" />
|
||||||
|
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_global_baseURLFragment"
|
||||||
|
app:destination="@id/baseURLFragment" />
|
||||||
</navigation>
|
</navigation>
|
||||||
@@ -47,4 +47,5 @@
|
|||||||
<string name="fragment_recipes_load_failure_toast_unexpected_response">неожиданный ответ</string>
|
<string name="fragment_recipes_load_failure_toast_unexpected_response">неожиданный ответ</string>
|
||||||
<string name="fragment_recipes_load_failure_toast_no_connection">нет соединения</string>
|
<string name="fragment_recipes_load_failure_toast_no_connection">нет соединения</string>
|
||||||
<string name="fragment_recipes_load_failure_toast_no_reason">Ошибка загрузки.</string>
|
<string name="fragment_recipes_load_failure_toast_no_reason">Ошибка загрузки.</string>
|
||||||
|
<string name="menu_bottom_navigation_change_url">Сменить URL</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -51,4 +51,5 @@
|
|||||||
<string name="fragment_recipes_load_failure_toast_unauthorized">unauthorized</string>
|
<string name="fragment_recipes_load_failure_toast_unauthorized">unauthorized</string>
|
||||||
<string name="fragment_recipes_load_failure_toast_unexpected_response">unexpected response</string>
|
<string name="fragment_recipes_load_failure_toast_unexpected_response">unexpected response</string>
|
||||||
<string name="fragment_recipes_load_failure_toast_no_connection">no connection</string>
|
<string name="fragment_recipes_load_failure_toast_no_connection">no connection</string>
|
||||||
|
<string name="menu_bottom_navigation_change_url">Change URL</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package gq.kirmanak.mealient.test
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.robolectric.annotation.Config
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
@Config(application = Application::class, manifest = Config.NONE)
|
|
||||||
abstract class RobolectricTest
|
|
||||||
@@ -1,32 +1,48 @@
|
|||||||
package gq.kirmanak.mealient.ui.baseurl
|
package gq.kirmanak.mealient.ui.baseurl
|
||||||
|
|
||||||
|
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import gq.kirmanak.mealient.data.auth.AuthRepo
|
||||||
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
import gq.kirmanak.mealient.data.baseurl.ServerInfoRepo
|
||||||
import gq.kirmanak.mealient.data.baseurl.VersionDataSource
|
import gq.kirmanak.mealient.data.baseurl.VersionDataSource
|
||||||
import gq.kirmanak.mealient.data.baseurl.VersionInfo
|
import gq.kirmanak.mealient.data.baseurl.VersionInfo
|
||||||
|
import gq.kirmanak.mealient.data.recipes.RecipeRepo
|
||||||
import gq.kirmanak.mealient.logging.Logger
|
import gq.kirmanak.mealient.logging.Logger
|
||||||
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
|
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_BASE_URL
|
||||||
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION
|
import gq.kirmanak.mealient.test.AuthImplTestData.TEST_VERSION
|
||||||
import gq.kirmanak.mealient.test.FakeLogger
|
import gq.kirmanak.mealient.test.FakeLogger
|
||||||
import gq.kirmanak.mealient.test.RobolectricTest
|
import gq.kirmanak.mealient.ui.OperationUiState
|
||||||
import io.mockk.MockKAnnotations
|
import io.mockk.MockKAnnotations
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.coVerify
|
import io.mockk.coVerify
|
||||||
import io.mockk.impl.annotations.MockK
|
import io.mockk.impl.annotations.MockK
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.*
|
||||||
import kotlinx.coroutines.test.runTest
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class BaseURLViewModelTest : RobolectricTest() {
|
class BaseURLViewModelTest {
|
||||||
|
|
||||||
@MockK(relaxUnitFun = true)
|
@MockK(relaxUnitFun = true)
|
||||||
lateinit var serverInfoRepo: ServerInfoRepo
|
lateinit var serverInfoRepo: ServerInfoRepo
|
||||||
|
|
||||||
|
@MockK(relaxUnitFun = true)
|
||||||
|
lateinit var authRepo: AuthRepo
|
||||||
|
|
||||||
|
@MockK(relaxUnitFun = true)
|
||||||
|
lateinit var recipeRepo: RecipeRepo
|
||||||
|
|
||||||
@MockK
|
@MockK
|
||||||
lateinit var versionDataSource: VersionDataSource
|
lateinit var versionDataSource: VersionDataSource
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val instantExecutorRule = InstantTaskExecutorRule()
|
||||||
|
|
||||||
private val logger: Logger = FakeLogger()
|
private val logger: Logger = FakeLogger()
|
||||||
|
|
||||||
lateinit var subject: BaseURLViewModel
|
lateinit var subject: BaseURLViewModel
|
||||||
@@ -34,16 +50,89 @@ class BaseURLViewModelTest : RobolectricTest() {
|
|||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockKAnnotations.init(this)
|
MockKAnnotations.init(this)
|
||||||
subject = BaseURLViewModel(serverInfoRepo, versionDataSource, logger)
|
Dispatchers.setMain(UnconfinedTestDispatcher())
|
||||||
|
subject = BaseURLViewModel(
|
||||||
|
serverInfoRepo = serverInfoRepo,
|
||||||
|
authRepo = authRepo,
|
||||||
|
recipeRepo = recipeRepo,
|
||||||
|
versionDataSource = versionDataSource,
|
||||||
|
logger = logger,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `when saveBaseUrl and getVersionInfo returns result then saves to storage`() = runTest {
|
fun `when saveBaseURL expect no version checks given that current URL matches new`() = runTest {
|
||||||
|
setupSaveBaseUrlWithOldUrl()
|
||||||
|
coVerify(inverse = true) { versionDataSource.getVersionInfo(any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect URL isn't saved given that current URL matches new`() = runTest {
|
||||||
|
setupSaveBaseUrlWithOldUrl()
|
||||||
|
coVerify(inverse = true) { serverInfoRepo.storeBaseURL(any(), any()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect no logout given that current URL matches new`() = runTest {
|
||||||
|
setupSaveBaseUrlWithOldUrl()
|
||||||
|
coVerify(inverse = true) { authRepo.logout() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect data intact given that current URL matches new`() = runTest {
|
||||||
|
setupSaveBaseUrlWithOldUrl()
|
||||||
|
coVerify(inverse = true) { recipeRepo.clearLocalData() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestScope.setupSaveBaseUrlWithOldUrl() {
|
||||||
|
coEvery { serverInfoRepo.getUrl() } returns TEST_BASE_URL
|
||||||
|
versionDataSourceReturnsSuccess()
|
||||||
|
subject.saveBaseUrl(TEST_BASE_URL)
|
||||||
|
advanceUntilIdle()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseUrl expect URL is saved given that new URL doesn't match old`() = runTest {
|
||||||
|
setupSaveBaseUrlWithNewUrl()
|
||||||
|
coVerify { serverInfoRepo.storeBaseURL(eq(TEST_BASE_URL), eq(TEST_VERSION)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect logout given that new URL doesn't match old`() = runTest {
|
||||||
|
setupSaveBaseUrlWithNewUrl()
|
||||||
|
coVerify { authRepo.logout() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect recipes removed given that new URL doesn't match old`() = runTest {
|
||||||
|
setupSaveBaseUrlWithNewUrl()
|
||||||
|
coVerify { recipeRepo.clearLocalData() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TestScope.setupSaveBaseUrlWithNewUrl() {
|
||||||
|
coEvery { serverInfoRepo.getUrl() } returns null
|
||||||
|
versionDataSourceReturnsSuccess()
|
||||||
|
subject.saveBaseUrl(TEST_BASE_URL)
|
||||||
|
advanceUntilIdle()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun versionDataSourceReturnsSuccess() {
|
||||||
coEvery {
|
coEvery {
|
||||||
versionDataSource.getVersionInfo(eq(TEST_BASE_URL))
|
versionDataSource.getVersionInfo(eq(TEST_BASE_URL))
|
||||||
} returns VersionInfo(TEST_VERSION)
|
} returns VersionInfo(TEST_VERSION)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `when saveBaseURL expect error given that version can't be fetched`() = runTest {
|
||||||
|
coEvery { serverInfoRepo.getUrl() } returns null
|
||||||
|
coEvery { versionDataSource.getVersionInfo(eq(TEST_BASE_URL)) } throws IOException()
|
||||||
subject.saveBaseUrl(TEST_BASE_URL)
|
subject.saveBaseUrl(TEST_BASE_URL)
|
||||||
advanceUntilIdle()
|
advanceUntilIdle()
|
||||||
coVerify { serverInfoRepo.storeBaseURL(eq(TEST_BASE_URL), eq(TEST_VERSION)) }
|
assertThat(subject.uiState.value).isInstanceOf(OperationUiState.Failure::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user