# Conflicts:
#	app/build.gradle
#	app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/ActivityMixin.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/FlexibleViewHolder.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/adapter/SmartFragmentStatePagerAdapter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/BaseRxFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/base/fragment/FragmentMixin.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/latest_updates/LatestUpdatesFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/main/ChangelogDialogFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaEvent.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/ChapterCountEvent.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaFavoriteEvent.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoPresenter.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/recently_read/RecentlyReadFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAboutFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsActivity.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadsFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingFragment.kt
#	app/src/main/java/eu/kanade/tachiyomi/util/AndroidComponentUtil.java
#	app/src/main/java/eu/kanade/tachiyomi/widget/preference/LibraryColumnsDialog.kt
#	app/src/main/java/eu/kanade/tachiyomi/widget/preference/SimpleDialogPreference.kt
#	app/src/main/res/layout/activity_download_manager.xml
#	app/src/main/res/layout/activity_edit_categories.xml
#	app/src/main/res/layout/activity_manga.xml
#	app/src/main/res/layout/activity_preferences.xml
#	app/src/main/res/layout/fragment_backup.xml
#	app/src/main/res/layout/fragment_download_queue.xml
#	app/src/main/res/layout/fragment_library.xml
#	app/src/main/res/layout/fragment_library_category.xml
#	app/src/main/res/layout/item_chapter.xml
#	app/src/main/res/layout/item_recent_chapters.xml
#	app/src/main/res/layout/toolbar.xml
#	app/src/main/res/raw/changelog_release.xml
#	app/src/main/res/values/arrays.xml
#	app/src/main/res/xml/pref_about.xml
#	app/src/main/res/xml/pref_advanced.xml
#	app/src/main/res/xml/pref_downloads.xml
#	app/src/main/res/xml/pref_general.xml
#	app/src/main/res/xml/pref_reader.xml
#	app/src/main/res/xml/pref_sources.xml
#	app/src/main/res/xml/pref_tracking.xml

Migrate to Tachiyomi 6.1
Rewrite batch add UI
This commit is contained in:
NerdNumber9
2017-08-24 11:24:23 -04:00
301 changed files with 12222 additions and 10356 deletions

View File

@@ -1,8 +0,0 @@
package eu.kanade.tachiyomi
open class TestApp : App() {
override fun setupAcra() {
// Do nothing
}
}

View File

