Manga parsers unit tests
This commit is contained in:
@@ -4,14 +4,26 @@ import android.content.Context
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
|
||||
class SourceConfig(context: Context, source: MangaSource) {
|
||||
interface SourceConfig {
|
||||
|
||||
private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE)
|
||||
fun getDomain(defaultValue: String): String
|
||||
|
||||
private val keyDomain = context.getString(R.string.key_parser_domain)
|
||||
private class PrefSourceConfig(context: Context, source: MangaSource) : SourceConfig {
|
||||
|
||||
fun getDomain(defaultValue: String) = prefs.getString(keyDomain, defaultValue)
|
||||
?.takeUnless(String::isBlank)
|
||||
?: defaultValue
|
||||
private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE)
|
||||
|
||||
private val keyDomain = context.getString(R.string.key_parser_domain)
|
||||
|
||||
override fun getDomain(defaultValue: String) = prefs.getString(keyDomain, defaultValue)
|
||||
?.takeUnless(String::isBlank)
|
||||
?: defaultValue
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
operator fun invoke(context: Context, source: MangaSource): SourceConfig =
|
||||
PrefSourceConfig(context, source)
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.SourceConfig
|
||||
import org.koitharu.kotatsu.utils.ext.await
|
||||
|
||||
class MangaLoaderContext : KoinComponent {
|
||||
open class MangaLoaderContext : KoinComponent {
|
||||
|
||||
private val okHttp by inject<OkHttpClient>()
|
||||
|
||||
@@ -43,5 +43,5 @@ class MangaLoaderContext : KoinComponent {
|
||||
return okHttp.newCall(request.build()).await()
|
||||
}
|
||||
|
||||
fun getSettings(source: MangaSource) = SourceConfig(get(), source)
|
||||
open fun getSettings(source: MangaSource) = SourceConfig(get(), source)
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.koitharu.kotatsu.parsers
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.OkHttpClient
|
||||
import org.junit.Assert
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.prefs.SourceConfig
|
||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.domain.MangaProviderFactory
|
||||
import org.koitharu.kotatsu.utils.AssertX
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class RemoteRepositoryTest(source: MangaSource) {
|
||||
|
||||
private val repo = MangaProviderFactory.create(source)
|
||||
|
||||
@Test
|
||||
fun getList() {
|
||||
val list = runBlocking { repo.getList(60) }
|
||||
Assert.assertFalse(list.isEmpty())
|
||||
val item = list.random()
|
||||
AssertX.assertContentType(item.coverUrl, "image")
|
||||
AssertX.assertContentType(item.url, "text", "html")
|
||||
Assert.assertFalse(item.title.isBlank())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun search() {
|
||||
val list = runBlocking { repo.getList(0, query = "tail") }
|
||||
Assert.assertFalse(list.isEmpty())
|
||||
val item = list.random()
|
||||
AssertX.assertContentType(item.coverUrl, "image")
|
||||
AssertX.assertContentType(item.url, "text", "html")
|
||||
Assert.assertFalse(item.title.isBlank())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getTags() {
|
||||
val tags = runBlocking { repo.getTags() }
|
||||
Assert.assertFalse(tags.isEmpty())
|
||||
val tag = tags.random()
|
||||
Assert.assertFalse(tag.key.isBlank())
|
||||
Assert.assertFalse(tag.title.isBlank())
|
||||
val list = runBlocking { repo.getList(0, tag = tag) }
|
||||
Assert.assertFalse(list.isEmpty())
|
||||
val item = list.random()
|
||||
AssertX.assertContentType(item.coverUrl, "image")
|
||||
AssertX.assertContentType(item.url, "text", "html")
|
||||
Assert.assertFalse(item.title.isBlank())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getDetails() {
|
||||
val manga = runBlocking { repo.getList(0) }.random()
|
||||
val details = runBlocking { repo.getDetails(manga) }
|
||||
Assert.assertFalse(details.chapters.isNullOrEmpty())
|
||||
Assert.assertFalse(details.description.isNullOrEmpty())
|
||||
val chapter = details.chapters!!.random()
|
||||
Assert.assertFalse(chapter.name.isBlank())
|
||||
AssertX.assertContentType(chapter.url, "text", "html")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getPages() {
|
||||
val manga = runBlocking { repo.getList(0) }.random()
|
||||
val details = runBlocking { repo.getDetails(manga) }
|
||||
val pages = runBlocking { repo.getPages(details.chapters!!.random()) }
|
||||
Assert.assertFalse(pages.isEmpty())
|
||||
val page = pages.random()
|
||||
val fullUrl = runBlocking { repo.getPageFullUrl(page) }
|
||||
AssertX.assertContentType(fullUrl, "image")
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun initialize() {
|
||||
startKoin {
|
||||
modules(listOf(
|
||||
module {
|
||||
factory {
|
||||
OkHttpClient.Builder()
|
||||
.connectTimeout(20, TimeUnit.SECONDS)
|
||||
.readTimeout(60, TimeUnit.SECONDS)
|
||||
.writeTimeout(20, TimeUnit.SECONDS)
|
||||
.build()
|
||||
}
|
||||
},
|
||||
module {
|
||||
single<MangaLoaderContext> {
|
||||
object : MangaLoaderContext() {
|
||||
override fun getSettings(source: MangaSource): SourceConfig {
|
||||
return SourceConfigMock()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun getProviders() = (MangaSource.values().toList() - MangaSource.LOCAL).toTypedArray()
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.OkHttpClient
|
||||
import org.junit.BeforeClass
|
||||
import org.koin.core.context.startKoin
|
||||
import org.koin.dsl.module
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||
|
||||
abstract class RepositoryTestEnvironment {
|
||||
|
||||
lateinit var repository: MangaRepository
|
||||
|
||||
@BeforeClass
|
||||
fun initialize(source: MangaSource) {
|
||||
startKoin {
|
||||
module {
|
||||
factory {
|
||||
OkHttpClient()
|
||||
}
|
||||
single {
|
||||
MangaLoaderContext()
|
||||
}
|
||||
}
|
||||
}
|
||||
val constructor = source.cls.getConstructor(MangaLoaderContext::class.java)
|
||||
repository = constructor.newInstance(MangaLoaderContext())
|
||||
}
|
||||
|
||||
fun getMangaList() = runBlocking { repository.getList(2) }
|
||||
|
||||
fun getMangaItem() = runBlocking { repository.getDetails(repository.getList(5).last()) }
|
||||
|
||||
fun getTags() = runBlocking { repository.getTags() }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.koitharu.kotatsu.parsers
|
||||
|
||||
import org.koitharu.kotatsu.core.prefs.SourceConfig
|
||||
|
||||
class SourceConfigMock : SourceConfig {
|
||||
|
||||
override fun getDomain(defaultValue: String) = defaultValue
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.repository
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.MangaParserTest
|
||||
import org.koitharu.kotatsu.parsers.RepositoryTestEnvironment
|
||||
import org.koitharu.kotatsu.utils.AssertX
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class MintMangaTest : MangaParserTest {
|
||||
|
||||
@Test
|
||||
override fun testMangaList() {
|
||||
val list = getMangaList()
|
||||
Assert.assertTrue(list.size == 70)
|
||||
val item = list[40]
|
||||
Assert.assertTrue(item.title.isNotEmpty())
|
||||
Assert.assertTrue(item.rating in 0f..1f)
|
||||
AssertX.assertValidUrl(item.url)
|
||||
AssertX.assertValidUrl(item.coverUrl)
|
||||
Assert.assertEquals(item.source, MangaSource.MINTMANGA)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaDetails() {
|
||||
val manga = getMangaItem()
|
||||
Assert.assertNotNull(manga.largeCoverUrl)
|
||||
AssertX.assertValidUrl(manga.largeCoverUrl!!)
|
||||
Assert.assertNotNull(manga.chapters)
|
||||
val chapter = manga.chapters!!.last()
|
||||
Assert.assertEquals(chapter.source, MangaSource.MINTMANGA)
|
||||
AssertX.assertValidUrl(chapter.url)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaPages() {
|
||||
val chapter = getMangaItem().chapters!!.first()
|
||||
val pages = runBlocking { repository.getPages(chapter) }
|
||||
Assert.assertFalse(pages.isEmpty())
|
||||
Assert.assertEquals(pages.first().source, MangaSource.MINTMANGA)
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.first()) })
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.last()) })
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testTags() {
|
||||
val tags = getTags()
|
||||
Assert.assertFalse(tags.isEmpty())
|
||||
val tag = tags.first()
|
||||
Assert.assertFalse(tag.title.isBlank())
|
||||
Assert.assertEquals(tag.source, MangaSource.MINTMANGA)
|
||||
AssertX.assertValidUrl("https://mintmanga.live/list/genre/${tag.key}")
|
||||
}
|
||||
|
||||
companion object : RepositoryTestEnvironment() {
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun setUp() = initialize(MangaSource.MINTMANGA)
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.repository
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.MangaParserTest
|
||||
import org.koitharu.kotatsu.parsers.RepositoryTestEnvironment
|
||||
import org.koitharu.kotatsu.utils.AssertX
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class ReadmangaRuTest : MangaParserTest {
|
||||
|
||||
@Test
|
||||
override fun testMangaList() {
|
||||
val list = getMangaList()
|
||||
Assert.assertTrue(list.size == 70)
|
||||
val item = list[40]
|
||||
Assert.assertTrue(item.title.isNotEmpty())
|
||||
Assert.assertTrue(item.rating in 0f..1f)
|
||||
AssertX.assertValidUrl(item.url)
|
||||
AssertX.assertValidUrl(item.coverUrl)
|
||||
Assert.assertEquals(item.source, MangaSource.READMANGA_RU)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaDetails() {
|
||||
val manga = getMangaItem()
|
||||
Assert.assertNotNull(manga.largeCoverUrl)
|
||||
AssertX.assertValidUrl(manga.largeCoverUrl!!)
|
||||
Assert.assertNotNull(manga.chapters)
|
||||
val chapter = manga.chapters!!.last()
|
||||
Assert.assertEquals(chapter.source, MangaSource.READMANGA_RU)
|
||||
AssertX.assertValidUrl(chapter.url)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaPages() {
|
||||
val chapter = getMangaItem().chapters!!.first()
|
||||
val pages = runBlocking { repository.getPages(chapter) }
|
||||
Assert.assertFalse(pages.isEmpty())
|
||||
Assert.assertEquals(pages.first().source, MangaSource.READMANGA_RU)
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.first()) })
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.last()) })
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testTags() {
|
||||
val tags = getTags()
|
||||
Assert.assertFalse(tags.isEmpty())
|
||||
val tag = tags.first()
|
||||
Assert.assertFalse(tag.title.isBlank())
|
||||
Assert.assertEquals(tag.source, MangaSource.READMANGA_RU)
|
||||
AssertX.assertValidUrl("https://readmanga.me/list/genre/${tag.key}")
|
||||
}
|
||||
|
||||
companion object : RepositoryTestEnvironment() {
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun setUp() = initialize(MangaSource.READMANGA_RU)
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.repository
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.MangaParserTest
|
||||
import org.koitharu.kotatsu.parsers.RepositoryTestEnvironment
|
||||
import org.koitharu.kotatsu.utils.AssertX
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class SelfMangaTest : MangaParserTest {
|
||||
|
||||
@Test
|
||||
override fun testMangaList() {
|
||||
val list = getMangaList()
|
||||
Assert.assertTrue(list.size == 70)
|
||||
val item = list[40]
|
||||
Assert.assertTrue(item.title.isNotEmpty())
|
||||
Assert.assertTrue(item.rating in 0f..1f)
|
||||
AssertX.assertValidUrl(item.url)
|
||||
AssertX.assertValidUrl(item.coverUrl)
|
||||
Assert.assertEquals(item.source, MangaSource.SELFMANGA)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaDetails() {
|
||||
val manga = getMangaItem()
|
||||
Assert.assertNotNull(manga.largeCoverUrl)
|
||||
AssertX.assertValidUrl(manga.largeCoverUrl!!)
|
||||
Assert.assertNotNull(manga.chapters)
|
||||
val chapter = manga.chapters!!.last()
|
||||
Assert.assertEquals(chapter.source, MangaSource.SELFMANGA)
|
||||
AssertX.assertValidUrl(chapter.url)
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testMangaPages() {
|
||||
val chapter = getMangaItem().chapters!!.first()
|
||||
val pages = runBlocking { repository.getPages(chapter) }
|
||||
Assert.assertFalse(pages.isEmpty())
|
||||
Assert.assertEquals(pages.first().source, MangaSource.SELFMANGA)
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.first()) })
|
||||
AssertX.assertValidUrl(runBlocking { repository.getPageFullUrl(pages.last()) })
|
||||
}
|
||||
|
||||
@Test
|
||||
override fun testTags() {
|
||||
val tags = getTags()
|
||||
Assert.assertFalse(tags.isEmpty())
|
||||
val tag = tags.first()
|
||||
Assert.assertFalse(tag.title.isBlank())
|
||||
Assert.assertEquals(tag.source, MangaSource.SELFMANGA)
|
||||
AssertX.assertValidUrl("https://selfmanga.ru/list/genre/${tag.key}")
|
||||
}
|
||||
|
||||
companion object : RepositoryTestEnvironment() {
|
||||
|
||||
@JvmStatic
|
||||
@BeforeClass
|
||||
fun setUp() = initialize(MangaSource.SELFMANGA)
|
||||
}
|
||||
}
|
||||
@@ -6,17 +6,23 @@ import java.net.URL
|
||||
|
||||
object AssertX {
|
||||
|
||||
private val VALID_RESPONSE_CODES = arrayOf(
|
||||
HttpURLConnection.HTTP_OK,
|
||||
HttpURLConnection.HTTP_MOVED_PERM,
|
||||
HttpURLConnection.HTTP_MOVED_TEMP
|
||||
)
|
||||
|
||||
fun assertValidUrl(url: String) {
|
||||
fun assertContentType(url: String, type: String, subtype: String? = null) {
|
||||
Assert.assertFalse("URL is empty", url.isEmpty())
|
||||
val cn = URL(url).openConnection() as HttpURLConnection
|
||||
cn.requestMethod = "HEAD"
|
||||
cn.connect()
|
||||
val code = cn.responseCode
|
||||
Assert.assertTrue("Invalid response code $code", code in VALID_RESPONSE_CODES)
|
||||
when (val code = cn.responseCode) {
|
||||
HttpURLConnection.HTTP_MOVED_PERM,
|
||||
HttpURLConnection.HTTP_MOVED_TEMP -> assertContentType(cn.getHeaderField("Location"), type, subtype)
|
||||
HttpURLConnection.HTTP_OK -> {
|
||||
val ct = cn.contentType.substringBeforeLast(';').split("/")
|
||||
Assert.assertEquals(type, ct.first())
|
||||
if (subtype != null) {
|
||||
Assert.assertEquals(subtype, ct.last())
|
||||
}
|
||||
}
|
||||
else -> Assert.fail("Invalid response code $code")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user