diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt index aa388a2c8..8efe31d7a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/NewBookDao.kt @@ -56,10 +56,7 @@ class NewBookDao @Inject constructor(private val box: Box) { } private fun removeEntriesWithMatchingIds(newBooks: List) { - box - .query { - inValues(BookOnDiskEntity_.bookId, newBooks.map { it.book.id }.toTypedArray()) - } + box.query { inValues(BookOnDiskEntity_.bookId, newBooks.map { it.book.id }.toTypedArray()) } .remove() } diff --git a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt index 94691d5fe..d7935c885 100644 --- a/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt +++ b/core/src/sharedTestFunctions/java/org/kiwix/sharedFunctions/TestModelFunctions.kt @@ -20,6 +20,8 @@ package org.kiwix.sharedFunctions import com.tonyodev.fetch2.Error import com.tonyodev.fetch2.Status import com.tonyodev.fetch2.Status.NONE +import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity +import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity import org.kiwix.kiwixmobile.core.downloader.model.Base64String import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel @@ -27,7 +29,6 @@ import org.kiwix.kiwixmobile.core.downloader.model.DownloadState import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Pending import org.kiwix.kiwixmobile.core.downloader.model.Seconds import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity -import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchEntity import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity import org.kiwix.kiwixmobile.core.entity.MetaLinkNetworkEntity.FileElement @@ -164,3 +165,40 @@ fun libraryNetworkEntity(books: List = emptyList()) = LibraryNetworkEntity fun recentSearchEntity(id: Long = 0L, searchTerm: String = "", zimId: String = "") = RecentSearchEntity(id, searchTerm, zimId) + +fun bookOnDiskEntity( + id: Long = 0, + file: File = File(""), + bookId: String = "", + title: String = "", + description: String = "", + language: String = "", + creator: String = "", + publisher: String = "", + date: String = "", + url: String? = "", + articleCount: String = "", + mediaCount: String = "", + size: String = "", + name: String? = "", + favIcon: String = "", + tags: String? = "" +) = + BookOnDiskEntity( + id, + file, + bookId, + title, + description, + language, + creator, + publisher, + date, + url, + articleCount, + mediaCount, + size, + name, + favIcon, + tags + ) diff --git a/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt new file mode 100644 index 000000000..3ebc38fee --- /dev/null +++ b/core/src/test/java/org/kiwix/kiwixmobile/core/dao/NewBookDaoTest.kt @@ -0,0 +1,134 @@ +/* + * Kiwix Android + * Copyright (c) 2020 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao + +import io.mockk.CapturingSlot +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import io.mockk.slot +import io.mockk.verify +import io.objectbox.Box +import io.objectbox.query.Query +import io.objectbox.query.QueryBuilder +import io.objectbox.rx.RxQuery +import io.reactivex.Observable +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity +import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity_ +import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk +import org.kiwix.sharedFunctions.book +import org.kiwix.sharedFunctions.bookOnDisk +import org.kiwix.sharedFunctions.bookOnDiskEntity +import java.io.File +import java.util.concurrent.Callable + +internal class NewBookDaoTest { + + private val box: Box = mockk(relaxed = true) + private val newBookDao = NewBookDao(box) + + @Nested + inner class BooksTests { + @Test + fun `books emits entities whose file exists`() { + val (expectedEntity, _) = expectEmissionOfExistingAndNotExistingBook() + newBookDao.books().test().assertValues(listOf(BookOnDisk(expectedEntity))) + } + + @Test + fun `books deletes entities whose file does not exist`() { + val (_, deletedEntity) = expectEmissionOfExistingAndNotExistingBook() + newBookDao.books().test() + verify { box.remove(listOf(deletedEntity)) } + } + + private fun expectEmissionOfExistingAndNotExistingBook(): + Pair { + val query: Query = mockk() + every { box.query().build() } returns query + val fileThatExists = mockk() + val fileThatDoesNotExist = mockk() + every { fileThatExists.exists() } returns true + every { fileThatDoesNotExist.exists() } returns false + val entityThatExists = bookOnDiskEntity(file = fileThatExists) + val entityThatDoesNotExist = bookOnDiskEntity(file = fileThatDoesNotExist) + mockkStatic(RxQuery::class) + every { RxQuery.observable(query) } returns Observable.just( + listOf(entityThatExists, entityThatDoesNotExist) + ) + return Pair(entityThatExists, entityThatDoesNotExist) + } + } + + @Test + fun getBooks() { + val entity = bookOnDiskEntity() + every { box.all } returns mutableListOf(entity) + assertThat(newBookDao.getBooks()).isEqualTo(listOf(BookOnDisk(entity))) + } + + @Test + fun `insert transaction adds books to the box that have distinct ids`() { + val slot: CapturingSlot> = slot() + every { box.store.callInTx(capture(slot)) } returns Unit + val distinctBook: BookOnDisk = bookOnDisk(databaseId = 0, book = book(id = "same")) + newBookDao.insert( + listOf(distinctBook, bookOnDisk(databaseId = 1, book = book(id = "same"))) + ) + slot.captured.call() + verify { box.put(listOf(BookOnDiskEntity(distinctBook))) } + } + + @Test + fun `insert transaction does not add books if a book with the same path exists in the box`() { + val slot: CapturingSlot> = slot() + every { box.store.callInTx(capture(slot)) } returns Unit + val distinctBook: BookOnDisk = bookOnDisk() + newBookDao.insert(listOf(distinctBook)) + val queryBuilder: QueryBuilder = mockk(relaxed = true) + every { box.query() } returns queryBuilder + every { + queryBuilder.`in`(BookOnDiskEntity_.file, arrayOf(distinctBook.file.path)) + } returns queryBuilder + val query: Query = mockk(relaxed = true) + every { queryBuilder.build() } returns query + every { query.find() } returns listOf(bookOnDiskEntity(file = distinctBook.file)) + slot.captured.call() + verify { box.put(listOf()) } + } + + @Test + fun delete() { + } + + @Test + fun migrationInsert() { + } + + @Test + fun getFavIconAndZimFile() { + } + + @Test + fun bookMatching() { + } +}