@@ -1,412 +0,0 @@
package eu.kanade.tachiyomi.data.backup
import android.app.Application
import android.content.Context
import android.os.Build
import com.github.salomonbrys.kotson.fromJson
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.DHistory
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.*
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.*
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import rx.Observable
import rx.observers.TestSubscriber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingleton
/**
* Test class for the [BackupManager].
* Note that this does not include the backup create/restore services.
*/
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
@RunWith(CustomRobolectricGradleTestRunner::class)
class BackupTest {
// Create root object
var root = JsonObject()
// Create information object
var information = JsonObject()
// Create manga array
var mangaEntries = JsonArray()
// Create category array
var categoryEntries = JsonArray()
lateinit var app: Application
lateinit var context: Context
lateinit var source: HttpSource
lateinit var backupManager: BackupManager
lateinit var db: DatabaseHelper
@Before
fun setup() {
app = RuntimeEnvironment.application
context = app.applicationContext
backupManager = BackupManager(context)
db = backupManager.databaseHelper
// Mock the source manager
val module = object : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingleton(Mockito.mock(SourceManager::class.java, RETURNS_DEEP_STUBS))
}
}
Injekt.importModule(module)
source = mock(HttpSource::class.java)
`when`(backupManager.sourceManager.get(anyLong())).thenReturn(source)
root.add(Backup.MANGAS, mangaEntries)
root.add(Backup.CATEGORIES, categoryEntries)
}
/**
* Test that checks if no crashes when no categories in library.
*/
@Test
fun testRestoreEmptyCategory() {
// Initialize json with version 2
initializeJsonTest(2)
// Create backup of empty database
backupManager.backupCategories(categoryEntries)
// Restore Json
backupManager.restoreCategories(categoryEntries)
// Check if empty
val dbCats = db.getCategories().executeAsBlocking()
assertThat(dbCats).isEmpty()
}
/**
* Test to check if single category gets restored
*/
@Test
fun testRestoreSingleCategory() {
// Initialize json with version 2
initializeJsonTest(2)
// Create category and add to json
val category = addSingleCategory("category")
// Restore Json
backupManager.restoreCategories(categoryEntries)
// Check if successful
val dbCats = backupManager.databaseHelper.getCategories().executeAsBlocking()
assertThat(dbCats).hasSize(1)
assertThat(dbCats[0].name).isEqualTo(category.name)
}
/**
* Test to check if multiple categories get restored.
*/
@Test
fun testRestoreMultipleCategories() {
// Initialize json with version 2
initializeJsonTest(2)
// Create category and add to json
val category = addSingleCategory("category")
val category2 = addSingleCategory("category2")
val category3 = addSingleCategory("category3")
val category4 = addSingleCategory("category4")
val category5 = addSingleCategory("category5")
// Insert category to test if no duplicates on restore.
db.insertCategory(category).executeAsBlocking()
// Restore Json
backupManager.restoreCategories(categoryEntries)
// Check if successful
val dbCats = backupManager.databaseHelper.getCategories().executeAsBlocking()
assertThat(dbCats).hasSize(5)
assertThat(dbCats[0].name).isEqualTo(category.name)
assertThat(dbCats[1].name).isEqualTo(category2.name)
assertThat(dbCats[2].name).isEqualTo(category3.name)
assertThat(dbCats[3].name).isEqualTo(category4.name)
assertThat(dbCats[4].name).isEqualTo(category5.name)
}
/**
* Test if restore of manga is successful
*/
@Test
fun testRestoreManga() {
// Initialize json with version 2
initializeJsonTest(2)
// Add manga to database
val manga = getSingleManga("One Piece")
manga.viewer = 3
manga.id = db.insertManga(manga).executeAsBlocking().insertedId()
var favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
assertThat(favoriteManga).hasSize(1)
assertThat(favoriteManga[0].viewer).isEqualTo(3)
// Update json with all options enabled
mangaEntries.add(backupManager.backupMangaObject(manga,1))
// Change manga in database to default values
val dbManga = getSingleManga("One Piece")
dbManga.id = manga.id
db.insertManga(dbManga).executeAsBlocking()
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
assertThat(favoriteManga).hasSize(1)
assertThat(favoriteManga[0].viewer).isEqualTo(0)
// Restore local manga
backupManager.restoreMangaNoFetch(manga,dbManga)
// Test if restore successful
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
assertThat(favoriteManga).hasSize(1)
assertThat(favoriteManga[0].viewer).isEqualTo(3)
// Clear database to test manga fetch
clearDatabase()
// Test if successful
favoriteManga = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
assertThat(favoriteManga).hasSize(0)
// Restore Json
// Create JSON from manga to test parser
val json = backupManager.parser.toJsonTree(manga)
// Restore JSON from manga to test parser
val jsonManga = backupManager.parser.fromJson<MangaImpl>(json)
// Restore manga with fetch observable
val networkManga = getSingleManga("One Piece")
networkManga.description = "This is a description"
`when`(source.fetchMangaDetails(jsonManga)).thenReturn(Observable.just(networkManga))
val obs = backupManager.restoreMangaFetchObservable(source, jsonManga)
val testSubscriber = TestSubscriber<Manga>()
obs.subscribe(testSubscriber)
testSubscriber.assertNoErrors()
// Check if restore successful
val dbCats = backupManager.databaseHelper.getFavoriteMangas().executeAsBlocking()
assertThat(dbCats).hasSize(1)
assertThat(dbCats[0].viewer).isEqualTo(3)
assertThat(dbCats[0].description).isEqualTo("This is a description")
}
/**
* Test if chapter restore is successful
*/
@Test
fun testRestoreChapters() {
// Initialize json with version 2
initializeJsonTest(2)
// Insert manga
val manga = getSingleManga("One Piece")
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
// Create restore list
val chapters = ArrayList<Chapter>()
for (i in 1..8){
val chapter = getSingleChapter("Chapter $i")
chapter.read = true
chapters.add(chapter)
}
// Check parser
val chaptersJson = backupManager.parser.toJsonTree(chapters)
val restoredChapters = backupManager.parser.fromJson<List<ChapterImpl>>(chaptersJson)
// Fetch chapters from upstream
// Create list
val chaptersRemote = ArrayList<Chapter>()
(1..10).mapTo(chaptersRemote) { getSingleChapter("Chapter $it") }
`when`(source.fetchChapterList(manga)).thenReturn(Observable.just(chaptersRemote))
// Call restoreChapterFetchObservable
val obs = backupManager.restoreChapterFetchObservable(source, manga, restoredChapters)
val testSubscriber = TestSubscriber<Pair<List<Chapter>, List<Chapter>>>()
obs.subscribe(testSubscriber)
testSubscriber.assertNoErrors()
val dbCats = backupManager.databaseHelper.getChapters(manga).executeAsBlocking()
assertThat(dbCats).hasSize(10)
assertThat(dbCats[0].read).isEqualTo(true)
}
/**
* Test to check if history restore works
*/
@Test
fun restoreHistoryForManga(){
// Initialize json with version 2
initializeJsonTest(2)
val manga = getSingleManga("One Piece")
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
// Create chapter
val chapter = getSingleChapter("Chapter 1")
chapter.manga_id = manga.id
chapter.read = true
chapter.id = backupManager.databaseHelper.insertChapter(chapter).executeAsBlocking().insertedId()
val historyJson = getSingleHistory(chapter)
val historyList = ArrayList<DHistory>()
historyList.add(historyJson)
// Check parser
val historyListJson = backupManager.parser.toJsonTree(historyList)
val history = backupManager.parser.fromJson<List<DHistory>>(historyListJson)
// Restore categories
backupManager.restoreHistoryForManga(history)
val historyDB = backupManager.databaseHelper.getHistoryByMangaId(manga.id!!).executeAsBlocking()
assertThat(historyDB).hasSize(1)
assertThat(historyDB[0].last_read).isEqualTo(1000)
}
/**
* Test to check if tracking restore works
*/
@Test
fun restoreTrackForManga() {
// Initialize json with version 2
initializeJsonTest(2)
// Create mangas
val manga = getSingleManga("One Piece")
val manga2 = getSingleManga("Bleach")
manga.id = backupManager.databaseHelper.insertManga(manga).executeAsBlocking().insertedId()
manga2.id = backupManager.databaseHelper.insertManga(manga2).executeAsBlocking().insertedId()
// Create track and add it to database
// This tests duplicate errors.
val track = getSingleTrack(manga)
track.last_chapter_read = 5
backupManager.databaseHelper.insertTrack(track).executeAsBlocking()
var trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
assertThat(trackDB).hasSize(1)
assertThat(trackDB[0].last_chapter_read).isEqualTo(5)
track.last_chapter_read = 7
// Create track for different manga to test track not in database
val track2 = getSingleTrack(manga2)
track2.last_chapter_read = 10
// Check parser and restore already in database
var trackList = listOf(track)
//Check parser
var trackListJson = backupManager.parser.toJsonTree(trackList)
var trackListRestore = backupManager.parser.fromJson<List<TrackImpl>>(trackListJson)
backupManager.restoreTrackForManga(manga, trackListRestore)
// Assert if restore works.
trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
assertThat(trackDB).hasSize(1)
assertThat(trackDB[0].last_chapter_read).isEqualTo(7)
// Check parser and restore already in database with lower chapter_read
track.last_chapter_read = 5
trackList = listOf(track)
backupManager.restoreTrackForManga(manga, trackList)
// Assert if restore works.
trackDB = backupManager.databaseHelper.getTracks(manga).executeAsBlocking()
assertThat(trackDB).hasSize(1)
assertThat(trackDB[0].last_chapter_read).isEqualTo(7)
// Check parser and restore, track not in database
trackList = listOf(track2)
//Check parser
trackListJson = backupManager.parser.toJsonTree(trackList)
trackListRestore = backupManager.parser.fromJson<List<TrackImpl>>(trackListJson)
backupManager.restoreTrackForManga(manga2, trackListRestore)
// Assert if restore works.
trackDB = backupManager.databaseHelper.getTracks(manga2).executeAsBlocking()
assertThat(trackDB).hasSize(1)
assertThat(trackDB[0].last_chapter_read).isEqualTo(10)
}
fun clearJson() {
root = JsonObject()
information = JsonObject()
mangaEntries = JsonArray()
categoryEntries = JsonArray()
}
fun initializeJsonTest(version: Int) {
clearJson()
backupManager.setVersion(version)
}
fun addSingleCategory(name: String): Category {
val category = Category.create(name)
val catJson = backupManager.parser.toJsonTree(category)
categoryEntries.add(catJson)
return category
}
fun clearDatabase(){
db.deleteMangas().executeAsBlocking()
db.deleteHistory().executeAsBlocking()
}
fun getSingleHistory(chapter: Chapter): DHistory {
return DHistory(chapter.url, 1000)
}
private fun getSingleTrack(manga: Manga): TrackImpl {
val track = TrackImpl()
track.title = manga.title
track.manga_id = manga.id!!
track.remote_id = 1
track.sync_id = 1
return track
}
private fun getSingleManga(title: String): MangaImpl {
val manga = MangaImpl()
manga.source = 1
manga.title = title
manga.url = "/manga/$title"
manga.favorite = true
return manga
}
private fun getSingleChapter(name: String): ChapterImpl {
val chapter = ChapterImpl()
chapter.name = name
chapter.url = "/read-online/$name-page-1.html"
return chapter
}
}

