Unit tests for json (de)serialization
parent
2d4c1b751e
commit
9eb5e699e1
@ -0,0 +1,62 @@
|
||||
package org.koitharu.kotatsu.core.backup
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.json.getBooleanOrDefault
|
||||
import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
|
||||
class JsonDeserializer(private val json: JSONObject) {
|
||||
|
||||
fun toFavouriteEntity() = FavouriteEntity(
|
||||
mangaId = json.getLong("manga_id"),
|
||||
categoryId = json.getLong("category_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
)
|
||||
|
||||
fun toMangaEntity() = MangaEntity(
|
||||
id = json.getLong("id"),
|
||||
title = json.getString("title"),
|
||||
altTitle = json.getStringOrNull("alt_title"),
|
||||
url = json.getString("url"),
|
||||
publicUrl = json.getStringOrNull("public_url").orEmpty(),
|
||||
rating = json.getDouble("rating").toFloat(),
|
||||
isNsfw = json.getBooleanOrDefault("nsfw", false),
|
||||
coverUrl = json.getString("cover_url"),
|
||||
largeCoverUrl = json.getStringOrNull("large_cover_url"),
|
||||
state = json.getStringOrNull("state"),
|
||||
author = json.getStringOrNull("author"),
|
||||
source = json.getString("source")
|
||||
)
|
||||
|
||||
fun toTagEntity() = TagEntity(
|
||||
id = json.getLong("id"),
|
||||
title = json.getString("title"),
|
||||
key = json.getString("key"),
|
||||
source = json.getString("source")
|
||||
)
|
||||
|
||||
fun toHistoryEntity() = HistoryEntity(
|
||||
mangaId = json.getLong("manga_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
updatedAt = json.getLong("updated_at"),
|
||||
chapterId = json.getLong("chapter_id"),
|
||||
page = json.getInt("page"),
|
||||
scroll = json.getDouble("scroll").toFloat(),
|
||||
percent = json.getFloatOrDefault("percent", -1f),
|
||||
)
|
||||
|
||||
fun toFavouriteCategoryEntity() = FavouriteCategoryEntity(
|
||||
categoryId = json.getInt("category_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
sortKey = json.getInt("sort_key"),
|
||||
title = json.getString("title"),
|
||||
order = json.getStringOrNull("order") ?: SortOrder.NEWEST.name,
|
||||
track = json.getBooleanOrDefault("track", true),
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package org.koitharu.kotatsu.core.backup
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
|
||||
class JsonSerializer private constructor(private val json: JSONObject) {
|
||||
|
||||
constructor(e: FavouriteEntity) : this(
|
||||
JSONObject().apply {
|
||||
put("manga_id", e.mangaId)
|
||||
put("category_id", e.categoryId)
|
||||
put("created_at", e.createdAt)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(e: FavouriteCategoryEntity) : this(
|
||||
JSONObject().apply {
|
||||
put("category_id", e.categoryId)
|
||||
put("created_at", e.createdAt)
|
||||
put("sort_key", e.sortKey)
|
||||
put("title", e.title)
|
||||
put("order", e.order)
|
||||
put("track", e.track)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(e: HistoryEntity) : this(
|
||||
JSONObject().apply {
|
||||
put("manga_id", e.mangaId)
|
||||
put("created_at", e.createdAt)
|
||||
put("updated_at", e.updatedAt)
|
||||
put("chapter_id", e.chapterId)
|
||||
put("page", e.page)
|
||||
put("scroll", e.scroll)
|
||||
put("percent", e.percent)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(e: TagEntity) : this(
|
||||
JSONObject().apply {
|
||||
put("id", e.id)
|
||||
put("title", e.title)
|
||||
put("key", e.key)
|
||||
put("source", e.source)
|
||||
}
|
||||
)
|
||||
|
||||
constructor(e: MangaEntity) : this(
|
||||
JSONObject().apply {
|
||||
put("id", e.id)
|
||||
put("title", e.title)
|
||||
put("alt_title", e.altTitle)
|
||||
put("url", e.url)
|
||||
put("public_url", e.publicUrl)
|
||||
put("rating", e.rating)
|
||||
put("nsfw", e.isNsfw)
|
||||
put("cover_url", e.coverUrl)
|
||||
put("large_cover_url", e.largeCoverUrl)
|
||||
put("state", e.state)
|
||||
put("author", e.author)
|
||||
put("source", e.source)
|
||||
}
|
||||
)
|
||||
|
||||
fun toJson(): JSONObject = json
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
package org.koitharu.kotatsu.core.backup
|
||||
|
||||
import androidx.room.withTransaction
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.json.*
|
||||
|
||||
class RestoreRepository(private val db: MangaDatabase) {
|
||||
|
||||
suspend fun upsertHistory(entry: BackupEntry): CompositeResult {
|
||||
val result = CompositeResult()
|
||||
for (item in entry.data.JSONIterator()) {
|
||||
val mangaJson = item.getJSONObject("manga")
|
||||
val manga = parseManga(mangaJson)
|
||||
val tags = mangaJson.getJSONArray("tags").mapJSON {
|
||||
parseTag(it)
|
||||
}
|
||||
val history = parseHistory(item)
|
||||
result += runCatching {
|
||||
db.withTransaction {
|
||||
db.tagsDao.upsert(tags)
|
||||
db.mangaDao.upsert(manga, tags)
|
||||
db.historyDao.upsert(history)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun upsertCategories(entry: BackupEntry): CompositeResult {
|
||||
val result = CompositeResult()
|
||||
for (item in entry.data.JSONIterator()) {
|
||||
val category = parseCategory(item)
|
||||
result += runCatching {
|
||||
db.favouriteCategoriesDao.upsert(category)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
suspend fun upsertFavourites(entry: BackupEntry): CompositeResult {
|
||||
val result = CompositeResult()
|
||||
for (item in entry.data.JSONIterator()) {
|
||||
val mangaJson = item.getJSONObject("manga")
|
||||
val manga = parseManga(mangaJson)
|
||||
val tags = mangaJson.getJSONArray("tags").mapJSON {
|
||||
parseTag(it)
|
||||
}
|
||||
val favourite = parseFavourite(item)
|
||||
result += runCatching {
|
||||
db.withTransaction {
|
||||
db.tagsDao.upsert(tags)
|
||||
db.mangaDao.upsert(manga, tags)
|
||||
db.favouritesDao.upsert(favourite)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun parseManga(json: JSONObject) = MangaEntity(
|
||||
id = json.getLong("id"),
|
||||
title = json.getString("title"),
|
||||
altTitle = json.getStringOrNull("alt_title"),
|
||||
url = json.getString("url"),
|
||||
publicUrl = json.getStringOrNull("public_url").orEmpty(),
|
||||
rating = json.getDouble("rating").toFloat(),
|
||||
isNsfw = json.getBooleanOrDefault("nsfw", false),
|
||||
coverUrl = json.getString("cover_url"),
|
||||
largeCoverUrl = json.getStringOrNull("large_cover_url"),
|
||||
state = json.getStringOrNull("state"),
|
||||
author = json.getStringOrNull("author"),
|
||||
source = json.getString("source")
|
||||
)
|
||||
|
||||
private fun parseTag(json: JSONObject) = TagEntity(
|
||||
id = json.getLong("id"),
|
||||
title = json.getString("title"),
|
||||
key = json.getString("key"),
|
||||
source = json.getString("source")
|
||||
)
|
||||
|
||||
private fun parseHistory(json: JSONObject) = HistoryEntity(
|
||||
mangaId = json.getLong("manga_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
updatedAt = json.getLong("updated_at"),
|
||||
chapterId = json.getLong("chapter_id"),
|
||||
page = json.getInt("page"),
|
||||
scroll = json.getDouble("scroll").toFloat(),
|
||||
percent = json.getFloatOrDefault("percent", -1f),
|
||||
)
|
||||
|
||||
private fun parseCategory(json: JSONObject) = FavouriteCategoryEntity(
|
||||
categoryId = json.getInt("category_id"),
|
||||
createdAt = json.getLong("created_at"),
|
||||
sortKey = json.getInt("sort_key"),
|
||||
title = json.getString("title"),
|
||||
order = json.getStringOrNull("order") ?: SortOrder.NEWEST.name,
|
||||
track = json.getBooleanOrDefault("track", true),
|
||||
)
|
||||
|
||||
private fun parseFavourite(json: JSONObject) = FavouriteEntity(
|
||||
mangaId = json.getLong("manga_id"),
|
||||
categoryId = json.getLong("category_id"),
|
||||
createdAt = json.getLong("created_at")
|
||||
)
|
||||
}
|
||||
@ -0,0 +1,93 @@
|
||||
package org.koitharu.kotatsu.core.backup
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.favourites.data.FavouriteEntity
|
||||
import org.koitharu.kotatsu.history.data.HistoryEntity
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class JsonSerializerTest {
|
||||
|
||||
@Test
|
||||
fun toFavouriteEntity() {
|
||||
val entity = FavouriteEntity(
|
||||
mangaId = 40,
|
||||
categoryId = 20,
|
||||
createdAt = System.currentTimeMillis(),
|
||||
)
|
||||
val json = JsonSerializer(entity).toJson()
|
||||
val result = JsonDeserializer(json).toFavouriteEntity()
|
||||
assertEquals(entity, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toMangaEntity() {
|
||||
val entity = MangaEntity(
|
||||
id = 231,
|
||||
title = "Lorem Ipsum",
|
||||
altTitle = "Lorem Ispum 2",
|
||||
url = "erw",
|
||||
publicUrl = "hthth",
|
||||
rating = 0.78f,
|
||||
isNsfw = true,
|
||||
coverUrl = "5345",
|
||||
largeCoverUrl = null,
|
||||
state = MangaState.FINISHED.name,
|
||||
author = "RERE",
|
||||
source = MangaSource.DUMMY.name,
|
||||
)
|
||||
val json = JsonSerializer(entity).toJson()
|
||||
val result = JsonDeserializer(json).toMangaEntity()
|
||||
assertEquals(entity, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toTagEntity() {
|
||||
val entity = TagEntity(
|
||||
id = 934023534,
|
||||
title = "Adventure",
|
||||
key = "adventure",
|
||||
source = MangaSource.DUMMY.name,
|
||||
)
|
||||
val json = JsonSerializer(entity).toJson()
|
||||
val result = JsonDeserializer(json).toTagEntity()
|
||||
assertEquals(entity, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toHistoryEntity() {
|
||||
val entity = HistoryEntity(
|
||||
mangaId = 304135341,
|
||||
createdAt = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(6),
|
||||
updatedAt = System.currentTimeMillis(),
|
||||
chapterId = 29014843034,
|
||||
page = 35,
|
||||
scroll = 24.0f,
|
||||
percent = 0.6f,
|
||||
)
|
||||
val json = JsonSerializer(entity).toJson()
|
||||
val result = JsonDeserializer(json).toHistoryEntity()
|
||||
assertEquals(entity, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun toFavouriteCategoryEntity() {
|
||||
val entity = FavouriteCategoryEntity(
|
||||
categoryId = 142,
|
||||
createdAt = System.currentTimeMillis(),
|
||||
sortKey = 14,
|
||||
title = "Read later",
|
||||
order = SortOrder.RATING.name,
|
||||
track = false,
|
||||
)
|
||||
val json = JsonSerializer(entity).toJson()
|
||||
val result = JsonDeserializer(json).toFavouriteCategoryEntity()
|
||||
assertEquals(entity, result)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue