mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Merge branch 'master' of https://github.com/inorichi/tachiyomi
# 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:
		@@ -1,8 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi
 | 
			
		||||
 | 
			
		||||
open class TestApp : App() {
 | 
			
		||||
 | 
			
		||||
    override fun setupAcra() {
 | 
			
		||||
        // Do nothing
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -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)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user