Refactord tests

This commit is contained in:
MohitMaliFtechiz 2023-06-29 18:09:13 +05:30
parent 18580f53f1
commit 2c045b8cfe
19 changed files with 106 additions and 81 deletions

View File

@ -24,6 +24,7 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.mockk
import io.objectbox.Box
import kotlinx.coroutines.flow.subscribe
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
@ -57,7 +58,7 @@ class NoteRoomDaoTest {
noteRoomDao = db.noteRoomDao()
noteRoomDao.deletePages(pagesToDelete)
noteRoomDao.deleteNotes(notesItemList)
noteRoomDao.pages().collect {
noteRoomDao.pages().subscribe {
Assertions.assertEquals(0, it.size)
}
}
@ -75,7 +76,7 @@ class NoteRoomDaoTest {
notesItem.title = noteTitle
noteRoomDao.saveNote(NotesRoomEntity(notesItem))
noteRoomDao.deleteNote(noteTitle)
noteRoomDao.notesAsEntity().collect {
noteRoomDao.notesAsEntity().subscribe {
Assertions.assertEquals(0, it.size)
}
}
@ -93,7 +94,7 @@ class NoteRoomDaoTest {
val noteTitle = "abNotesTitle"
notesItem.title = noteTitle
noteRoomDao.saveNote(NotesRoomEntity(notesItem))
noteRoomDao.notesAsEntity().collect {
noteRoomDao.notesAsEntity().subscribe {
Assertions.assertEquals(1, it.size)
Assertions.assertEquals(noteTitle, it.first().noteTitle)
}
@ -117,7 +118,7 @@ class NoteRoomDaoTest {
noteRoomDao.saveNote(NotesRoomEntity(notesItem3))
noteRoomDao.saveNote(NotesRoomEntity(notesItem4))
noteRoomDao.saveNote(NotesRoomEntity(notesItem5))
noteRoomDao.notesAsEntity().collect {
noteRoomDao.notesAsEntity().subscribe {
Assertions.assertEquals(5, it.size)
}
}
@ -134,7 +135,7 @@ class NoteRoomDaoTest {
newNotesDao.saveNote(newNote)
notesBox.put(NotesEntity(newNote))
noteRoomDao.migrationToRoomInsert(notesBox)
noteRoomDao.pages().collect {
noteRoomDao.pages().subscribe {
Assertions.assertEquals(1, it.size)
}
}
@ -156,7 +157,7 @@ class NoteRoomDaoTest {
notesBox.put(NotesEntity(newNote))
notesBox.put(NotesEntity(newNote))
noteRoomDao.migrationToRoomInsert(notesBox)
noteRoomDao.pages().collect {
noteRoomDao.pages().subscribe {
Assertions.assertEquals(6, it.size)
}
}

View File

@ -347,4 +347,5 @@ object Libs {
const val roomKtx = "androidx.room:room-ktx:" + Versions.roomVersion
const val roomCompiler = "androidx.room:room-compiler:" + Versions.roomVersion
const val roomRxjava2 = "androidx.room:room-rxjava2:" + Versions.roomVersion
}

View File

@ -209,6 +209,7 @@ class AllProjectConfigurer {
implementation(Libs.rxjava)
implementation(Libs.preference_ktx)
implementation(Libs.roomKtx)
implementation(Libs.roomRxjava2)
kapt(Libs.roomCompiler)
}
}

View File

@ -23,10 +23,9 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import io.objectbox.Box
import io.reactivex.Flowable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.dao.entities.NotesEntity
import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity
@ -34,12 +33,12 @@ import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
@Dao
abstract class NotesRoomDao : PageRoomDao {
abstract class NotesRoomDao : PageDao {
@Query("SELECT * FROM NotesRoomEntity ORDER BY NotesRoomEntity.noteTitle")
abstract fun notesAsEntity(): Flow<List<NotesRoomEntity>>
abstract fun notesAsEntity(): Flowable<List<NotesRoomEntity>>
fun notes(): Flow<List<Page>> = notesAsEntity().map { it.map(::NoteListItem) }
override fun pages(): Flow<List<Page>> = notes()
fun notes(): Flowable<List<Page>> = notesAsEntity().map { it.map(::NoteListItem) }
override fun pages(): Flowable<List<Page>> = notes()
override fun deletePages(pagesToDelete: List<Page>) =
deleteNotes(pagesToDelete as List<NoteListItem>)

View File

@ -19,18 +19,18 @@
package org.kiwix.kiwixmobile.core.dao
import io.reactivex.Flowable
import kotlinx.coroutines.flow.Flow
import org.kiwix.kiwixmobile.core.page.adapter.Page
interface PageDao : BasePageDao {
override fun pages(): Flowable<List<Page>>
}
interface PageRoomDao : BasePageDao {
override fun pages(): Flow<List<Page>>
}
interface BasePageDao {
fun pages(): Any
interface PageDao {
fun pages(): Flowable<List<Page>>
fun deletePages(pagesToDelete: List<Page>)
}
// interface PageRoomDao : BasePageDao {
// override fun pages(): Flow<List<Page>>
// }
//
// interface BasePageDao {
// fun pages(): Any
// fun deletePages(pagesToDelete: List<Page>)
// }

View File

@ -22,6 +22,7 @@ import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
@Deprecated("Replaced with the Room")
@Entity
data class NotesEntity(
@Id var id: Long = 0L,

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel
import androidx.lifecycle.viewModelScope
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects.ShowDeleteBookmarksDialog
@ -61,7 +62,7 @@ class BookmarkViewModel @Inject constructor(
state.copy(pageItems = state.pageItems.map { it.copy(isSelected = false) })
override fun createDeletePageDialogEffect(state: BookmarkState) =
ShowDeleteBookmarksDialog(effects, state, basePageDao)
ShowDeleteBookmarksDialog(effects, state, pageDao, viewModelScope)
override fun copyWithNewItems(state: BookmarkState, newItems: List<BookmarkItem>): BookmarkState =
state.copy(pageItems = newItems)

View File

@ -21,8 +21,10 @@ package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.effects
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.CoroutineScope
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
import org.kiwix.kiwixmobile.core.page.viewmodel.PageState
@ -35,14 +37,17 @@ import javax.inject.Inject
data class ShowDeleteBookmarksDialog(
private val effects: PublishProcessor<SideEffect<*>>,
private val state: PageState<BookmarkItem>,
private val pageDao: BasePageDao
private val pageDao: PageDao,
private val coroutineScope: CoroutineScope
) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) {
activity.cachedComponent.inject(this)
dialogShower.show(
if (state.isInSelectionState) DeleteSelectedBookmarks else DeleteAllBookmarks,
{ effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope)) }
{
effects.offer(DeletePageItems(state, pageDao))
}
)
}
}

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.page.history.viewmodel
import androidx.lifecycle.viewModelScope
import org.kiwix.kiwixmobile.core.dao.HistoryDao
import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.core.page.history.viewmodel.effects.ShowDeleteHistoryDialog
@ -58,7 +59,7 @@ class HistoryViewModel @Inject constructor(
}
override fun createDeletePageDialogEffect(state: HistoryState) =
ShowDeleteHistoryDialog(effects, state, basePageDao)
ShowDeleteHistoryDialog(effects, state, pageDao, viewModelScope)
override fun deselectAllPages(state: HistoryState): HistoryState =
state.copy(pageItems = state.pageItems.map { it.copy(isSelected = false) })

View File

@ -19,10 +19,9 @@ package org.kiwix.kiwixmobile.core.page.history.viewmodel.effects
*/
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.CoroutineScope
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryState
@ -35,13 +34,14 @@ import javax.inject.Inject
data class ShowDeleteHistoryDialog(
private val effects: PublishProcessor<SideEffect<*>>,
private val state: HistoryState,
private val pageDao: BasePageDao
private val pageDao: PageDao,
private val coroutineScope: CoroutineScope
) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) {
activity.cachedComponent.inject(this)
dialogShower.show(if (state.isInSelectionState) DeleteSelectedHistory else DeleteAllHistory, {
effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope))
effects.offer(DeletePageItems(state, pageDao))
})
}
}

View File

@ -18,7 +18,7 @@
package org.kiwix.kiwixmobile.core.page.notes.viewmodel
import org.kiwix.kiwixmobile.core.dao.NewNoteDao
import androidx.lifecycle.viewModelScope
import org.kiwix.kiwixmobile.core.dao.NotesRoomDao
import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem
@ -67,7 +67,7 @@ class NotesViewModel @Inject constructor(
state.copy(pageItems = state.pageItems.map { it.copy(isSelected = false) })
override fun createDeletePageDialogEffect(state: NotesState) =
ShowDeleteNotesDialog(effects, state, basePageDao)
ShowDeleteNotesDialog(effects, state, pageDao, viewModelScope)
override fun onItemClick(page: Page) =
ShowOpenNoteDialog(effects, page, zimReaderContainer)

View File

@ -22,8 +22,12 @@ import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.cachedComponent
import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesState
import org.kiwix.kiwixmobile.core.page.viewmodel.effects.DeletePageItems
@ -35,7 +39,8 @@ import javax.inject.Inject
data class ShowDeleteNotesDialog(
private val effects: PublishProcessor<SideEffect<*>>,
private val state: NotesState,
private val pageDao: BasePageDao
private val pageDao: PageDao,
private val coroutineScope: CoroutineScope
) : SideEffect<Unit> {
@Inject lateinit var dialogShower: DialogShower
override fun invokeWith(activity: AppCompatActivity) {
@ -44,7 +49,9 @@ data class ShowDeleteNotesDialog(
dialogShower.show(
if (state.isInSelectionState) DeleteSelectedNotes else DeleteAllNotes,
{
effects.offer(DeletePageItems(state, pageDao, activity.lifecycleScope))
coroutineScope.launch(Dispatchers.IO) {
effects.offer(DeletePageItems(state, pageDao))
}
}
)
}

View File

@ -20,16 +20,12 @@ package org.kiwix.kiwixmobile.core.page.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.processors.PublishProcessor
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.dao.PageRoomDao
import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.viewmodel.Action.Exit
import org.kiwix.kiwixmobile.core.page.viewmodel.Action.ExitActionModeMenu
@ -46,7 +42,7 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.effects.PopFragmentBackstack
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
abstract class PageViewModel<T : Page, S : PageState<T>>(
protected val basePageDao: BasePageDao,
protected val pageDao: PageDao,
val sharedPreferenceUtil: SharedPreferenceUtil,
val zimReaderContainer: ZimReaderContainer
) : ViewModel() {
@ -74,23 +70,11 @@ abstract class PageViewModel<T : Page, S : PageState<T>>(
.subscribe(state::postValue, Throwable::printStackTrace)
protected fun addDisposablesToCompositeDisposable() {
when (basePageDao) {
is PageDao -> {
compositeDisposable.addAll(
viewStateReducer(),
basePageDao.pages().subscribeOn(Schedulers.io())
.subscribe({ actions.offer(UpdatePages(it)) }, Throwable::printStackTrace)
)
}
is PageRoomDao -> {
compositeDisposable.add(viewStateReducer())
viewModelScope.launch {
basePageDao.pages().collect {
actions.offer(UpdatePages(it))
}
}
}
}
compositeDisposable.addAll(
viewStateReducer(),
pageDao.pages().subscribeOn(Schedulers.io())
.subscribe({ actions.offer(UpdatePages(it)) }, Throwable::printStackTrace)
)
}
private fun reduce(action: Action, state: S): S = when (action) {

View File

@ -19,30 +19,20 @@
package org.kiwix.kiwixmobile.core.page.viewmodel.effects
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.BasePageDao
import org.kiwix.kiwixmobile.core.dao.PageDao
import org.kiwix.kiwixmobile.core.page.adapter.Page
import org.kiwix.kiwixmobile.core.page.viewmodel.PageState
data class DeletePageItems(
private val state: PageState<*>,
private val pageDao: BasePageDao,
private val coroutineScope: CoroutineScope
private val pageDao: PageDao
) : SideEffect<Unit> {
override fun invokeWith(activity: AppCompatActivity) {
if (state.isInSelectionState) {
pageDao.deletePages(state.pageItems.filter(Page::isSelected))
} else {
coroutineScope.launch(Dispatchers.IO) {
if (state.isInSelectionState) {
pageDao.deletePages(state.pageItems.filter(Page::isSelected))
} else {
pageDao.deletePages(state.pageItems)
}
}
pageDao.deletePages(state.pageItems)
}
}
}

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.page.bookmark.viewmodel
import androidx.lifecycle.viewModelScope
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
@ -132,7 +133,12 @@ internal class BookmarkViewModelTest {
assertThat(
viewModel.createDeletePageDialogEffect(bookmarkState())
).isEqualTo(
ShowDeleteBookmarksDialog(viewModel.effects, bookmarkState(), bookmarksDao)
ShowDeleteBookmarksDialog(
viewModel.effects,
bookmarkState(),
bookmarksDao,
viewModel.viewModelScope
)
)
}

View File

@ -23,6 +23,7 @@ import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.CoroutineScope
import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
@ -39,17 +40,25 @@ internal class ShowDeleteBookmarksDialogTest {
private val newBookmarksDao = mockk<NewBookmarksDao>()
val activity = mockk<CoreMainActivity>()
private val dialogShower = mockk<DialogShower>(relaxed = true)
private val coroutineScope: CoroutineScope = mockk(relaxed = true)
@Test
fun `invoke with shows dialog that offers ConfirmDelete action`() {
val showDeleteBookmarksDialog =
ShowDeleteBookmarksDialog(effects, bookmarkState(), newBookmarksDao)
ShowDeleteBookmarksDialog(effects, bookmarkState(), newBookmarksDao, coroutineScope)
mockkActivityInjection(showDeleteBookmarksDialog)
val lambdaSlot = slot<() -> Unit>()
showDeleteBookmarksDialog.invokeWith(activity)
verify { dialogShower.show(any(), capture(lambdaSlot)) }
lambdaSlot.captured.invoke()
verify { effects.offer(DeletePageItems(bookmarkState(), newBookmarksDao)) }
verify {
effects.offer(
DeletePageItems(
bookmarkState(),
newBookmarksDao
)
)
}
}
private fun mockkActivityInjection(showDeleteBookmarksDialog: ShowDeleteBookmarksDialog) {
@ -65,7 +74,8 @@ internal class ShowDeleteBookmarksDialogTest {
ShowDeleteBookmarksDialog(
effects,
bookmarkState(listOf(bookmark(isSelected = true))),
newBookmarksDao
newBookmarksDao,
coroutineScope
)
mockkActivityInjection(showDeleteBookmarksDialog)
showDeleteBookmarksDialog.invokeWith(activity)
@ -78,7 +88,8 @@ internal class ShowDeleteBookmarksDialogTest {
ShowDeleteBookmarksDialog(
effects,
bookmarkState(listOf(bookmark())),
newBookmarksDao
newBookmarksDao,
coroutineScope
)
mockkActivityInjection(showDeleteBookmarksDialog)
showDeleteBookmarksDialog.invokeWith(activity)

View File

@ -1,5 +1,6 @@
package org.kiwix.kiwixmobile.core.page.history.viewmodel
import androidx.lifecycle.viewModelScope
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.mockk
@ -101,7 +102,12 @@ internal class HistoryViewModelTest {
@Test
fun `createDeletePageDialogEffect returns ShowDeleteHistoryDialog`() {
assertThat(viewModel.createDeletePageDialogEffect(historyState())).isEqualTo(
ShowDeleteHistoryDialog(viewModel.effects, historyState(), historyDao)
ShowDeleteHistoryDialog(
viewModel.effects,
historyState(),
historyDao,
viewModel.viewModelScope
)
)
}

View File

@ -5,6 +5,7 @@ import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import io.reactivex.processors.PublishProcessor
import kotlinx.coroutines.CoroutineScope
import org.junit.jupiter.api.Test
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.dao.HistoryDao
@ -21,6 +22,7 @@ internal class ShowDeleteHistoryDialogTest {
private val historyDao = mockk<HistoryDao>()
val activity = mockk<CoreMainActivity>()
private val dialogShower = mockk<DialogShower>(relaxed = true)
private val coroutineScope: CoroutineScope = mockk(relaxed = true)
@Test
fun `invoke with shows dialog that offers ConfirmDelete action`() {
@ -28,7 +30,8 @@ internal class ShowDeleteHistoryDialogTest {
ShowDeleteHistoryDialog(
effects,
historyState(),
historyDao
historyDao,
coroutineScope
)
mockkActivityInjection(showDeleteHistoryDialog)
val lambdaSlot = slot<() -> Unit>()
@ -44,7 +47,8 @@ internal class ShowDeleteHistoryDialogTest {
ShowDeleteHistoryDialog(
effects,
historyState(listOf(historyItem(isSelected = true))),
historyDao
historyDao,
coroutineScope
)
mockkActivityInjection(showDeleteHistoryDialog)
showDeleteHistoryDialog.invokeWith(activity)
@ -57,7 +61,8 @@ internal class ShowDeleteHistoryDialogTest {
ShowDeleteHistoryDialog(
effects,
historyState(),
historyDao
historyDao,
coroutineScope
)
mockkActivityInjection(showDeleteHistoryDialog)
showDeleteHistoryDialog.invokeWith(activity)

View File

@ -35,14 +35,20 @@ internal class DeletePageItemsTest {
@Test
fun `delete with selected items only deletes the selected items`() {
item1.isSelected = true
DeletePageItems(historyState(listOf(item1, item2)), pageDao).invokeWith(activity)
DeletePageItems(
historyState(listOf(item1, item2)),
pageDao
).invokeWith(activity)
verify { pageDao.deletePages(listOf(item1)) }
}
@Test
fun `delete with no selected items deletes all items`() {
item1.isSelected = false
DeletePageItems(historyState(listOf(item1, item2)), pageDao).invokeWith(activity)
DeletePageItems(
historyState(listOf(item1, item2)),
pageDao
).invokeWith(activity)
verify { pageDao.deletePages(listOf(item1, item2)) }
}
}