mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
Added migration test cases for migrating the objectBox data to libkiwix.
* Fixed: `ImportBookmarkTest` which was failing on CI. * Refactored UI and unit test cases according to the new codebase. * Fixed: Selecting a ZIM file would select all ZIM files displayed on the Local Library screen. * Fixed: `network result & language db results activate a combined network + db result`, `library marks files over 4GB as can't download if file system state says to` and `books found on filesystem are filtered by books already in db`, which sometimes fails on the CI.
This commit is contained in:
parent
42da475867
commit
c2d35e17d4
@ -39,9 +39,11 @@ import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.kiwix.kiwixmobile.core.CoreApp
|
||||
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
||||
import org.kiwix.kiwixmobile.core.data.remote.ObjectBoxToLibkiwixMigrator
|
||||
import org.kiwix.kiwixmobile.core.di.modules.DatabaseModule
|
||||
import org.kiwix.kiwixmobile.core.entity.LibkiwixBook
|
||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
|
||||
@ -51,6 +53,7 @@ import org.kiwix.kiwixmobile.testutils.RetryRule
|
||||
import org.kiwix.kiwixmobile.testutils.TestUtils
|
||||
import org.kiwix.kiwixmobile.utils.KiwixIdlingResource
|
||||
import org.kiwix.libkiwix.Book
|
||||
import org.kiwix.libzim.Archive
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.OutputStream
|
||||
@ -62,7 +65,8 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
// take the existing boxStore object
|
||||
private var boxStore: BoxStore? = null
|
||||
private lateinit var zimFile: File
|
||||
private lateinit var box: Box<BookmarkEntity>
|
||||
private lateinit var bookOnDiskBox: Box<BookOnDiskEntity>
|
||||
private lateinit var bookmarkBox: Box<BookmarkEntity>
|
||||
private val expectedZimName = "Alpine_Linux"
|
||||
private val expectedZimId = "60094d1e-1c9a-a60b-2011-4fb02f8db6c3"
|
||||
private val expectedZimFilePath: String by lazy { zimFile.canonicalPath }
|
||||
@ -82,6 +86,27 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
)
|
||||
}
|
||||
|
||||
private val bookOnDiskEntity: BookOnDiskEntity by lazy {
|
||||
BookOnDiskEntity(
|
||||
id = 0,
|
||||
file = zimFile,
|
||||
zimReaderSource = ZimReaderSource(zimFile),
|
||||
bookId = expectedZimId,
|
||||
title = "",
|
||||
description = "",
|
||||
language = "",
|
||||
creator = "",
|
||||
publisher = "",
|
||||
date = "",
|
||||
url = "",
|
||||
articleCount = "",
|
||||
mediaCount = "",
|
||||
size = "",
|
||||
name = expectedZimName,
|
||||
favIcon = ""
|
||||
)
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var retryRule = RetryRule()
|
||||
@ -128,18 +153,26 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
" check is your application running"
|
||||
)
|
||||
}
|
||||
box = boxStore!!.boxFor(BookmarkEntity::class.java)
|
||||
bookmarkBox = boxStore!!.boxFor(BookmarkEntity::class.java)
|
||||
|
||||
// clear the data before running the test case
|
||||
runBlocking { clearBookmarks() }
|
||||
|
||||
bookOnDiskBox = boxStore!!.boxFor(BookOnDiskEntity::class.java)
|
||||
// clear the data before running the test case
|
||||
runBlocking { clearBookOnDisk() }
|
||||
|
||||
// add a file in fileSystem because we need to actual file path for making object of Archive.
|
||||
zimFile = getZimFile("testzim.zim")
|
||||
}
|
||||
|
||||
private fun getZimFile(zimFileName: String): File {
|
||||
val loadFileStream =
|
||||
ObjectBoxToLibkiwixMigratorTest::class.java.classLoader.getResourceAsStream("testzim.zim")
|
||||
zimFile =
|
||||
ObjectBoxToLibkiwixMigratorTest::class.java.classLoader.getResourceAsStream(zimFileName)
|
||||
val zimFile =
|
||||
File(
|
||||
context.getExternalFilesDirs(null)[0],
|
||||
"testzim.zim"
|
||||
zimFileName
|
||||
)
|
||||
if (zimFile.exists()) zimFile.delete()
|
||||
zimFile.createNewFile()
|
||||
@ -153,15 +186,16 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return zimFile
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSingleDataMigration(): Unit =
|
||||
runBlocking {
|
||||
box.put(bookmarkEntity)
|
||||
// migrate data into room database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
// check if data successfully migrated to room
|
||||
bookmarkBox.put(bookmarkEntity)
|
||||
// migrate data into room libkiwix.
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
// check if data successfully migrated to libkiwix.
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
@ -173,11 +207,89 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
clearBookmarks()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migrateBookOnDisk_ShouldInsertDataInLibkiwix(): Unit =
|
||||
runBlocking {
|
||||
// test with single entity
|
||||
bookOnDiskBox.put(bookOnDiskEntity)
|
||||
// migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateLocalBooks(bookOnDiskBox)
|
||||
// check if data successfully migrated to libkiwix.
|
||||
var actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.getBooks()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
assertEquals(
|
||||
actualDataAfterMigration[0].book.zimReaderSource.toDatabase(),
|
||||
expectedZimFilePath
|
||||
)
|
||||
assertEquals(actualDataAfterMigration[0].book.id, expectedZimId)
|
||||
assertEquals(actualDataAfterMigration[0].book.title, "Test_Zim")
|
||||
// Clear the bookOnDisk list from device to not affect the other test cases.
|
||||
clearBookOnDisk()
|
||||
|
||||
// test with empty data
|
||||
objectBoxToLibkiwixMigrator.migrateLocalBooks(bookOnDiskBox)
|
||||
// check if data successfully migrated to libkiwix.
|
||||
actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.getBooks()
|
||||
assertTrue(actualDataAfterMigration.isEmpty())
|
||||
// Clear the bookOnDisk list from device to not affect the other test cases.
|
||||
clearBookOnDisk()
|
||||
|
||||
// Test if data successfully migrated to libkiwix and existing data is preserved
|
||||
zimFile = getZimFile("testzim.zim")
|
||||
val secondZimFile = getZimFile("small.zim")
|
||||
val archive = Archive(secondZimFile.path)
|
||||
val book = Book().apply {
|
||||
update(archive)
|
||||
}
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.insert(listOf(book))
|
||||
val thirdZim = getZimFile("characters_encoding.zim")
|
||||
val thirdEntity = BookOnDiskEntity(
|
||||
id = 0,
|
||||
file = thirdZim,
|
||||
zimReaderSource = ZimReaderSource(thirdZim),
|
||||
bookId = expectedZimId,
|
||||
title = "",
|
||||
description = "",
|
||||
language = "",
|
||||
creator = "",
|
||||
publisher = "",
|
||||
date = "",
|
||||
url = "",
|
||||
articleCount = "",
|
||||
mediaCount = "",
|
||||
size = "",
|
||||
name = expectedZimName,
|
||||
favIcon = ""
|
||||
)
|
||||
bookOnDiskBox.put(thirdEntity)
|
||||
bookOnDiskBox.put(bookOnDiskEntity)
|
||||
// Migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateLocalBooks(bookOnDiskBox)
|
||||
actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.getBooks()
|
||||
assertEquals(3, actualDataAfterMigration.size)
|
||||
val existingItem =
|
||||
actualDataAfterMigration.find {
|
||||
it.book.zimReaderSource.toDatabase() == secondZimFile.path
|
||||
}
|
||||
assertNotNull(existingItem)
|
||||
val newItem =
|
||||
actualDataAfterMigration.find {
|
||||
it.book.zimReaderSource.toDatabase() == expectedZimFilePath
|
||||
}
|
||||
assertNotNull(newItem)
|
||||
// Clear the bookmarks list from device to not affect the other test cases.
|
||||
clearBookmarks()
|
||||
secondZimFile.delete()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMigrationWithEmptyData(): Unit =
|
||||
runBlocking {
|
||||
// Migrate data from empty ObjectBox database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertTrue(actualDataAfterMigration.isEmpty())
|
||||
@ -209,9 +321,9 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
libkiwixBook
|
||||
)
|
||||
)
|
||||
box.put(bookmarkEntity)
|
||||
// Migrate data into Room database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
bookmarkBox.put(bookmarkEntity)
|
||||
// Migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertEquals(2, actualDataAfterMigration.size)
|
||||
@ -234,7 +346,7 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
runBlocking {
|
||||
// Test large data migration for recent searches
|
||||
for (i in 1..1000) {
|
||||
box.put(
|
||||
bookmarkBox.put(
|
||||
BookmarkEntity(
|
||||
0,
|
||||
expectedZimId,
|
||||
@ -247,9 +359,9 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
)
|
||||
)
|
||||
}
|
||||
// Migrate data into Room database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
// Check if data successfully migrated to Room
|
||||
// Migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
// Check if data successfully migrated to libkiwix
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertEquals(1000, actualDataAfterMigration.size)
|
||||
@ -272,10 +384,10 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedTitle,
|
||||
expectedFavicon
|
||||
)
|
||||
box.put(bookmarkEntity)
|
||||
// migrate data into room database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
// check if data successfully migrated to room
|
||||
bookmarkBox.put(bookmarkEntity)
|
||||
// migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
// check if data successfully migrated to libkiwix
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
@ -303,10 +415,10 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
expectedTitle,
|
||||
expectedFavicon
|
||||
)
|
||||
box.put(bookmarkEntity)
|
||||
// migrate data into room database
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(box)
|
||||
// check if data successfully migrated to room
|
||||
bookmarkBox.put(bookmarkEntity)
|
||||
// migrate data into libkiwix
|
||||
objectBoxToLibkiwixMigrator.migrateBookMarks(bookmarkBox)
|
||||
// check if data successfully migrated to libkiwix
|
||||
val actualDataAfterMigration =
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks().first()
|
||||
assertEquals(1, actualDataAfterMigration.size)
|
||||
@ -318,13 +430,24 @@ class ObjectBoxToLibkiwixMigratorTest : BaseActivityTest() {
|
||||
clearBookmarks()
|
||||
}
|
||||
|
||||
private suspend fun clearBookOnDisk() {
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.delete(
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookOnDisk.getBooks()
|
||||
.map { LibkiwixBook(it.book.nativeBook) }
|
||||
)
|
||||
bookOnDiskBox.removeAll()
|
||||
if (::zimFile.isInitialized) {
|
||||
zimFile.delete() // delete the temp ZIM file to free up the memory
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun clearBookmarks() {
|
||||
// delete bookmarks for testing other edge cases
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.deleteBookmarks(
|
||||
objectBoxToLibkiwixMigrator.libkiwixBookmarks.bookmarks()
|
||||
.first() as List<LibkiwixBookmarkItem>
|
||||
)
|
||||
box.removeAll()
|
||||
bookmarkBox.removeAll()
|
||||
if (::zimFile.isInitialized) {
|
||||
zimFile.delete() // delete the temp ZIM file to free up the memory
|
||||
}
|
||||
|
@ -40,9 +40,8 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.kiwix.kiwixmobile.BaseActivityTest
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
||||
import org.kiwix.kiwixmobile.core.di.modules.DatabaseModule
|
||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem
|
||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||
@ -63,7 +62,7 @@ class ImportBookmarkTest : BaseActivityTest() {
|
||||
private var boxStore: BoxStore? = null
|
||||
private val library = Library()
|
||||
private val manager = Manager(library)
|
||||
private lateinit var newBookDao: NewBookDao
|
||||
private lateinit var libkiwixBookOnDisk: LibkiwixBookOnDisk
|
||||
private lateinit var libkiwixBookmarks: LibkiwixBookmarks
|
||||
|
||||
private val bookmarkXmlData =
|
||||
@ -138,13 +137,14 @@ class ImportBookmarkTest : BaseActivityTest() {
|
||||
}
|
||||
}
|
||||
boxStore = DatabaseModule.boxStore
|
||||
newBookDao = NewBookDao(boxStore!!.boxFor(BookOnDiskEntity::class.java))
|
||||
val sharedPreferenceUtils = SharedPreferenceUtil(context)
|
||||
libkiwixBookOnDisk = LibkiwixBookOnDisk(library, manager, sharedPreferenceUtils)
|
||||
libkiwixBookmarks =
|
||||
LibkiwixBookmarks(
|
||||
library,
|
||||
manager,
|
||||
SharedPreferenceUtil(context),
|
||||
newBookDao,
|
||||
sharedPreferenceUtils,
|
||||
libkiwixBookOnDisk,
|
||||
null
|
||||
)
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import app.cash.turbine.TurbineTestContext
|
||||
import app.cash.turbine.test
|
||||
import com.jraska.livedata.test
|
||||
import io.mockk.clearAllMocks
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
@ -41,9 +42,9 @@ import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
@ -129,8 +130,8 @@ class ZimManageViewModelTest {
|
||||
|
||||
@AfterAll
|
||||
fun teardown() {
|
||||
Dispatchers.resetMain()
|
||||
viewModel.onClearedExposed()
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
@ -236,24 +237,24 @@ class ZimManageViewModelTest {
|
||||
@Test
|
||||
fun `books found on filesystem are filtered by books already in db`() = runTest {
|
||||
every { application.getString(any()) } returns ""
|
||||
val expectedBook = libkiwixBook("1")
|
||||
val bookToRemove = libkiwixBook("2")
|
||||
val expectedBook = bookOnDisk(1L, libkiwixBook("1", nativeBook = BookTestWrapper("1")))
|
||||
val bookToRemove = bookOnDisk(1L, libkiwixBook("2", nativeBook = BookTestWrapper("2")))
|
||||
advanceUntilIdle()
|
||||
viewModel.requestFileSystemCheck.emit(Unit)
|
||||
advanceUntilIdle()
|
||||
// books.emit(listOf(bookToRemove))
|
||||
// advanceUntilIdle()
|
||||
// booksOnFileSystem.emit(
|
||||
// listOf(
|
||||
// expectedBook,
|
||||
// expectedBook,
|
||||
// bookToRemove
|
||||
// )
|
||||
// )
|
||||
// advanceUntilIdle()
|
||||
// coVerify {
|
||||
// libkiwixBookOnDisk.insert(listOf(expectedBook.book))
|
||||
// }
|
||||
books.emit(listOf(bookToRemove))
|
||||
advanceUntilIdle()
|
||||
booksOnFileSystem.emit(
|
||||
listOfNotNull(
|
||||
expectedBook.book.nativeBook,
|
||||
expectedBook.book.nativeBook,
|
||||
bookToRemove.book.nativeBook
|
||||
)
|
||||
)
|
||||
advanceUntilIdle()
|
||||
coVerify(timeout = 500) {
|
||||
libkiwixBookOnDisk.insert(listOfNotNull(expectedBook.book.nativeBook))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,7 +359,7 @@ class ZimManageViewModelTest {
|
||||
language(isActive = true, occurencesOfLanguage = 1)
|
||||
)
|
||||
advanceUntilIdle()
|
||||
verify {
|
||||
verify(timeout = 500) {
|
||||
newLanguagesDao.insert(
|
||||
listOf(
|
||||
dbLanguage.copy(occurencesOfLanguage = 2),
|
||||
@ -384,9 +385,9 @@ class ZimManageViewModelTest {
|
||||
every { application.getString(any(), any()) } returns ""
|
||||
every { defaultLanguageProvider.provide() } returns defaultLanguage
|
||||
viewModel.networkLibrary.emit(networkBooks)
|
||||
runCurrent()
|
||||
advanceUntilIdle()
|
||||
languages.value = dbBooks
|
||||
runCurrent()
|
||||
advanceUntilIdle()
|
||||
networkStates.value = CONNECTED
|
||||
advanceUntilIdle()
|
||||
}
|
||||
@ -475,13 +476,21 @@ class ZimManageViewModelTest {
|
||||
viewModel.networkLibrary.emit(listOf(bookOver4Gb))
|
||||
},
|
||||
assert = {
|
||||
skipItems(1)
|
||||
assertThat(awaitItem()).isEqualTo(
|
||||
listOf(
|
||||
LibraryListItem.DividerItem(Long.MIN_VALUE, R.string.other_languages),
|
||||
LibraryListItem.BookItem(bookOver4Gb, CannotWrite4GbFile)
|
||||
)
|
||||
)
|
||||
withTimeout(5000) {
|
||||
while (true) {
|
||||
val item = awaitItem()
|
||||
val bookItem = item.filterIsInstance<LibraryListItem.BookItem>().firstOrNull()
|
||||
if (bookItem?.fileSystemState == CannotWrite4GbFile) {
|
||||
assertThat(item).isEqualTo(
|
||||
listOf(
|
||||
LibraryListItem.DividerItem(Long.MIN_VALUE, R.string.other_languages),
|
||||
LibraryListItem.BookItem(bookOver4Gb, CannotWrite4GbFile)
|
||||
)
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -610,3 +619,9 @@ suspend fun <T> TestScope.testFlow(
|
||||
}
|
||||
job.join()
|
||||
}
|
||||
|
||||
class BookTestWrapper(private val id: String) : Book(0L) {
|
||||
override fun getId(): String = id
|
||||
override fun equals(other: Any?): Boolean = other is BookTestWrapper && getId() == other.getId()
|
||||
override fun hashCode(): Int = getId().hashCode()
|
||||
}
|
||||
|
@ -39,7 +39,8 @@ class StorageObserver @Inject constructor(
|
||||
private val downloadRoomDao: DownloadRoomDao,
|
||||
private val fileSearch: FileSearch,
|
||||
private val zimReaderFactory: ZimFileReader.Factory,
|
||||
private val libkiwixBookmarks: LibkiwixBookmarks
|
||||
private val libkiwixBookmarks: LibkiwixBookmarks,
|
||||
private val libkiwixBookFactory: LibkiwixBookFactory
|
||||
) {
|
||||
fun getBooksOnFileSystem(
|
||||
scanningProgressListener: ScanningProgressListener,
|
||||
@ -64,7 +65,7 @@ class StorageObserver @Inject constructor(
|
||||
private suspend fun convertToLibkiwixBook(file: File) =
|
||||
zimReaderFactory.create(ZimReaderSource(file))
|
||||
?.let { zimFileReader ->
|
||||
Book().apply {
|
||||
libkiwixBookFactory.create().apply {
|
||||
update(zimFileReader.jniKiwixReader)
|
||||
}.also {
|
||||
// add the book to libkiwix library to validate the imported bookmarks
|
||||
@ -73,3 +74,7 @@ class StorageObserver @Inject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface LibkiwixBookFactory {
|
||||
fun create(): Book
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ class LibkiwixBookOnDisk @Inject constructor(
|
||||
private suspend fun isInTrashFolder(filePath: String) =
|
||||
Regex("/\\.Trash/").containsMatchIn(filePath)
|
||||
|
||||
private suspend fun delete(books: List<LibkiwixBook>) {
|
||||
suspend fun delete(books: List<LibkiwixBook>) {
|
||||
runCatching {
|
||||
books.forEach {
|
||||
library.removeBookById(it.id)
|
||||
|
@ -25,12 +25,13 @@ import dagger.BindsInstance
|
||||
import dagger.Component
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import org.kiwix.kiwixmobile.core.CoreApp
|
||||
import org.kiwix.kiwixmobile.core.LibkiwixBookFactory
|
||||
import org.kiwix.kiwixmobile.core.StorageObserver
|
||||
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||
import org.kiwix.kiwixmobile.core.dao.HistoryDao
|
||||
import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
|
||||
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
||||
@ -85,6 +86,7 @@ interface CoreComponent {
|
||||
fun zimReaderContainer(): ZimReaderContainer
|
||||
fun sharedPrefUtil(): SharedPreferenceUtil
|
||||
fun zimFileReaderFactory(): ZimFileReader.Factory
|
||||
fun libkiwixBookFactory(): LibkiwixBookFactory
|
||||
fun storageObserver(): StorageObserver
|
||||
fun kiwixService(): KiwixService
|
||||
fun application(): Application
|
||||
|
@ -20,10 +20,12 @@ package org.kiwix.kiwixmobile.core.di.modules
|
||||
import android.content.Context
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import org.kiwix.kiwixmobile.core.LibkiwixBookFactory
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.libkiwix.Book
|
||||
import org.kiwix.libkiwix.JNIKiwix
|
||||
import org.kiwix.libkiwix.Library
|
||||
import org.kiwix.libkiwix.Manager
|
||||
@ -83,6 +85,14 @@ class JNIModule {
|
||||
@Named(LOCAL_BOOKS_MANAGER) manager: Manager,
|
||||
sharedPreferenceUtil: SharedPreferenceUtil,
|
||||
): LibkiwixBookOnDisk = LibkiwixBookOnDisk(library, manager, sharedPreferenceUtil)
|
||||
|
||||
/**
|
||||
* We are not making this singleton because we need multiple objects of this.
|
||||
*/
|
||||
@Provides
|
||||
fun provideBookFactory(): LibkiwixBookFactory = object : LibkiwixBookFactory {
|
||||
override fun create(): Book = Book()
|
||||
}
|
||||
}
|
||||
|
||||
const val BOOKMARK_LIBRARY = "bookmarkLibrary"
|
||||
|
@ -29,7 +29,7 @@ import java.io.File
|
||||
*/
|
||||
@Suppress("ConstructorParameterNaming")
|
||||
data class LibkiwixBook(
|
||||
val nativeBook: Book? = null,
|
||||
var nativeBook: Book? = null,
|
||||
private var _id: String = "",
|
||||
private var _title: String = "",
|
||||
private var _description: String? = null,
|
||||
|
@ -35,6 +35,7 @@ import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity.Url
|
||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.libkiwix.Book
|
||||
import java.io.File
|
||||
|
||||
fun bookOnDisk(
|
||||
@ -146,8 +147,11 @@ fun libkiwixBook(
|
||||
size: String = "1024",
|
||||
name: String = "name",
|
||||
favIcon: String = "favIcon",
|
||||
file: File = File("")
|
||||
file: File = File(""),
|
||||
nativeBook: Book? = null,
|
||||
tags: String? = ""
|
||||
) = LibkiwixBook().apply {
|
||||
this.nativeBook = nativeBook
|
||||
this.id = id
|
||||
this.title = title
|
||||
this.description = description
|
||||
@ -162,6 +166,7 @@ fun libkiwixBook(
|
||||
this.file = file
|
||||
bookName = name
|
||||
favicon = favIcon
|
||||
this.tags = tags
|
||||
}
|
||||
|
||||
fun recentSearchEntity(
|
||||
|
@ -19,6 +19,8 @@
|
||||
package org.kiwix.kiwixmobile.core
|
||||
|
||||
import io.mockk.clearAllMocks
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
@ -39,9 +41,9 @@ import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||
import org.kiwix.kiwixmobile.core.utils.files.FileSearch
|
||||
import org.kiwix.kiwixmobile.core.utils.files.ScanningProgressListener
|
||||
import org.kiwix.kiwixmobile.core.utils.files.testFlow
|
||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.BooksOnDiskListItem.BookOnDisk
|
||||
import org.kiwix.libkiwix.Book
|
||||
import org.kiwix.libzim.Archive
|
||||
import org.kiwix.sharedFunctions.libkiwixBook
|
||||
import org.kiwix.sharedFunctions.bookOnDisk
|
||||
import java.io.File
|
||||
|
||||
class StorageObserverTest {
|
||||
@ -58,6 +60,8 @@ class StorageObserverTest {
|
||||
|
||||
private val files = MutableStateFlow<List<File>>(emptyList())
|
||||
private val downloads = MutableStateFlow<List<DownloadModel>>(emptyList())
|
||||
private val libkiwixBookFactory: LibkiwixBookFactory = mockk()
|
||||
private val libkiwixBook: Book = BookTestWrapper("id")
|
||||
|
||||
private lateinit var storageObserver: StorageObserver
|
||||
|
||||
@ -66,9 +70,17 @@ class StorageObserverTest {
|
||||
every { sharedPreferenceUtil.prefStorage } returns "a"
|
||||
every { fileSearch.scan(scanningProgressListener) } returns files
|
||||
every { downloadRoomDao.downloads() } returns downloads
|
||||
coEvery { libkiwixBookmarks.addBookToLibrary(any()) } returns Unit
|
||||
every { zimFileReader.jniKiwixReader } returns mockk()
|
||||
every { runBlocking { readerFactory.create(zimReaderSource) } } returns zimFileReader
|
||||
storageObserver = StorageObserver(downloadRoomDao, fileSearch, readerFactory, libkiwixBookmarks)
|
||||
every { libkiwixBookFactory.create() } returns libkiwixBook
|
||||
storageObserver = StorageObserver(
|
||||
downloadRoomDao,
|
||||
fileSearch,
|
||||
readerFactory,
|
||||
libkiwixBookmarks,
|
||||
libkiwixBookFactory
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,7 +89,7 @@ class StorageObserverTest {
|
||||
testFlow(
|
||||
flow = booksOnFileSystem(),
|
||||
triggerAction = {},
|
||||
assert = { assertThat(awaitItem()).isEqualTo(listOf<BookOnDisk>()) }
|
||||
assert = { assertThat(awaitItem()).isEqualTo(listOf<Book>()) }
|
||||
)
|
||||
}
|
||||
|
||||
@ -87,7 +99,7 @@ class StorageObserverTest {
|
||||
val expectedBook =
|
||||
libkiwixBook(
|
||||
"id", "title", "1", "favicon", "creator", "publisher", "date",
|
||||
"description", "language"
|
||||
"description", "language", nativeBook = libkiwixBook
|
||||
)
|
||||
withNoFiltering()
|
||||
every { zimFileReader.toBook() } returns expectedBook
|
||||
@ -97,15 +109,14 @@ class StorageObserverTest {
|
||||
triggerAction = {},
|
||||
assert = {
|
||||
assertThat(awaitItem()).isEqualTo(
|
||||
listOf<BookOnDisk>(
|
||||
bookOnDisk(
|
||||
book = expectedBook,
|
||||
zimReaderSource = zimReaderSource
|
||||
)
|
||||
listOfNotNull<Book>(
|
||||
expectedBook.nativeBook
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
// test the book is added to bookmark's library.
|
||||
coVerify { libkiwixBookmarks.addBookToLibrary(archive = any()) }
|
||||
verify { zimFileReader.dispose() }
|
||||
}
|
||||
|
||||
@ -128,3 +139,12 @@ class StorageObserverTest {
|
||||
every { zimReaderSource.file } returns file
|
||||
}
|
||||
}
|
||||
|
||||
class BookTestWrapper(private val id: String) : Book(0L) {
|
||||
override fun getId(): String = id
|
||||
override fun equals(other: Any?): Boolean = other is BookTestWrapper && getId() == other.getId()
|
||||
override fun hashCode(): Int = getId().hashCode()
|
||||
override fun update(archive: Archive?) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
|
||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookOnDisk
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions
|
||||
|
||||
@ -44,7 +44,7 @@ import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions
|
||||
class DonationDialogHandlerTest {
|
||||
private lateinit var activity: Activity
|
||||
private lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
||||
private lateinit var newBookDao: NewBookDao
|
||||
private lateinit var libkiwixBookOnDisk: LibkiwixBookOnDisk
|
||||
private lateinit var donationDialogHandler: DonationDialogHandler
|
||||
private lateinit var showDonationDialogCallback: DonationDialogHandler.ShowDonationDialogCallback
|
||||
private lateinit var packageManager: PackageManager
|
||||
@ -56,10 +56,10 @@ class DonationDialogHandlerTest {
|
||||
every { activity.packageManager } returns packageManager
|
||||
every { activity.packageName } returns "org.kiwix.kiwixmobile"
|
||||
sharedPreferenceUtil = mockk(relaxed = true)
|
||||
newBookDao = mockk(relaxed = true)
|
||||
libkiwixBookOnDisk = mockk(relaxed = true)
|
||||
showDonationDialogCallback = mockk(relaxed = true)
|
||||
donationDialogHandler =
|
||||
DonationDialogHandler(activity, sharedPreferenceUtil, newBookDao)
|
||||
DonationDialogHandler(activity, sharedPreferenceUtil, libkiwixBookOnDisk)
|
||||
donationDialogHandler.setDonationDialogCallBack(showDonationDialogCallback)
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ class DonationDialogHandlerTest {
|
||||
donationDialogHandler = spyk(donationDialogHandler)
|
||||
every { sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds } returns 0L
|
||||
every { sharedPreferenceUtil.laterClickedMilliSeconds } returns 0L
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
every {
|
||||
donationDialogHandler.shouldShowInitialPopup(any())
|
||||
} returns true
|
||||
@ -81,7 +81,7 @@ class DonationDialogHandlerTest {
|
||||
fun `should not show donation popup if app is not three month old`() =
|
||||
runTest {
|
||||
every { sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds } returns 0L
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
val currentMillis = System.currentTimeMillis()
|
||||
val installTime = currentMillis - 1000
|
||||
val packageInfo =
|
||||
@ -99,7 +99,7 @@ class DonationDialogHandlerTest {
|
||||
fun `should not show donation popup when no ZIM files available in library`() =
|
||||
runTest {
|
||||
every { sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds } returns 0L
|
||||
coEvery { newBookDao.getBooks() } returns emptyList()
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns emptyList()
|
||||
val currentMillis = System.currentTimeMillis()
|
||||
val threeMonthsAgo = currentMillis - THREE_MONTHS_IN_MILLISECONDS
|
||||
val packageInfo =
|
||||
@ -119,7 +119,7 @@ class DonationDialogHandlerTest {
|
||||
every {
|
||||
sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds
|
||||
} returns currentMilliSeconds - (THREE_MONTHS_IN_MILLISECONDS / 2)
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
donationDialogHandler.attemptToShowDonationPopup()
|
||||
verify(exactly = 0) { showDonationDialogCallback.showDonationDialog() }
|
||||
}
|
||||
@ -131,7 +131,7 @@ class DonationDialogHandlerTest {
|
||||
every {
|
||||
sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds
|
||||
} returns currentMilliSeconds - (THREE_MONTHS_IN_MILLISECONDS + 1000)
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
donationDialogHandler.attemptToShowDonationPopup()
|
||||
verify { showDonationDialogCallback.showDonationDialog() }
|
||||
}
|
||||
@ -145,7 +145,7 @@ class DonationDialogHandlerTest {
|
||||
sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds
|
||||
} returns 0L
|
||||
every { donationDialogHandler.shouldShowInitialPopup(any()) } returns true
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
every {
|
||||
sharedPreferenceUtil.laterClickedMilliSeconds
|
||||
} returns currentMilliSeconds - (THREE_MONTHS_IN_MILLISECONDS + 1000)
|
||||
@ -162,7 +162,7 @@ class DonationDialogHandlerTest {
|
||||
sharedPreferenceUtil.lastDonationPopupShownInMilliSeconds
|
||||
} returns 0L
|
||||
every { donationDialogHandler.shouldShowInitialPopup(any()) } returns true
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
every {
|
||||
sharedPreferenceUtil.laterClickedMilliSeconds
|
||||
} returns currentMilliSeconds - 10000L
|
||||
@ -243,7 +243,7 @@ class DonationDialogHandlerTest {
|
||||
with(mockk<ActivityExtensions>()) {
|
||||
every { activity.packageName } returns "org.kiwix.kiwixmobile"
|
||||
every { activity.isCustomApp() } returns false
|
||||
coEvery { newBookDao.getBooks() } returns emptyList()
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns emptyList()
|
||||
val result = donationDialogHandler.isZimFilesAvailableInLibrary()
|
||||
assertFalse(result)
|
||||
}
|
||||
@ -255,7 +255,7 @@ class DonationDialogHandlerTest {
|
||||
with(mockk<ActivityExtensions>()) {
|
||||
every { activity.packageName } returns "org.kiwix.kiwixmobile"
|
||||
every { activity.isCustomApp() } returns false
|
||||
coEvery { newBookDao.getBooks() } returns listOf(mockk())
|
||||
coEvery { libkiwixBookOnDisk.getBooks() } returns listOf(mockk())
|
||||
val result = donationDialogHandler.isZimFilesAvailableInLibrary()
|
||||
assertTrue(result)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user