Manga parsers unit tests

pull/1/head
Koitharu 6 years ago
parent c765e03b28
commit f0b3400103

@ -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 {
fun getDomain(defaultValue: String): String
private class PrefSourceConfig(context: Context, source: MangaSource) : SourceConfig {
private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE) private val prefs = context.getSharedPreferences(source.name, Context.MODE_PRIVATE)
private val keyDomain = context.getString(R.string.key_parser_domain) private val keyDomain = context.getString(R.string.key_parser_domain)
fun getDomain(defaultValue: String) = prefs.getString(keyDomain, defaultValue) override fun getDomain(defaultValue: String) = prefs.getString(keyDomain, defaultValue)
?.takeUnless(String::isBlank) ?.takeUnless(String::isBlank)
?: defaultValue ?: 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")
}
} }
} }
Loading…
Cancel
Save