mirror of
https://github.com/Suwayomi/Suwayomi-Server.git
synced 2026-07-09 22:04:34 -05:00
improve tests
This commit is contained in:
@@ -1,204 +0,0 @@
|
||||
package suwayomi
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import mu.KotlinLogging
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import rx.Observable
|
||||
import suwayomi.tachidesk.manga.impl.Source.getSourceList
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.installExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.uninstallExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension.updateExtension
|
||||
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList.getExtensionList
|
||||
import suwayomi.tachidesk.manga.impl.util.lang.awaitSingle
|
||||
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogueSource
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.server.applicationSetup
|
||||
import xyz.nulldev.ts.config.CONFIG_PREFIX
|
||||
import java.io.File
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class TestExtensions {
|
||||
private val logger = KotlinLogging.logger {}
|
||||
private lateinit var extensions: List<ExtensionDataClass>
|
||||
private lateinit var sources: List<HttpSource>
|
||||
|
||||
private val mangaToFetch = mutableListOf<Pair<HttpSource, SManga>>()
|
||||
private val failedToFetch = mutableListOf<Pair<HttpSource, Exception>>()
|
||||
private val mangaFailedToFetch = mutableListOf<Triple<HttpSource, SManga, Exception>>()
|
||||
private val chaptersToFetch = mutableListOf<Triple<HttpSource, SManga, SChapter>>()
|
||||
private val chaptersFailedToFetch = mutableListOf<Triple<HttpSource, SManga, Throwable>>()
|
||||
private val chaptersPageListFailedToFetch = mutableListOf<Triple<HttpSource, Pair<SManga, SChapter>, Exception>>()
|
||||
|
||||
@BeforeAll
|
||||
fun setup() {
|
||||
val dataRoot = File(BASE_PATH).absolutePath
|
||||
System.setProperty("$CONFIG_PREFIX.server.rootDir", dataRoot)
|
||||
applicationSetup()
|
||||
setLoggingEnabled(false)
|
||||
|
||||
runBlocking {
|
||||
extensions = getExtensionList()
|
||||
extensions.forEach {
|
||||
when {
|
||||
it.obsolete -> {
|
||||
uninstallExtension(it.pkgName)
|
||||
}
|
||||
it.hasUpdate -> {
|
||||
updateExtension(it.pkgName)
|
||||
}
|
||||
else -> {
|
||||
uninstallExtension(it.pkgName)
|
||||
installExtension(it.pkgName)
|
||||
}
|
||||
}
|
||||
}
|
||||
sources = getSourceList().map { getCatalogueSource(it.id.toLong())!! as HttpSource }
|
||||
}
|
||||
setLoggingEnabled(true)
|
||||
File("$BASE_PATH/sources.txt").writeText(sources.joinToString("\n") { "${it.name} - ${it.lang.uppercase()} - ${it.id}" })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun runTest() {
|
||||
runBlocking(Dispatchers.Default) {
|
||||
val semaphore = Semaphore(10)
|
||||
val popularCount = AtomicInteger(1)
|
||||
sources.map { source ->
|
||||
async {
|
||||
semaphore.withPermit {
|
||||
logger.info { "${popularCount.getAndIncrement()} - Now fetching popular manga from $source" }
|
||||
try {
|
||||
mangaToFetch += source to (
|
||||
source.fetchPopularManga(1)
|
||||
.awaitSingleRepeat().mangas.firstOrNull()
|
||||
?: throw Exception("Source returned no manga")
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.warn { "Failed to fetch popular manga from $source: ${e.message}" }
|
||||
failedToFetch += source to e
|
||||
}
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
File("$BASE_PATH/failedToFetch.txt").writeText(
|
||||
failedToFetch.joinToString("\n") { (source, exception) ->
|
||||
"${source.name} (${source.lang.uppercase()}, ${source.id}):" +
|
||||
" ${exception.message}"
|
||||
}
|
||||
)
|
||||
logger.info { "Now fetching manga info from ${mangaToFetch.size} sources" }
|
||||
|
||||
val mangaCount = AtomicInteger(1)
|
||||
mangaToFetch.map { (source, manga) ->
|
||||
async {
|
||||
semaphore.withPermit {
|
||||
logger.info { "${mangaCount.getAndIncrement()} - Now fetching manga from $source" }
|
||||
try {
|
||||
manga.copyFrom(source.fetchMangaDetails(manga).awaitSingleRepeat())
|
||||
manga.initialized = true
|
||||
} catch (e: Exception) {
|
||||
logger.warn {
|
||||
"Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest(manga).url}): ${e.message}"
|
||||
}
|
||||
mangaFailedToFetch += Triple(source, manga, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
File("$BASE_PATH/MangaFailedToFetch.txt").writeText(
|
||||
mangaFailedToFetch.joinToString("\n") { (source, manga, exception) ->
|
||||
"${source.name} (${source.lang}, ${source.id}):" +
|
||||
" ${manga.title} (${source.mangaDetailsRequest(manga).url}):" +
|
||||
" ${exception.message}"
|
||||
}
|
||||
)
|
||||
logger.info { "Now fetching manga chapters from ${mangaToFetch.size} sources" }
|
||||
|
||||
val chapterCount = AtomicInteger(1)
|
||||
mangaToFetch.filter { it.second.initialized }.map { (source, manga) ->
|
||||
async {
|
||||
semaphore.withPermit {
|
||||
logger.info { "${chapterCount.getAndIncrement()} - Now fetching manga chapters from $source" }
|
||||
try {
|
||||
chaptersToFetch += Triple(
|
||||
source,
|
||||
manga,
|
||||
source.fetchChapterList(manga).awaitSingleRepeat().firstOrNull() ?: throw Exception("Source returned no chapters")
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logger.warn {
|
||||
"Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest(manga).url}): ${e.message}"
|
||||
}
|
||||
chaptersFailedToFetch += Triple(source, manga, e)
|
||||
} catch (e: NoClassDefFoundError) {
|
||||
logger.warn {
|
||||
"Failed to fetch manga chapters from $source for ${manga.title} (${source.mangaDetailsRequest(manga).url}): ${e.message}"
|
||||
}
|
||||
chaptersFailedToFetch += Triple(source, manga, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
|
||||
File("$BASE_PATH/ChaptersFailedToFetch.txt").writeText(
|
||||
chaptersFailedToFetch.joinToString("\n") { (source, manga, exception) ->
|
||||
"${source.name} (${source.lang}, ${source.id}):" +
|
||||
" ${manga.title} (${source.mangaDetailsRequest(manga).url}):" +
|
||||
" ${exception.message}"
|
||||
}
|
||||
)
|
||||
|
||||
val pageListCount = AtomicInteger(1)
|
||||
chaptersToFetch.map { (source, manga, chapter) ->
|
||||
async {
|
||||
semaphore.withPermit {
|
||||
logger.info { "${pageListCount.getAndIncrement()} - Now fetching page list from $source" }
|
||||
try {
|
||||
source.fetchPageList(chapter).awaitSingleRepeat()
|
||||
} catch (e: Exception) {
|
||||
logger.warn {
|
||||
"Failed to fetch manga info from $source for ${manga.title} (${source.mangaDetailsRequest(manga).url}): ${e.message}"
|
||||
}
|
||||
chaptersPageListFailedToFetch += Triple(source, manga to chapter, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.awaitAll()
|
||||
|
||||
File("$BASE_PATH/ChapterPageListFailedToFetch.txt").writeText(
|
||||
chaptersPageListFailedToFetch.joinToString("\n") { (source, manga, exception) ->
|
||||
"${source.name} (${source.lang}, ${source.id}):" +
|
||||
" ${manga.first.title} (${source.mangaDetailsRequest(manga.first).url}):" +
|
||||
" ${manga.second.name} (${manga.second.url}): ${exception.message}"
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <T> Observable<T>.awaitSingleRepeat(): T {
|
||||
for (i in 1..2) {
|
||||
try {
|
||||
return awaitSingle()
|
||||
} catch (e: Exception) {}
|
||||
}
|
||||
return awaitSingle()
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package suwayomi
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import ch.qos.logback.classic.Level
|
||||
import mu.KotlinLogging
|
||||
import org.slf4j.Logger
|
||||
|
||||
fun setLoggingEnabled(enabled: Boolean = true) {
|
||||
val logger = (KotlinLogging.logger(Logger.ROOT_LOGGER_NAME).underlyingLogger as ch.qos.logback.classic.Logger)
|
||||
logger.level = if (enabled) {
|
||||
Level.DEBUG
|
||||
} else Level.ERROR
|
||||
}
|
||||
|
||||
const val BASE_PATH = "build/tmp/TestDesk"
|
||||
157
server/src/test/kotlin/suwayomi/tachidesk/ApplicationTest.kt
Normal file
157
server/src/test/kotlin/suwayomi/tachidesk/ApplicationTest.kt
Normal file
@@ -0,0 +1,157 @@
|
||||
package suwayomi.tachidesk
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import eu.kanade.tachiyomi.App
|
||||
import eu.kanade.tachiyomi.source.local.LocalSource
|
||||
import mu.KotlinLogging
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
import org.kodein.di.DI
|
||||
import org.kodein.di.bind
|
||||
import org.kodein.di.conf.global
|
||||
import org.kodein.di.singleton
|
||||
import masstest.BASE_PATH
|
||||
import suwayomi.tachidesk.server.ApplicationDirs
|
||||
import suwayomi.tachidesk.server.JavalinSetup
|
||||
import suwayomi.tachidesk.server.ServerConfig
|
||||
import suwayomi.tachidesk.server.androidCompat
|
||||
import suwayomi.tachidesk.server.database.databaseUp
|
||||
import suwayomi.tachidesk.server.serverConfig
|
||||
import suwayomi.tachidesk.server.systemTrayInstance
|
||||
import suwayomi.tachidesk.server.util.AppMutex
|
||||
import xyz.nulldev.androidcompat.AndroidCompatInitializer
|
||||
import xyz.nulldev.ts.config.CONFIG_PREFIX
|
||||
import xyz.nulldev.ts.config.ConfigKodeinModule
|
||||
import xyz.nulldev.ts.config.GlobalConfigManager
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
open class ApplicationTest {
|
||||
companion object {
|
||||
@BeforeAll
|
||||
@JvmStatic
|
||||
fun beforeAll() {
|
||||
if (!initializedTheApp) {
|
||||
val dataRoot = File(BASE_PATH).absolutePath
|
||||
System.setProperty("$CONFIG_PREFIX.server.rootDir", dataRoot)
|
||||
|
||||
testingSetup()
|
||||
|
||||
databaseSetup()
|
||||
|
||||
initializedTheApp = true
|
||||
}
|
||||
}
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
private var initializedTheApp = false
|
||||
|
||||
fun testingSetup() {
|
||||
// Application dirs
|
||||
val applicationDirs = ApplicationDirs()
|
||||
|
||||
DI.global.addImport(
|
||||
DI.Module("Server") {
|
||||
bind<ApplicationDirs>() with singleton { applicationDirs }
|
||||
}
|
||||
)
|
||||
|
||||
logger.debug("Data Root directory is set to: ${applicationDirs.dataRoot}")
|
||||
|
||||
// make dirs we need
|
||||
listOf(
|
||||
applicationDirs.dataRoot,
|
||||
applicationDirs.extensionsRoot,
|
||||
applicationDirs.extensionsRoot + "/icon",
|
||||
applicationDirs.mangaThumbnailsRoot,
|
||||
applicationDirs.animeThumbnailsRoot,
|
||||
applicationDirs.mangaRoot,
|
||||
applicationDirs.localMangaRoot,
|
||||
).forEach {
|
||||
File(it).mkdirs()
|
||||
}
|
||||
|
||||
// register Tachidesk's config which is dubbed "ServerConfig"
|
||||
GlobalConfigManager.registerModule(
|
||||
ServerConfig.register(GlobalConfigManager.config)
|
||||
)
|
||||
|
||||
// Make sure only one instance of the app is running
|
||||
AppMutex.handleAppMutex()
|
||||
|
||||
// Load config API
|
||||
DI.global.addImport(ConfigKodeinModule().create())
|
||||
// Load Android compatibility dependencies
|
||||
AndroidCompatInitializer().init()
|
||||
// start app
|
||||
androidCompat.startApp(App())
|
||||
|
||||
// create conf file if doesn't exist
|
||||
try {
|
||||
val dataConfFile = File("${applicationDirs.dataRoot}/server.conf")
|
||||
if (!dataConfFile.exists()) {
|
||||
JavalinSetup::class.java.getResourceAsStream("/server-reference.conf").use { input ->
|
||||
dataConfFile.outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("Exception while creating initial server.conf", e)
|
||||
}
|
||||
|
||||
// copy local source icon
|
||||
try {
|
||||
val localSourceIconFile = File("${applicationDirs.extensionsRoot}/icon/localSource.png")
|
||||
if (!localSourceIconFile.exists()) {
|
||||
JavalinSetup::class.java.getResourceAsStream("/icon/localSource.png").use { input ->
|
||||
localSourceIconFile.outputStream().use { output ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("Exception while copying Local source's icon", e)
|
||||
}
|
||||
|
||||
// create system tray
|
||||
if (serverConfig.systemTrayEnabled) {
|
||||
try {
|
||||
systemTrayInstance
|
||||
} catch (e: Throwable) { // cover both java.lang.Exception and java.lang.Error
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
// Disable jetty's logging
|
||||
System.setProperty("org.eclipse.jetty.util.log.announce", "false")
|
||||
System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog")
|
||||
System.setProperty("org.eclipse.jetty.LEVEL", "OFF")
|
||||
|
||||
// socks proxy settings
|
||||
if (serverConfig.socksProxyEnabled) {
|
||||
System.getProperties()["socksProxyHost"] = serverConfig.socksProxyHost
|
||||
System.getProperties()["socksProxyPort"] = serverConfig.socksProxyPort
|
||||
logger.info("Socks Proxy is enabled to ${serverConfig.socksProxyHost}:${serverConfig.socksProxyPort}")
|
||||
}
|
||||
}
|
||||
|
||||
fun databaseSetup() {
|
||||
// fixes #119 , ref: https://github.com/Suwayomi/Tachidesk-Server/issues/119#issuecomment-894681292 , source Id calculation depends on String.lowercase()
|
||||
Locale.setDefault(Locale.ENGLISH)
|
||||
|
||||
// in-memory database, don't discard database between connections/transactions
|
||||
val db = Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;", "org.h2.Driver")
|
||||
|
||||
databaseUp(db)
|
||||
|
||||
LocalSource.addDbRecords()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,22 @@
|
||||
package suwayomi.tachidesk.manga.controller
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import org.jetbrains.exposed.sql.deleteAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import suwayomi.BASE_PATH
|
||||
import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.server.applicationSetup
|
||||
import xyz.nulldev.ts.config.CONFIG_PREFIX
|
||||
import java.io.File
|
||||
|
||||
internal class CategoryControllerTest {
|
||||
|
||||
@BeforeEach
|
||||
internal fun setUp() {
|
||||
val dataRoot = File(BASE_PATH).absolutePath
|
||||
System.setProperty("$CONFIG_PREFIX.server.rootDir", dataRoot)
|
||||
applicationSetup()
|
||||
}
|
||||
import suwayomi.tachidesk.ApplicationTest
|
||||
|
||||
internal class CategoryControllerTest : ApplicationTest() {
|
||||
@Test
|
||||
fun categoryReorder() {
|
||||
Category.createCategory("foo")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package suwayomi.tachidesk.manga.controller
|
||||
|
||||
/*
|
||||
* Copyright (C) Contributors to the Suwayomi project
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import org.jetbrains.exposed.sql.deleteAll
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||
import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.ApplicationTest
|
||||
|
||||
@TestInstance(PER_CLASS)
|
||||
internal class SourceControllerTest : ApplicationTest() {
|
||||
@Test
|
||||
fun categoryReorder() {
|
||||
Category.createCategory("foo")
|
||||
Category.createCategory("bar")
|
||||
val cats = Category.getCategoryList()
|
||||
val foo = cats.asSequence().filter { it.name == "foo" }.first()
|
||||
val bar = cats.asSequence().filter { it.name == "bar" }.first()
|
||||
assertEquals(1, foo.order)
|
||||
assertEquals(2, bar.order)
|
||||
Category.reorderCategory(1, 2)
|
||||
val catsReordered = Category.getCategoryList()
|
||||
val fooReordered = catsReordered.asSequence().filter { it.name == "foo" }.first()
|
||||
val barReordered = catsReordered.asSequence().filter { it.name == "bar" }.first()
|
||||
assertEquals(2, fooReordered.order)
|
||||
assertEquals(1, barReordered.order)
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
internal fun tearDown() {
|
||||
transaction {
|
||||
CategoryTable.deleteAll()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,9 @@ import org.jetbrains.exposed.sql.insertAndGetId
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.TestInstance
|
||||
import suwayomi.BASE_PATH
|
||||
import suwayomi.tachidesk.manga.impl.Category.DEFAULT_CATEGORY_ID
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryMangaTable
|
||||
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable
|
||||
@@ -26,59 +25,49 @@ import suwayomi.tachidesk.manga.model.table.ChapterTable.name
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable.sourceOrder
|
||||
import suwayomi.tachidesk.manga.model.table.ChapterTable.url
|
||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
||||
import suwayomi.tachidesk.server.applicationSetup
|
||||
import xyz.nulldev.ts.config.CONFIG_PREFIX
|
||||
import java.io.File
|
||||
import suwayomi.tachidesk.ApplicationTest
|
||||
|
||||
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
|
||||
class CategoryMangaTest {
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
val dataRoot = File(BASE_PATH).absolutePath
|
||||
System.setProperty("$CONFIG_PREFIX.server.rootDir", dataRoot)
|
||||
applicationSetup()
|
||||
}
|
||||
|
||||
class CategoryMangaTest : ApplicationTest() {
|
||||
@Test
|
||||
fun getCategoryMangaList() {
|
||||
val emptyCats = CategoryManga.getCategoryMangaList(0).size
|
||||
val emptyCats = CategoryManga.getCategoryMangaList(DEFAULT_CATEGORY_ID).size
|
||||
assertEquals(0, emptyCats, "Default category should be empty at start")
|
||||
val mangaId = createManga("Psyren")
|
||||
val mangaId = createLibraryManga("Psyren")
|
||||
createChapters(mangaId, 10, true)
|
||||
assertEquals(1, CategoryManga.getCategoryMangaList(0).size, "Default category should have one member")
|
||||
assertEquals(1, CategoryManga.getCategoryMangaList(DEFAULT_CATEGORY_ID).size, "Default category should have one member")
|
||||
assertEquals(
|
||||
0, CategoryManga.getCategoryMangaList(0)[0].unreadCount,
|
||||
0, CategoryManga.getCategoryMangaList(DEFAULT_CATEGORY_ID)[0].unreadCount,
|
||||
"Manga should not have any unread chapters"
|
||||
)
|
||||
createChapters(mangaId, 10, false)
|
||||
assertEquals(
|
||||
10, CategoryManga.getCategoryMangaList(0)[0].unreadCount,
|
||||
10, CategoryManga.getCategoryMangaList(DEFAULT_CATEGORY_ID)[0].unreadCount,
|
||||
"Manga should have unread chapters"
|
||||
)
|
||||
|
||||
Category.createCategory("Old") // category id 1
|
||||
val categoryId = Category.createCategory("Old")
|
||||
assertEquals(
|
||||
0,
|
||||
CategoryManga.getCategoryMangaList(1).size,
|
||||
CategoryManga.getCategoryMangaList(categoryId).size,
|
||||
"Newly created category shouldn't have any Mangas"
|
||||
)
|
||||
CategoryManga.addMangaToCategory(mangaId, 1)
|
||||
CategoryManga.addMangaToCategory(mangaId, categoryId)
|
||||
assertEquals(
|
||||
1, CategoryManga.getCategoryMangaList(1).size,
|
||||
1, CategoryManga.getCategoryMangaList(categoryId).size,
|
||||
"Manga should been moved"
|
||||
)
|
||||
assertEquals(
|
||||
10, CategoryManga.getCategoryMangaList(1)[0].unreadCount,
|
||||
10, CategoryManga.getCategoryMangaList(categoryId)[0].unreadCount,
|
||||
"Manga should keep it's unread count in moved category"
|
||||
)
|
||||
assertEquals(
|
||||
0, CategoryManga.getCategoryMangaList(0).size,
|
||||
0, CategoryManga.getCategoryMangaList(DEFAULT_CATEGORY_ID).size,
|
||||
"Manga shouldn't be member of default category after moving"
|
||||
)
|
||||
}
|
||||
|
||||
private fun createManga(
|
||||
private fun createLibraryManga(
|
||||
_title: String
|
||||
): Int {
|
||||
return transaction {
|
||||
|
||||
Reference in New Issue
Block a user