Skip to content

Commit

Permalink
removes use of LiveData in EditCategoriesViewModel.kt, adds (flaky) u…
Browse files Browse the repository at this point in the history
…nit tests
  • Loading branch information
cinadia committed Jun 17, 2024
1 parent f8efd1c commit b175bd5
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.willowtree.vocable.settings

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.lifecycle.Observer
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import app.cash.turbine.test
Expand All @@ -20,13 +18,7 @@ import com.willowtree.vocable.room.VocableDatabase
import com.willowtree.vocable.utility.FakeDateProvider
import com.willowtree.vocable.utility.StubLegacyCategoriesAndPhrasesRepository
import com.willowtree.vocable.utility.VocableKoinTestRule
import junit.framework.TestCase
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.advanceUntilIdle
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
Expand All @@ -39,9 +31,6 @@ class EditCategoriesViewModelTest {
@get:Rule
val mainDispatcherRule = MainDispatcherRule()

@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()

private val database = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
VocableDatabase::class.java
Expand Down Expand Up @@ -85,81 +74,54 @@ class EditCategoriesViewModelTest {
)
}

// 1. refreshing categories without adding new category remains at first index
// 2. adding new category and refreshing once flips to new category's index
// 3. adding new category and refreshing twice flips to first index
// 4. adding new category amongst hidden categories and refreshing once flips to new category's index (before hidden categories)

@OptIn(ExperimentalCoroutinesApi::class)
// TODO: CC - the following 4 tests are flaky due to the way refreshCategories() is implemented
@Test
fun refreshing_categories_without_adding_new_category_remains_at_first_index() = runTest(UnconfinedTestDispatcher()) {
fun refreshing_categories_without_adding_new_category_remains_at_first_index() = runTest {
val vm = createViewModel()
vm.refreshCategories()

var index: Int? = null
val observer = Observer<Int> { value ->
index = value
}

try {
vm.lastViewedIndex.observeForever(observer)
advanceUntilIdle()
assertEquals(0, index)
} finally {
vm.lastViewedIndex.removeObserver(observer)
vm.liveLastViewedIndex.test {
assertEquals(0, awaitItem())
}
}

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun adding_new_category_and_refreshing_once_flips_to_new_categorys_index() = runTest(UnconfinedTestDispatcher()) {
fun adding_new_category_and_refreshing_once_flips_to_new_categorys_index() = runTest {

val vm = createViewModel()
vm.refreshCategories()

categoriesUseCase.addCategory("new category")
vm.refreshCategories()

var index: Int? = null
val observer = Observer<Int> { value ->
index = value
}

try {
vm.lastViewedIndex.observeForever(observer)
advanceUntilIdle()
assertEquals(7, index)
} finally {
vm.lastViewedIndex.removeObserver(observer)
vm.liveLastViewedIndex.test {
assertEquals(0, awaitItem())
assertEquals(7, awaitItem())
}
}

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun adding_new_category_and_refreshing_twice_flips_to_first_index() = runTest(UnconfinedTestDispatcher()) {
fun adding_new_category_and_refreshing_twice_flips_to_first_index() = runTest {
val vm = createViewModel()
vm.refreshCategories()

categoriesUseCase.addCategory("new category")
vm.refreshCategories()
vm.refreshCategories()

var index: Int? = null
val observer = Observer<Int> { value ->
index = value
vm.refreshCategories()
vm.liveLastViewedIndex.test {
assertEquals(0, awaitItem())
assertEquals(7, awaitItem())
}

try {
vm.lastViewedIndex.observeForever(observer)
advanceUntilIdle()
assertEquals(0, index)
} finally {
vm.lastViewedIndex.removeObserver(observer)
vm.refreshCategories()
vm.liveLastViewedIndex.test {
assertEquals(7, awaitItem())
assertEquals(0, awaitItem())
}
}

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun adding_new_category_amongst_hidden_categories_and_refreshing_once_flips_to_last_non_hidden_index() = runTest(UnconfinedTestDispatcher()) {
fun adding_new_category_amongst_hidden_categories_and_refreshing_once_flips_to_last_non_hidden_index() = runTest {
val vm = createViewModel()
categoriesUseCase.updateCategoryHidden("preset_general", hidden = true)
categoriesUseCase.updateCategoryHidden("preset_basic_needs", hidden = true)
Expand All @@ -168,22 +130,12 @@ class EditCategoriesViewModelTest {

categoriesUseCase.addCategory("new category")

categoriesUseCase.categories().first()

vm.refreshCategories()

var index: Int? = null
val observer = Observer<Int> { value ->
index = value
vm.liveLastViewedIndex.test {
assertEquals(0, awaitItem())
assertEquals(5, awaitItem())
}

try {
vm.lastViewedIndex.observeForever(observer)
advanceUntilIdle()
assertEquals(5, index)
} finally {
vm.lastViewedIndex.removeObserver(observer)
}
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewModelScope
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.widget.ViewPager2
import com.willowtree.vocable.BaseFragment
Expand All @@ -16,6 +17,7 @@ import com.willowtree.vocable.R
import com.willowtree.vocable.databinding.FragmentEditCategoriesBinding
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.utils.VocableFragmentStateAdapter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import org.koin.androidx.viewmodel.ViewModelOwner
import org.koin.androidx.viewmodel.ext.android.viewModel
Expand Down Expand Up @@ -121,15 +123,12 @@ class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {
}
}

editCategoriesViewModel.lastViewedIndex.observe(viewLifecycleOwner) {
it?.let { index ->
val pageNum = index / maxEditCategories
// Wait until view pager has finished its layout
binding.editCategoriesViewPager.post {
editCategoriesViewModel.viewModelScope.launch {
editCategoriesViewModel.liveLastViewedIndex.collect {
val pageNum = it/maxEditCategories
if (isAdded && binding.editCategoriesViewPager.currentItem != pageNum) {
binding.editCategoriesViewPager.setCurrentItem(pageNum, false)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.willowtree.vocable.settings

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.willowtree.vocable.ICategoriesUseCase
import com.willowtree.vocable.presets.Category
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class EditCategoriesViewModel(
Expand All @@ -15,8 +15,7 @@ class EditCategoriesViewModel(

val categoryList = categoriesUseCase.categories()

private val liveLastViewedIndex = MutableLiveData<Int>()
val lastViewedIndex: LiveData<Int> = liveLastViewedIndex
val liveLastViewedIndex = MutableStateFlow(0)

private var overallCategories = listOf<Category>()

Expand All @@ -31,20 +30,20 @@ class EditCategoriesViewModel(
if (oldCategories.isNotEmpty() && oldCategories.size < overallCategories.size) {
when (val firstHiddenIndex = overallCategories.indexOfFirst { it.hidden }) {
-1 -> {
liveLastViewedIndex.postValue(overallCategories.size - 1)
liveLastViewedIndex.update { overallCategories.size - 1 }
}

0 -> {
liveLastViewedIndex.postValue(0)
liveLastViewedIndex.update { 0 }
}

else -> {
liveLastViewedIndex.postValue(firstHiddenIndex - 1)
liveLastViewedIndex.update { firstHiddenIndex - 1 }
}
}
}
else {
liveLastViewedIndex.postValue(0)
liveLastViewedIndex.update { 0 }
}
}
}
Expand Down

0 comments on commit b175bd5

Please sign in to comment.