View File

@@ -1,110 +0,0 @@
package eu.kanade.tachiyomi.data.database
import android.os.Build
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
@RunWith(CustomRobolectricGradleTestRunner::class)
class CategoryTest {
lateinit var db: DatabaseHelper
@Before
fun setup() {
val app = RuntimeEnvironment.application
db = DatabaseHelper(app)
// Create 5 manga
createManga("a")
createManga("b")
createManga("c")
createManga("d")
createManga("e")
}
@Test
fun testHasCategories() {
// Create 2 categories
createCategory("Reading")
createCategory("Hold")
val categories = db.getCategories().executeAsBlocking()
assertThat(categories).hasSize(2)
}
@Test
fun testHasLibraryMangas() {
val mangas = db.getLibraryMangas().executeAsBlocking()
assertThat(mangas).hasSize(5)
}
@Test
fun testHasCorrectFavorites() {
val m = Manga.create(0)
m.title = "title"
m.author = ""
m.artist = ""
m.thumbnail_url = ""
m.genre = "a list of genres"
m.description = "long description"
m.url = "url to manga"
m.favorite = false
db.insertManga(m).executeAsBlocking()
val mangas = db.getLibraryMangas().executeAsBlocking()
assertThat(mangas).hasSize(5)
}
@Test
fun testMangaInCategory() {
// Create 2 categories
createCategory("Reading")
createCategory("Hold")
// It should not have 0 as id
val c = db.getCategories().executeAsBlocking()[0]
assertThat(c.id).isNotZero()
// Add a manga to a category
val m = db.getMangas().executeAsBlocking()[0]
val mc = MangaCategory.create(m, c)
db.insertMangaCategory(mc).executeAsBlocking()
// Get mangas from library and assert manga category is the same
val mangas = db.getLibraryMangas().executeAsBlocking()
for (manga in mangas) {
if (manga.id == m.id) {
assertThat(manga.category).isEqualTo(c.id)
}
}
}
private fun createManga(title: String) {
val m = Manga.create(0)
m.title = title
m.author = ""
m.artist = ""
m.thumbnail_url = ""
m.genre = "a list of genres"
m.description = "long description"
m.url = "url to manga"
m.favorite = true
db.insertManga(m).executeAsBlocking()
}
private fun createCategory(name: String) {
val c = CategoryImpl()
c.name = name
db.insertCategory(c).executeAsBlocking()
}
}

