Manga parsers unit tests
This commit is contained in:
@@ -92,6 +92,4 @@ dependencies {
|
|||||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
|
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
testImplementation 'androidx.test:core:1.2.0'
|
|
||||||
testImplementation 'org.mockito:mockito-core:2.23.0'
|
|
||||||
}
|
}
|
||||||
@@ -4,14 +4,26 @@ import android.content.Context
|
|||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.model.MangaSource
|
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)
|
private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE)
|
||||||
?.takeUnless(String::isBlank)
|
|
||||||
?: defaultValue
|
|
||||||
|
|
||||||
|
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.core.prefs.SourceConfig
|
||||||
import org.koitharu.kotatsu.utils.ext.await
|
import org.koitharu.kotatsu.utils.ext.await
|
||||||
|
|
||||||
class MangaLoaderContext : KoinComponent {
|
open class MangaLoaderContext : KoinComponent {
|
||||||
|
|
||||||
private val okHttp by inject<OkHttpClient>()
|
private val okHttp by inject<OkHttpClient>()
|
||||||
|
|
||||||
@@ -43,5 +43,5 @@ class MangaLoaderContext : KoinComponent {
|
|||||||
return okHttp.newCall(request.build()).await()
|
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 {
|
object AssertX {
|
||||||
|
|
||||||
private val VALID_RESPONSE_CODES = arrayOf(
|
fun assertContentType(url: String, type: String, subtype: String? = null) {
|
||||||
HttpURLConnection.HTTP_OK,
|
Assert.assertFalse("URL is empty", url.isEmpty())
|
||||||
HttpURLConnection.HTTP_MOVED_PERM,
|
|
||||||
HttpURLConnection.HTTP_MOVED_TEMP
|
|
||||||
)
|
|
||||||
|
|
||||||
fun assertValidUrl(url: String) {
|
|
||||||
val cn = URL(url).openConnection() as HttpURLConnection
|
val cn = URL(url).openConnection() as HttpURLConnection
|
||||||
|
cn.requestMethod = "HEAD"
|
||||||
cn.connect()
|
cn.connect()
|
||||||
val code = cn.responseCode
|
when (val code = cn.responseCode) {
|
||||||
Assert.assertTrue("Invalid response code $code", code in VALID_RESPONSE_CODES)
|
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