View File

@@ -1,443 +0,0 @@
package eu.kanade.tachiyomi.data.database
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.ChapterRecognition
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
class ChapterRecognitionTest {
/**
* The manga containing manga title
*/
lateinit var manga: Manga
/**
* The chapter containing chapter name
*/
lateinit var chapter: Chapter
/**
* Set chapter title
* @param name name of chapter
* @return chapter object
*/
private fun createChapter(name: String): Chapter {
chapter = Chapter.create()
chapter.name = name
return chapter
}
/**
* Set manga title
* @param title title of manga
* @return manga object
*/
private fun createManga(title: String): Manga {
manga.title = title
return manga
}
/**
* Called before test
*/
@Before fun setup() {
manga = Manga.create(0).apply { title = "random" }
chapter = Chapter.create()
}
/**
* Ch.xx base case
*/
@Test fun ChCaseBase() {
createManga("Mokushiroku Alice")
createChapter("Mokushiroku Alice Vol.1 Ch.4: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4f)
}
/**
* Ch.xx.x base case
*/
@Test fun ChCaseDecimal() {
createManga("Mokushiroku Alice")
createChapter("Mokushiroku Alice Vol.1 Ch.4.1: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4.1f)
createChapter("Mokushiroku Alice Vol.1 Ch.4.4: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4.4f)
}
/**
* Ch.xx.a base case
*/
@Test fun ChCaseAlpha() {
createManga("Mokushiroku Alice")
createChapter("Mokushiroku Alice Vol.1 Ch.4.a: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4.1f)
createChapter("Mokushiroku Alice Vol.1 Ch.4.b: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4.2f)
createChapter("Mokushiroku Alice Vol.1 Ch.4.extra: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4.99f)
}
/**
* Name containing one number base case
*/
@Test fun OneNumberCaseBase() {
createManga("Bleach")
createChapter("Bleach 567 Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567f)
}
/**
* Name containing one number and decimal case
*/
@Test fun OneNumberCaseDecimal() {
createManga("Bleach")
createChapter("Bleach 567.1 Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567.1f)
createChapter("Bleach 567.4 Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567.4f)
}
/**
* Name containing one number and alpha case
*/
@Test fun OneNumberCaseAlpha() {
createManga("Bleach")
createChapter("Bleach 567.a Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567.1f)
createChapter("Bleach 567.b Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567.2f)
createChapter("Bleach 567.extra Down With Snowwhite")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(567.99f)
}
/**
* Chapter containing manga title and number base case
*/
@Test fun MangaTitleCaseBase() {
createManga("Solanin")
createChapter("Solanin 028 Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28f)
}
/**
* Chapter containing manga title and number decimal case
*/
@Test fun MangaTitleCaseDecimal() {
createManga("Solanin")
createChapter("Solanin 028.1 Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.1f)
createChapter("Solanin 028.4 Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.4f)
}
/**
* Chapter containing manga title and number alpha case
*/
@Test fun MangaTitleCaseAlpha() {
createManga("Solanin")
createChapter("Solanin 028.a Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.1f)
createChapter("Solanin 028.b Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.2f)
createChapter("Solanin 028.extra Vol. 2")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.99f)
}
/**
* Extreme base case
*/
@Test fun ExtremeCaseBase() {
createManga("Onepunch-Man")
createChapter("Onepunch-Man Punch Ver002 028")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28f)
}
/**
* Extreme base case decimal
*/
@Test fun ExtremeCaseDecimal() {
createManga("Onepunch-Man")
createChapter("Onepunch-Man Punch Ver002 028.1")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.1f)
createChapter("Onepunch-Man Punch Ver002 028.4")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.4f)
}
/**
* Extreme base case alpha
*/
@Test fun ExtremeCaseAlpha() {
createManga("Onepunch-Man")
createChapter("Onepunch-Man Punch Ver002 028.a")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.1f)
createChapter("Onepunch-Man Punch Ver002 028.b")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.2f)
createChapter("Onepunch-Man Punch Ver002 028.extra")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(28.99f)
}
/**
* Chapter containing .v2
*/
@Test fun dotV2Case() {
createChapter("Vol.1 Ch.5v.2: Alones")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(5f)
}
/**
* Check for case with number in manga title
*/
@Test fun numberInMangaTitleCase() {
createManga("Ayame 14")
createChapter("Ayame 14 1 - The summer of 14")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(1f)
}
/**
* Case with space between ch. x
*/
@Test fun spaceAfterChapterCase() {
createManga("Mokushiroku Alice")
createChapter("Mokushiroku Alice Vol.1 Ch. 4: Misrepresentation")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(4f)
}
/**
* Chapter containing mar(ch)
*/
@Test fun marchInChapterCase() {
createManga("Ayame 14")
createChapter("Vol.1 Ch.1: March 25 (First Day Cohabiting)")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(1f)
}
/**
* Chapter containing range
*/
@Test fun rangeInChapterCase() {
createChapter("Ch.191-200 Read Online")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(191f)
}
/**
* Chapter containing multiple zeros
*/
@Test fun multipleZerosCase() {
createChapter("Vol.001 Ch.003: Kaguya Doesn't Know Much")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(3f)
}
/**
* Chapter with version before number
*/
@Test fun chapterBeforeNumberCase() {
createManga("Onepunch-Man")
createChapter("Onepunch-Man Punch Ver002 086 : Creeping Darkness [3]")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(86f)
}
/**
* Case with version attached to chapter number
*/
@Test fun vAttachedToChapterCase() {
createManga("Ansatsu Kyoushitsu")
createChapter("Ansatsu Kyoushitsu 011v002: Assembly Time")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(11f)
}
/**
* Case where the chapter title contains the chapter
* But wait it's not actual the chapter number.
*/
@Test fun NumberAfterMangaTitleWithChapterInChapterTitleCase() {
createChapter("Tokyo ESP 027: Part 002: Chapter 001")
createManga("Tokyo ESP")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(027f)
}
/**
* unParsable chapter
*/
@Test fun unParsableCase() {
createChapter("Foo")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(-1f)
}
/**
* chapter with time in title
*/
@Test fun timeChapterCase() {
createChapter("Fairy Tail 404: 00:00")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404f)
}
/**
* chapter with alpha without dot
*/
@Test fun alphaWithoutDotCase() {
createChapter("Asu No Yoichi 19a")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(19.1f)
}
/**
* Chapter title containing extra and vol
*/
@Test fun chapterContainingExtraCase() {
createManga("Fairy Tail")
createChapter("Fairy Tail 404.extravol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.99f)
createChapter("Fairy Tail 404 extravol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.99f)
createChapter("Fairy Tail 404.evol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.5f)
}
/**
* Chapter title containing omake (japanese extra) and vol
*/
@Test fun chapterContainingOmakeCase() {
createManga("Fairy Tail")
createChapter("Fairy Tail 404.omakevol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.98f)
createChapter("Fairy Tail 404 omakevol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.98f)
createChapter("Fairy Tail 404.ovol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.15f)
}
/**
* Chapter title containing special and vol
*/
@Test fun chapterContainingSpecialCase() {
createManga("Fairy Tail")
createChapter("Fairy Tail 404.specialvol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.97f)
createChapter("Fairy Tail 404 specialvol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.97f)
createChapter("Fairy Tail 404.svol002")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(404.19f)
}
/**
* Chapter title containing comma's
*/
@Test fun chapterContainingCommasCase() {
createManga("One Piece")
createChapter("One Piece 300,a")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(300.1f)
createChapter("One Piece Ch,123,extra")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(123.99f)
createChapter("One Piece the sunny, goes swimming 024,005")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(24.005f)
}
/**
* Test for chapters containing season
*/
@Test fun chapterContainingSeasonCase() {
createManga("D.I.C.E")
createChapter("D.I.C.E[Season 001] Ep. 007")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(7f)
}
/**
* Test for chapters in format sx - chapter xx
*/
@Test fun chapterContainingSeasonCase2() {
createManga("The Gamer")
createChapter("S3 - Chapter 20")
ChapterRecognition.parseChapterNumber(chapter, manga)
assertThat(chapter.chapter_number).isEqualTo(20f)
}
}

View File

@@ -1,127 +0,0 @@
package eu.kanade.tachiyomi.data.library
import android.app.Application
import android.content.Context
import android.content.Intent
import android.os.Build
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.online.HttpSource
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Matchers.anyLong
import org.mockito.Mockito
import org.mockito.Mockito.*
import org.robolectric.Robolectric
import org.robolectric.RuntimeEnvironment
import org.robolectric.annotation.Config
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.InjektModule
import uy.kohesive.injekt.api.InjektRegistrar
import uy.kohesive.injekt.api.addSingleton
import java.util.*
@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
@RunWith(CustomRobolectricGradleTestRunner::class)
class LibraryUpdateServiceTest {
lateinit var app: Application
lateinit var context: Context
lateinit var service: LibraryUpdateService
lateinit var source: HttpSource
@Before
fun setup() {
app = RuntimeEnvironment.application
context = app.applicationContext
// Mock the source manager
val module = object : InjektModule {
override fun InjektRegistrar.registerInjectables() {
addSingleton(Mockito.mock(SourceManager::class.java, RETURNS_DEEP_STUBS))
}
}
Injekt.importModule(module)
service = Robolectric.setupService(LibraryUpdateService::class.java)
source = mock(HttpSource::class.java)
`when`(service.sourceManager.get(anyLong())).thenReturn(source)
}
@Test
fun testLifecycle() {
// Smoke test
Robolectric.buildService(LibraryUpdateService::class.java)
.attach()
.create()
.startCommand(0, 0)
.destroy()
.get()
}
@Test
fun testUpdateManga() {
val manga = createManga("/manga1")[0]
manga.id = 1L
service.db.insertManga(manga).executeAsBlocking()
val sourceChapters = createChapters("/chapter1", "/chapter2")
`when`(source.fetchChapterList(manga)).thenReturn(Observable.just(sourceChapters))
service.updateManga(manga).subscribe()
assertThat(service.db.getChapters(manga).executeAsBlocking()).hasSize(2)
}
@Test
fun testContinuesUpdatingWhenAMangaFails() {
var favManga = createManga("/manga1", "/manga2", "/manga3")
service.db.insertMangas(favManga).executeAsBlocking()
favManga = service.db.getFavoriteMangas().executeAsBlocking()
val chapters = createChapters("/chapter1", "/chapter2")
val chapters3 = createChapters("/achapter1", "/achapter2")
// One of the updates will fail
`when`(source.fetchChapterList(favManga[0])).thenReturn(Observable.just(chapters))
`when`(source.fetchChapterList(favManga[1])).thenReturn(Observable.error<List<SChapter>>(Exception()))
`when`(source.fetchChapterList(favManga[2])).thenReturn(Observable.just(chapters3))
val intent = Intent()
service.updateChapterList(service.getMangaToUpdate(intent)).subscribe()
// There are 3 network attempts and 2 insertions (1 request failed)
assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)
assertThat(service.db.getChapters(favManga[1]).executeAsBlocking()).hasSize(0)
assertThat(service.db.getChapters(favManga[2]).executeAsBlocking()).hasSize(2)
}
private fun createChapters(vararg urls: String): List<Chapter> {
val list = ArrayList<Chapter>()
for (url in urls) {
val c = Chapter.create()
c.url = url
c.name = url.substring(1)
list.add(c)
}
return list
}
private fun createManga(vararg urls: String): List<Manga> {
val list = ArrayList<Manga>()
for (url in urls) {
val m = Manga.create(url, url.substring(1))
m.favorite = true
list.add(m)
}
return list
}
}