mirror of
https://github.com/gotson/komga.git
synced 2026-05-08 21:00:16 +02:00
rename serie to series and other polish
This commit is contained in:
parent
17ee332ad8
commit
397b7b1952
20 changed files with 303 additions and 286 deletions
|
|
@ -37,8 +37,8 @@ class Book(
|
|||
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "serie_id", nullable = false)
|
||||
lateinit var serie: Serie
|
||||
@JoinColumn(name = "series_id", nullable = false)
|
||||
lateinit var series: Series
|
||||
|
||||
@OneToOne(optional = false, orphanRemoval = true, cascade = [CascadeType.ALL], fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "book_metadata_id", nullable = false)
|
||||
|
|
@ -51,4 +51,4 @@ class Book(
|
|||
override fun toString(): String = url.toURI().path
|
||||
}
|
||||
|
||||
fun Book.path(): Path = Paths.get(this.url.toURI())
|
||||
fun Book.path(): Path = Paths.get(this.url.toURI())
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ import javax.validation.constraints.NotNull
|
|||
private val natSortComparator: Comparator<String> = CaseInsensitiveSimpleNaturalComparator.getInstance()
|
||||
|
||||
@Entity
|
||||
@Table(name = "serie")
|
||||
class Serie(
|
||||
@Table(name = "series")
|
||||
class Series(
|
||||
@NotBlank
|
||||
@Column(name = "name", nullable = false)
|
||||
var name: String,
|
||||
|
|
@ -46,7 +46,7 @@ class Serie(
|
|||
@JoinColumn(name = "library_id", nullable = false)
|
||||
lateinit var library: Library
|
||||
|
||||
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "serie")
|
||||
@OneToMany(cascade = [CascadeType.ALL], fetch = FetchType.LAZY, orphanRemoval = true, mappedBy = "series")
|
||||
@OrderColumn(name = "index")
|
||||
private var _books: MutableList<Book> = mutableListOf()
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class Serie(
|
|||
get() = _books.toList()
|
||||
set(value) {
|
||||
_books.clear()
|
||||
value.forEach { it.serie = this }
|
||||
value.forEach { it.series = this }
|
||||
_books.addAll(value.sortedWith(compareBy(natSortComparator) { it.name }))
|
||||
}
|
||||
|
||||
|
|
@ -63,4 +63,4 @@ class Serie(
|
|||
}
|
||||
|
||||
override fun toString(): String = url.toURI().path
|
||||
}
|
||||
}
|
||||
|
|
@ -12,19 +12,19 @@ import java.net.URL
|
|||
@Repository
|
||||
interface BookRepository : JpaRepository<Book, Long> {
|
||||
@Query(
|
||||
value = "select * from Book b where b.serie_id = ?1 order by b.index",
|
||||
countQuery = "select count(*) from Book where serie_id = ?1",
|
||||
value = "select * from Book b where b.series_id = ?1 order by b.index",
|
||||
countQuery = "select count(*) from Book where series_id = ?1",
|
||||
nativeQuery = true)
|
||||
fun findAllBySerieId(serieId: Long, pageable: Pageable): Page<Book>
|
||||
fun findAllBySeriesId(seriesId: Long, pageable: Pageable): Page<Book>
|
||||
|
||||
@Query(
|
||||
value = "select * from Book b, Book_Metadata m where b.book_metadata_id = m.id " +
|
||||
"and b.serie_id = ?2 and m.status = ?1 order by b.index",
|
||||
countQuery = "select count(*) from Book b, Book_Metadata m where b.book_metadata_id = m.id and b.serie_id = ?2 and m.status = ?1",
|
||||
"and b.series_id = ?2 and m.status = ?1 order by b.index",
|
||||
countQuery = "select count(*) from Book b, Book_Metadata m where b.book_metadata_id = m.id and b.series_id = ?2 and m.status = ?1",
|
||||
nativeQuery = true)
|
||||
fun findAllByMetadataStatusAndSerieId(status: String, serieId: Long, pageable: Pageable): Page<Book>
|
||||
fun findAllByMetadataStatusAndSeriesId(status: String, seriesId: Long, pageable: Pageable): Page<Book>
|
||||
|
||||
fun findByUrl(url: URL): Book?
|
||||
fun findAllByMetadataStatus(status: Status): List<Book>
|
||||
fun findAllByMetadataThumbnailIsNull(): List<Book>
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
package org.gotson.komga.domain.persistence
|
||||
|
||||
import org.gotson.komga.domain.model.Serie
|
||||
import org.gotson.komga.domain.model.Series
|
||||
import org.springframework.data.jpa.repository.JpaRepository
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.net.URL
|
||||
|
||||
@Repository
|
||||
interface SerieRepository : JpaRepository<Serie, Long>, JpaSpecificationExecutor<Serie> {
|
||||
fun findByLibraryIdAndUrlNotIn(libraryId: Long, urls: Iterable<URL>): List<Serie>
|
||||
fun findByLibraryIdAndUrl(libraryId: Long, url: URL): Serie?
|
||||
interface SeriesRepository : JpaRepository<Series, Long>, JpaSpecificationExecutor<Series> {
|
||||
fun findByLibraryIdAndUrlNotIn(libraryId: Long, urls: Iterable<URL>): List<Series>
|
||||
fun findByLibraryIdAndUrl(libraryId: Long, url: URL): Series?
|
||||
fun deleteByLibraryId(libraryId: Long)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ class AsyncOrchestrator(
|
|||
private val libraryScanner: LibraryScanner,
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val bookRepository: BookRepository,
|
||||
private val bookLifecyle: BookLifecyle
|
||||
private val bookLifecycle: BookLifecycle
|
||||
) {
|
||||
|
||||
@Async("periodicScanTaskExecutor")
|
||||
|
|
@ -52,7 +52,7 @@ class AsyncOrchestrator(
|
|||
var sumOfTasksTime = 0L
|
||||
measureTimeMillis {
|
||||
sumOfTasksTime = books
|
||||
.map { bookLifecyle.regenerateThumbnailAndPersist(it) }
|
||||
.map { bookLifecycle.regenerateThumbnailAndPersist(it) }
|
||||
.map {
|
||||
try {
|
||||
it.get()
|
||||
|
|
@ -65,4 +65,4 @@ class AsyncOrchestrator(
|
|||
logger.info { "Generated ${books.size} thumbnails in ${DurationFormatUtils.formatDurationHMS(it)} (virtual: ${DurationFormatUtils.formatDurationHMS(sumOfTasksTime)})" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import kotlin.system.measureTimeMillis
|
|||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
@Service
|
||||
class BookLifecyle(
|
||||
class BookLifecycle(
|
||||
private val bookRepository: BookRepository,
|
||||
private val bookParser: BookParser,
|
||||
private val imageConverter: ImageConverter
|
||||
|
|
@ -89,4 +89,4 @@ class BookLifecyle(
|
|||
|
||||
return BookPageContent(number, pageContent, pageMediaType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import mu.KotlinLogging
|
|||
import org.apache.commons.io.FilenameUtils
|
||||
import org.apache.commons.lang3.time.DurationFormatUtils
|
||||
import org.gotson.komga.domain.model.Book
|
||||
import org.gotson.komga.domain.model.Serie
|
||||
import org.gotson.komga.domain.model.Series
|
||||
import org.springframework.stereotype.Service
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
|
@ -23,11 +23,11 @@ class FileSystemScanner {
|
|||
|
||||
val supportedExtensions = listOf("cbz", "zip", "cbr", "rar", "pdf")
|
||||
|
||||
fun scanRootFolder(root: Path): List<Serie> {
|
||||
fun scanRootFolder(root: Path): List<Series> {
|
||||
logger.info { "Scanning folder: $root" }
|
||||
logger.info { "Supported extensions: $supportedExtensions" }
|
||||
|
||||
lateinit var scannedSeries: List<Serie>
|
||||
lateinit var scannedSeries: List<Series>
|
||||
|
||||
measureTimeMillis {
|
||||
scannedSeries = Files.walk(root).use { dirsStream ->
|
||||
|
|
@ -47,7 +47,7 @@ class FileSystemScanner {
|
|||
}.toList()
|
||||
}
|
||||
if (books.isNullOrEmpty()) return@mapNotNull null
|
||||
Serie(
|
||||
Series(
|
||||
name = dir.fileName.toString(),
|
||||
url = dir.toUri().toURL(),
|
||||
fileLastModified = dir.getUpdatedTime(),
|
||||
|
|
@ -70,4 +70,4 @@ fun Path.getUpdatedTime(): LocalDateTime =
|
|||
}
|
||||
|
||||
fun FileTime.toLocalDateTime(): LocalDateTime =
|
||||
LocalDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault())
|
||||
LocalDateTime.ofInstant(this.toInstant(), ZoneId.systemDefault())
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import org.gotson.komga.domain.model.Library
|
|||
import org.gotson.komga.domain.model.PathContainedInPath
|
||||
import org.gotson.komga.domain.model.path
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.io.FileNotFoundException
|
||||
|
|
@ -19,7 +19,7 @@ private val logger = KotlinLogging.logger {}
|
|||
@Service
|
||||
class LibraryLifecycle(
|
||||
private val libraryRepository: LibraryRepository,
|
||||
private val serieRepository: SerieRepository,
|
||||
private val seriesRepository: SeriesRepository,
|
||||
private val asyncOrchestrator: AsyncOrchestrator
|
||||
) {
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ class LibraryLifecycle(
|
|||
@Transactional
|
||||
fun deleteLibrary(library: Library) {
|
||||
logger.info { "Deleting library: ${library.name} with root folder: ${library.root}" }
|
||||
serieRepository.deleteByLibraryId(library.id)
|
||||
seriesRepository.deleteByLibraryId(library.id)
|
||||
libraryRepository.delete(library)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import org.apache.commons.lang3.time.DurationFormatUtils
|
|||
import org.gotson.komga.domain.model.Library
|
||||
import org.gotson.komga.domain.model.Status
|
||||
import org.gotson.komga.domain.persistence.BookRepository
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.springframework.stereotype.Service
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import java.nio.file.Paths
|
||||
|
|
@ -16,46 +16,46 @@ private val logger = KotlinLogging.logger {}
|
|||
@Service
|
||||
class LibraryScanner(
|
||||
private val fileSystemScanner: FileSystemScanner,
|
||||
private val serieRepository: SerieRepository,
|
||||
private val seriesRepository: SeriesRepository,
|
||||
private val bookRepository: BookRepository,
|
||||
private val bookLifecyle: BookLifecyle
|
||||
private val bookLifecycle: BookLifecycle
|
||||
) {
|
||||
|
||||
@Transactional
|
||||
fun scanRootFolder(library: Library) {
|
||||
logger.info { "Updating library: ${library.name}, root folder: ${library.root}" }
|
||||
measureTimeMillis {
|
||||
val series = fileSystemScanner.scanRootFolder(Paths.get(library.root.toURI()))
|
||||
val scannedSeries = fileSystemScanner.scanRootFolder(Paths.get(library.root.toURI()))
|
||||
|
||||
// delete series that don't exist anymore
|
||||
if (series.isEmpty()) {
|
||||
if (scannedSeries.isEmpty()) {
|
||||
logger.info { "Scan returned no series, deleting all existing series" }
|
||||
serieRepository.deleteByLibraryId(library.id)
|
||||
seriesRepository.deleteByLibraryId(library.id)
|
||||
} else {
|
||||
series.map { it.url }.let { urls ->
|
||||
serieRepository.findByLibraryIdAndUrlNotIn(library.id, urls).forEach {
|
||||
logger.info { "Deleting serie not on disk anymore: $it" }
|
||||
serieRepository.delete(it)
|
||||
scannedSeries.map { it.url }.let { urls ->
|
||||
seriesRepository.findByLibraryIdAndUrlNotIn(library.id, urls).forEach {
|
||||
logger.info { "Deleting series not on disk anymore: $it" }
|
||||
seriesRepository.delete(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
series.forEach { newSerie ->
|
||||
val existingSerie = serieRepository.findByLibraryIdAndUrl(library.id, newSerie.url)
|
||||
scannedSeries.forEach { newSeries ->
|
||||
val existingSeries = seriesRepository.findByLibraryIdAndUrl(library.id, newSeries.url)
|
||||
|
||||
// if serie does not exist, save it
|
||||
if (existingSerie == null) {
|
||||
logger.info { "Adding new serie: $newSerie" }
|
||||
serieRepository.save(newSerie.also { it.library = library })
|
||||
// if series does not exist, save it
|
||||
if (existingSeries == null) {
|
||||
logger.info { "Adding new series: $newSeries" }
|
||||
seriesRepository.save(newSeries.also { it.library = library })
|
||||
} else {
|
||||
// if serie already exists, update it
|
||||
if (newSerie.fileLastModified != existingSerie.fileLastModified) {
|
||||
logger.info { "Serie changed on disk, updating: $newSerie" }
|
||||
existingSerie.name = newSerie.name
|
||||
existingSerie.fileLastModified = newSerie.fileLastModified
|
||||
// if series already exists, update it
|
||||
if (newSeries.fileLastModified != existingSeries.fileLastModified) {
|
||||
logger.info { "Series changed on disk, updating: $newSeries" }
|
||||
existingSeries.name = newSeries.name
|
||||
existingSeries.fileLastModified = newSeries.fileLastModified
|
||||
|
||||
// update list of books with existing entities if they exist
|
||||
existingSerie.books = newSerie.books.map { newBook ->
|
||||
existingSeries.books = newSeries.books.map { newBook ->
|
||||
val existingBook = bookRepository.findByUrl(newBook.url) ?: newBook
|
||||
|
||||
if (newBook.fileLastModified != existingBook.fileLastModified) {
|
||||
|
|
@ -67,7 +67,7 @@ class LibraryScanner(
|
|||
existingBook
|
||||
}.toMutableList()
|
||||
|
||||
serieRepository.save(existingSerie)
|
||||
seriesRepository.save(existingSeries)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ class LibraryScanner(
|
|||
var sumOfTasksTime = 0L
|
||||
measureTimeMillis {
|
||||
sumOfTasksTime = booksToParse
|
||||
.map { bookLifecyle.parseAndPersist(it) }
|
||||
.map { bookLifecycle.parseAndPersist(it) }
|
||||
.map {
|
||||
try {
|
||||
it.get()
|
||||
|
|
@ -96,4 +96,4 @@ class LibraryScanner(
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ package org.gotson.komga.interfaces.web.opds
|
|||
|
||||
import com.github.klinq.jpaspec.likeLower
|
||||
import org.gotson.komga.domain.model.Book
|
||||
import org.gotson.komga.domain.model.Serie
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.model.Series
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.gotson.komga.interfaces.web.opds.dto.OpdsAuthor
|
||||
import org.gotson.komga.interfaces.web.opds.dto.OpdsEntryAcquisition
|
||||
import org.gotson.komga.interfaces.web.opds.dto.OpdsEntryNavigation
|
||||
|
|
@ -44,7 +44,7 @@ private const val ID_SERIES_LATEST = "latestSeries"
|
|||
@RestController
|
||||
@RequestMapping(value = [ROUTE_BASE], produces = [MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE])
|
||||
class OpdsController(
|
||||
private val serieRepository: SerieRepository
|
||||
private val seriesRepository: SeriesRepository
|
||||
) {
|
||||
|
||||
private val komgaAuthor = OpdsAuthor("Komga", URI("https://github.com/gotson/komga"))
|
||||
|
|
@ -86,10 +86,10 @@ class OpdsController(
|
|||
): OpdsFeed {
|
||||
val sort = Sort.by(Sort.Order.asc("name").ignoreCase())
|
||||
val series = if (!searchTerm.isNullOrEmpty()) {
|
||||
val spec = Serie::name.likeLower("%$searchTerm%")
|
||||
serieRepository.findAll(spec, sort)
|
||||
val spec = Series::name.likeLower("%$searchTerm%")
|
||||
seriesRepository.findAll(spec, sort)
|
||||
} else {
|
||||
serieRepository.findAll(sort)
|
||||
seriesRepository.findAll(sort)
|
||||
}
|
||||
|
||||
return OpdsFeedNavigation(
|
||||
|
|
@ -107,7 +107,7 @@ class OpdsController(
|
|||
|
||||
@GetMapping(ROUTE_SERIES_LATEST)
|
||||
fun getLatestSeries(): OpdsFeed {
|
||||
val series = serieRepository.findAll(Sort(Sort.Direction.DESC, "lastModifiedDate"))
|
||||
val series = seriesRepository.findAll(Sort(Sort.Direction.DESC, "lastModifiedDate"))
|
||||
return OpdsFeedNavigation(
|
||||
id = ID_SERIES_LATEST,
|
||||
title = "Latest series",
|
||||
|
|
@ -122,24 +122,24 @@ class OpdsController(
|
|||
}
|
||||
|
||||
@GetMapping("series/{id}")
|
||||
fun getOneSerie(
|
||||
fun getOneSeries(
|
||||
@PathVariable id: Long
|
||||
): OpdsFeed =
|
||||
serieRepository.findByIdOrNull(id)?.let {
|
||||
seriesRepository.findByIdOrNull(id)?.let { series ->
|
||||
OpdsFeedAcquisition(
|
||||
id = it.id.toString(),
|
||||
title = it.name,
|
||||
updated = it.lastModifiedDate?.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
id = series.id.toString(),
|
||||
title = series.name,
|
||||
updated = series.lastModifiedDate?.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
author = komgaAuthor,
|
||||
links = listOf(
|
||||
OpdsLinkFeedNavigation(OpdsLinkRel.SELF, "${ROUTE_BASE}series/$id"),
|
||||
linkStart
|
||||
),
|
||||
entries = it.books.map { it.toOpdsEntry() }
|
||||
entries = series.books.map { it.toOpdsEntry() }
|
||||
)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
private fun Serie.toOpdsEntry() =
|
||||
private fun Series.toOpdsEntry() =
|
||||
OpdsEntryNavigation(
|
||||
title = name,
|
||||
updated = lastModifiedDate?.atZone(ZoneId.systemDefault()) ?: ZonedDateTime.now(),
|
||||
|
|
@ -155,11 +155,11 @@ class OpdsController(
|
|||
id = id.toString(),
|
||||
content = "",
|
||||
links = listOf(
|
||||
OpdsLinkImageThumbnail("image/png", "/api/v1/series/${serie.id}/books/$id/thumbnail"),
|
||||
OpdsLinkImage(metadata.pages[0].mediaType, "/api/v1/series/${serie.id}/books/$id/pages/1"),
|
||||
OpdsLinkImageThumbnail("image/png", "/api/v1/series/${series.id}/books/$id/thumbnail"),
|
||||
OpdsLinkImage(metadata.pages[0].mediaType, "/api/v1/series/${series.id}/books/$id/pages/1"),
|
||||
OpdsLinkFileAcquisition(metadata.mediaType
|
||||
?: "application/octet-stream", "/api/v1/series/${serie.id}/books/$id/file"),
|
||||
OpdsLinkPageStreaming("image/jpeg", "/api/v1/series/${serie.id}/books/$id/pages/{pageNumber}?convert=jpeg&zerobased=true", metadata.pages.size)
|
||||
?: "application/octet-stream", "/api/v1/series/${series.id}/books/$id/file"),
|
||||
OpdsLinkPageStreaming("image/jpeg", "/api/v1/series/${series.id}/books/$id/pages/{pageNumber}?convert=jpeg&zerobased=true", metadata.pages.size)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ class OpdsLinkPageStreaming(
|
|||
|
||||
class OpdsLinkRel {
|
||||
companion object {
|
||||
val SELF = "self"
|
||||
val START = "start"
|
||||
val SUBSECTION = "subsection"
|
||||
val SORT_NEW = "http://opds-spec.org/sort/new"
|
||||
val SORT_POPULAR = "http://opds-spec.org/sort/popular"
|
||||
const val SELF = "self"
|
||||
const val START = "start"
|
||||
const val SUBSECTION = "subsection"
|
||||
const val SORT_NEW = "http://opds-spec.org/sort/new"
|
||||
const val SORT_POPULAR = "http://opds-spec.org/sort/popular"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import mu.KotlinLogging
|
|||
import org.apache.commons.io.FilenameUtils
|
||||
import org.gotson.komga.domain.model.Book
|
||||
import org.gotson.komga.domain.model.MetadataNotReadyException
|
||||
import org.gotson.komga.domain.model.Serie
|
||||
import org.gotson.komga.domain.model.Series
|
||||
import org.gotson.komga.domain.model.Status
|
||||
import org.gotson.komga.domain.model.UnsupportedMediaTypeException
|
||||
import org.gotson.komga.domain.persistence.BookRepository
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.service.BookLifecyle
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.gotson.komga.domain.service.BookLifecycle
|
||||
import org.gotson.komga.infrastructure.image.ImageType
|
||||
import org.springframework.data.domain.Page
|
||||
import org.springframework.data.domain.PageRequest
|
||||
|
|
@ -40,10 +40,10 @@ private val logger = KotlinLogging.logger {}
|
|||
|
||||
@RestController
|
||||
@RequestMapping("api/v1/series", produces = [MediaType.APPLICATION_JSON_VALUE])
|
||||
class SerieController(
|
||||
private val serieRepository: SerieRepository,
|
||||
class SeriesController(
|
||||
private val seriesRepository: SeriesRepository,
|
||||
private val bookRepository: BookRepository,
|
||||
private val bookLifecyle: BookLifecyle
|
||||
private val bookLifecycle: BookLifecycle
|
||||
) {
|
||||
|
||||
@GetMapping
|
||||
|
|
@ -52,7 +52,7 @@ class SerieController(
|
|||
searchTerm: String?,
|
||||
|
||||
page: Pageable
|
||||
): Page<SerieDto> {
|
||||
): Page<SeriesDto> {
|
||||
val pageRequest = PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
|
|
@ -60,81 +60,81 @@ class SerieController(
|
|||
else Sort.by(Sort.Order.asc("name").ignoreCase())
|
||||
)
|
||||
return if (!searchTerm.isNullOrEmpty()) {
|
||||
val spec = Serie::name.likeLower("%$searchTerm%")
|
||||
serieRepository.findAll(spec, pageRequest)
|
||||
val spec = Series::name.likeLower("%$searchTerm%")
|
||||
seriesRepository.findAll(spec, pageRequest)
|
||||
} else {
|
||||
serieRepository.findAll(pageRequest)
|
||||
seriesRepository.findAll(pageRequest)
|
||||
}.map { it.toDto() }
|
||||
}
|
||||
|
||||
@GetMapping("/latest")
|
||||
fun getLatestSeries(
|
||||
page: Pageable
|
||||
): Page<SerieDto> {
|
||||
): Page<SeriesDto> {
|
||||
val pageRequest = PageRequest.of(
|
||||
page.pageNumber,
|
||||
page.pageSize,
|
||||
Sort(Sort.Direction.DESC, "lastModifiedDate")
|
||||
)
|
||||
return serieRepository.findAll(pageRequest).map { it.toDto() }
|
||||
return seriesRepository.findAll(pageRequest).map { it.toDto() }
|
||||
}
|
||||
|
||||
@GetMapping("{id}")
|
||||
fun getOneSerie(
|
||||
fun getOneSeries(
|
||||
@PathVariable id: Long
|
||||
): SerieDto =
|
||||
serieRepository.findByIdOrNull(id)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
): SeriesDto =
|
||||
seriesRepository.findByIdOrNull(id)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
@GetMapping(value = ["{serieId}/thumbnail"], produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun getSerieThumbnail(
|
||||
@PathVariable serieId: Long
|
||||
@GetMapping(value = ["{seriesId}/thumbnail"], produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun getSeriesThumbnail(
|
||||
@PathVariable seriesId: Long
|
||||
): ByteArray {
|
||||
return serieRepository.findByIdOrNull(serieId)?.let {
|
||||
return seriesRepository.findByIdOrNull(seriesId)?.let {
|
||||
it.books.firstOrNull()?.metadata?.thumbnail ?: throw ResponseStatusException(HttpStatus.NO_CONTENT)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
@GetMapping("{id}/books")
|
||||
fun getAllBooksBySerie(
|
||||
fun getAllBooksBySeries(
|
||||
@PathVariable id: Long,
|
||||
@RequestParam(value = "readyonly", defaultValue = "true") readyFilter: Boolean,
|
||||
page: Pageable
|
||||
): Page<BookDto> {
|
||||
if (!serieRepository.existsById(id)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(id)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
return if (readyFilter) {
|
||||
bookRepository.findAllByMetadataStatusAndSerieId(Status.READY.name, id, page)
|
||||
bookRepository.findAllByMetadataStatusAndSeriesId(Status.READY.name, id, page)
|
||||
} else {
|
||||
bookRepository.findAllBySerieId(id, page)
|
||||
bookRepository.findAllBySeriesId(id, page)
|
||||
}.map { it.toDto() }
|
||||
}
|
||||
|
||||
@GetMapping("{serieId}/books/{bookId}")
|
||||
@GetMapping("{seriesId}/books/{bookId}")
|
||||
fun getOneBook(
|
||||
@PathVariable serieId: Long,
|
||||
@PathVariable seriesId: Long,
|
||||
@PathVariable bookId: Long
|
||||
): BookDto {
|
||||
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(seriesId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
return bookRepository.findByIdOrNull(bookId)?.toDto() ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
@GetMapping(value = ["{serieId}/books/{bookId}/thumbnail"], produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
@GetMapping(value = ["{seriesId}/books/{bookId}/thumbnail"], produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun getBookThumbnail(
|
||||
@PathVariable serieId: Long,
|
||||
@PathVariable seriesId: Long,
|
||||
@PathVariable bookId: Long
|
||||
): ByteArray {
|
||||
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(seriesId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
return bookRepository.findByIdOrNull(bookId)?.let {
|
||||
it.metadata.thumbnail ?: throw ResponseStatusException(HttpStatus.NO_CONTENT)
|
||||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
@GetMapping("{serieId}/books/{bookId}/file")
|
||||
@GetMapping("{seriesId}/books/{bookId}/file")
|
||||
fun getBookFile(
|
||||
@PathVariable serieId: Long,
|
||||
@PathVariable seriesId: Long,
|
||||
@PathVariable bookId: Long
|
||||
): ResponseEntity<ByteArray> {
|
||||
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(seriesId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
return bookRepository.findByIdOrNull(bookId)?.let { book ->
|
||||
try {
|
||||
ResponseEntity.ok()
|
||||
|
|
@ -152,12 +152,12 @@ class SerieController(
|
|||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
@GetMapping("{serieId}/books/{bookId}/pages")
|
||||
@GetMapping("{seriesId}/books/{bookId}/pages")
|
||||
fun getBookPages(
|
||||
@PathVariable serieId: Long,
|
||||
@PathVariable seriesId: Long,
|
||||
@PathVariable bookId: Long
|
||||
): List<PageDto> {
|
||||
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(seriesId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
return bookRepository.findByIdOrNull((bookId))?.let {
|
||||
if (it.metadata.status == Status.UNKNOWN) throw ResponseStatusException(HttpStatus.NO_CONTENT, "Book is not parsed yet")
|
||||
|
|
@ -167,15 +167,15 @@ class SerieController(
|
|||
} ?: throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
}
|
||||
|
||||
@GetMapping("{serieId}/books/{bookId}/pages/{pageNumber}")
|
||||
@GetMapping("{seriesId}/books/{bookId}/pages/{pageNumber}")
|
||||
fun getBookPage(
|
||||
@PathVariable serieId: Long,
|
||||
@PathVariable seriesId: Long,
|
||||
@PathVariable bookId: Long,
|
||||
@PathVariable pageNumber: Int,
|
||||
@RequestParam(value = "convert") convertTo: String?,
|
||||
@RequestParam(value = "zerobased", defaultValue = "false") zeroBasedIndex: Boolean
|
||||
): ResponseEntity<ByteArray> {
|
||||
if (!serieRepository.existsById(serieId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
if (!seriesRepository.existsById(seriesId)) throw ResponseStatusException(HttpStatus.NOT_FOUND)
|
||||
|
||||
return bookRepository.findByIdOrNull((bookId))?.let { book ->
|
||||
try {
|
||||
|
|
@ -189,7 +189,7 @@ class SerieController(
|
|||
val pageNum = if (zeroBasedIndex) pageNumber + 1 else pageNumber
|
||||
|
||||
val pageContent = try {
|
||||
bookLifecyle.getBookPage(book, pageNum, convertFormat)
|
||||
bookLifecycle.getBookPage(book, pageNum, convertFormat)
|
||||
} catch (e: UnsupportedMediaTypeException) {
|
||||
throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
|
||||
} catch (e: Exception) {
|
||||
|
|
@ -221,7 +221,7 @@ class SerieController(
|
|||
}
|
||||
}
|
||||
|
||||
data class SerieDto(
|
||||
data class SeriesDto(
|
||||
val id: Long,
|
||||
val name: String,
|
||||
val url: String,
|
||||
|
|
@ -229,7 +229,7 @@ data class SerieDto(
|
|||
val lastModified: LocalDateTime?
|
||||
)
|
||||
|
||||
fun Serie.toDto() = SerieDto(
|
||||
fun Series.toDto() = SeriesDto(
|
||||
id = id,
|
||||
name = name,
|
||||
url = url.toString(),
|
||||
|
|
@ -270,4 +270,4 @@ data class PageDto(
|
|||
)
|
||||
|
||||
fun LocalDateTime.toUTC(): LocalDateTime =
|
||||
atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime()
|
||||
atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneOffset.UTC).toLocalDateTime()
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
alter table serie
|
||||
rename to series;
|
||||
|
||||
alter table series
|
||||
rename constraint fk_serie_library_library_id to fk_series_library_library_id;
|
||||
|
||||
alter index if exists fk_serie_library_library_id_index_4 rename to fk_series_library_library_id_index_4;
|
||||
|
||||
|
||||
alter table book
|
||||
alter column serie_id
|
||||
rename to series_id;
|
||||
|
||||
alter table book
|
||||
rename constraint fk_book_serie_serie_id to fk_book_series_series_id;
|
||||
|
||||
alter index if exists fk_book_serie_serie_id_index_1 rename to fk_book_series_series_id_index_1;
|
||||
|
|
@ -8,9 +8,9 @@ fun makeBook(name: String, url: String = "file:/$name", fileLastModified: LocalD
|
|||
return Book(name = name, url = URL(url), fileLastModified = fileLastModified)
|
||||
}
|
||||
|
||||
fun makeSerie(name: String, url: String = "file:/$name", books: List<Book> = listOf()): Serie {
|
||||
fun makeSeries(name: String, url: String = "file:/$name", books: List<Book> = listOf()): Series {
|
||||
Thread.sleep(5)
|
||||
return Serie(name = name, url = URL(url), fileLastModified = LocalDateTime.now(), books = books.toMutableList())
|
||||
return Series(name = name, url = URL(url), fileLastModified = LocalDateTime.now(), books = books.toMutableList())
|
||||
}
|
||||
|
||||
fun makeLibrary(name: String = "default", url: String = "file:/$name"): Library {
|
||||
|
|
@ -18,4 +18,4 @@ fun makeLibrary(name: String = "default", url: String = "file:/$name"): Library
|
|||
}
|
||||
|
||||
fun makeBookPage(name: String) =
|
||||
BookPage(name, "image/png")
|
||||
BookPage(name, "image/png")
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package org.gotson.komga.domain.persistence
|
|||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSerie
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
|
|
@ -19,7 +19,7 @@ import java.time.LocalDateTime
|
|||
@DataJpaTest
|
||||
@Transactional
|
||||
class AuditableEntityTest(
|
||||
@Autowired private val serieRepository: SerieRepository,
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository
|
||||
) {
|
||||
|
||||
|
|
@ -37,81 +37,81 @@ class AuditableEntityTest(
|
|||
|
||||
@AfterEach
|
||||
fun `clear repository`() {
|
||||
serieRepository.deleteAll()
|
||||
seriesRepository.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given serie with book when saving then created and modified date is also saved`() {
|
||||
fun `given series with book when saving then created and modified date is also saved`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
|
||||
// when
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
// then
|
||||
assertThat(serie.createdDate).isBefore(LocalDateTime.now())
|
||||
assertThat(serie.lastModifiedDate).isBefore(LocalDateTime.now())
|
||||
assertThat(serie.books.first().createdDate).isBefore(LocalDateTime.now())
|
||||
assertThat(serie.books.first().lastModifiedDate).isBefore(LocalDateTime.now())
|
||||
assertThat(series.createdDate).isBefore(LocalDateTime.now())
|
||||
assertThat(series.lastModifiedDate).isBefore(LocalDateTime.now())
|
||||
assertThat(series.books.first().createdDate).isBefore(LocalDateTime.now())
|
||||
assertThat(series.books.first().lastModifiedDate).isBefore(LocalDateTime.now())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given existing serie with book when updating serie only then created date is kept and modified date is changed for serie only`() {
|
||||
fun `given existing series with book when updating series only then created date is kept and modified date is changed for series only`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
val creationTimeApprox = LocalDateTime.now()
|
||||
|
||||
Thread.sleep(1000)
|
||||
|
||||
// when
|
||||
serie.name = "serieUpdated"
|
||||
serieRepository.saveAndFlush(serie)
|
||||
series.name = "seriesUpdated"
|
||||
seriesRepository.saveAndFlush(series)
|
||||
|
||||
val modificationTimeApprox = LocalDateTime.now()
|
||||
|
||||
// then
|
||||
assertThat(serie.createdDate)
|
||||
assertThat(series.createdDate)
|
||||
.isBefore(creationTimeApprox)
|
||||
.isNotEqualTo(serie.lastModifiedDate)
|
||||
assertThat(serie.lastModifiedDate)
|
||||
.isNotEqualTo(series.lastModifiedDate)
|
||||
assertThat(series.lastModifiedDate)
|
||||
.isAfter(creationTimeApprox)
|
||||
.isBefore(modificationTimeApprox)
|
||||
|
||||
assertThat(serie.books.first().createdDate)
|
||||
assertThat(series.books.first().createdDate)
|
||||
.isBefore(creationTimeApprox)
|
||||
.isEqualTo(serie.books.first().lastModifiedDate)
|
||||
.isEqualTo(series.books.first().lastModifiedDate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given existing serie with book when updating book only then created date is kept and modified date is changed for book only`() {
|
||||
fun `given existing series with book when updating book only then created date is kept and modified date is changed for book only`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
val creationTimeApprox = LocalDateTime.now()
|
||||
|
||||
Thread.sleep(1000)
|
||||
|
||||
// when
|
||||
serie.books.first().name = "bookUpdated"
|
||||
serieRepository.saveAndFlush(serie)
|
||||
series.books.first().name = "bookUpdated"
|
||||
seriesRepository.saveAndFlush(series)
|
||||
|
||||
val modificationTimeApprox = LocalDateTime.now()
|
||||
|
||||
// then
|
||||
assertThat(serie.createdDate)
|
||||
assertThat(series.createdDate)
|
||||
.isBefore(creationTimeApprox)
|
||||
.isEqualTo(serie.lastModifiedDate)
|
||||
.isEqualTo(series.lastModifiedDate)
|
||||
|
||||
assertThat(serie.books.first().createdDate)
|
||||
assertThat(series.books.first().createdDate)
|
||||
.isBefore(creationTimeApprox)
|
||||
.isNotEqualTo(serie.books.first().lastModifiedDate)
|
||||
assertThat(serie.books.first().lastModifiedDate)
|
||||
.isNotEqualTo(series.books.first().lastModifiedDate)
|
||||
assertThat(series.books.first().lastModifiedDate)
|
||||
.isAfter(creationTimeApprox)
|
||||
.isBefore(modificationTimeApprox)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import org.gotson.komga.domain.model.BookMetadata
|
|||
import org.gotson.komga.domain.model.Status
|
||||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSerie
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
|
|
@ -21,7 +21,7 @@ import org.springframework.transaction.annotation.Transactional
|
|||
@DataJpaTest
|
||||
@Transactional
|
||||
class BookRepositoryTest(
|
||||
@Autowired private val serieRepository: SerieRepository,
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val bookRepository: BookRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository
|
||||
) {
|
||||
|
|
@ -40,22 +40,22 @@ class BookRepositoryTest(
|
|||
|
||||
@AfterEach
|
||||
fun `clear repository`() {
|
||||
serieRepository.deleteAll()
|
||||
seriesRepository.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given many books with unordered index when fetching then books are ordered and paged`() {
|
||||
val serie = makeSerie(
|
||||
name = "serie",
|
||||
val series = makeSeries(
|
||||
name = "series",
|
||||
books = (1..100 step 2).map { makeBook("$it") }
|
||||
).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
serie.books = serie.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
serieRepository.save(serie)
|
||||
series.books = series.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
seriesRepository.save(series)
|
||||
|
||||
val pageable = PageRequest.of(0, 20)
|
||||
val pageOfBooks = bookRepository.findAllBySerieId(serie.id, pageable)
|
||||
val pageOfBooks = bookRepository.findAllBySeriesId(series.id, pageable)
|
||||
|
||||
assertThat(pageOfBooks.isFirst).isTrue()
|
||||
assertThat(pageOfBooks.isLast).isFalse()
|
||||
|
|
@ -67,18 +67,18 @@ class BookRepositoryTest(
|
|||
|
||||
@Test
|
||||
fun `given many books in ready state with unordered index when fetching then books are ordered and paged`() {
|
||||
val serie = makeSerie(
|
||||
name = "serie",
|
||||
val series = makeSeries(
|
||||
name = "series",
|
||||
books = (1..100 step 2).map { makeBook("$it") }
|
||||
).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
serie.books = serie.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
serie.books.forEach { it.metadata = BookMetadata(Status.READY) }
|
||||
serieRepository.save(serie)
|
||||
series.books = series.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
series.books.forEach { it.metadata = BookMetadata(Status.READY) }
|
||||
seriesRepository.save(series)
|
||||
|
||||
val pageable = PageRequest.of(0, 20)
|
||||
val pageOfBooks = bookRepository.findAllBySerieId(serie.id, pageable)
|
||||
val pageOfBooks = bookRepository.findAllBySeriesId(series.id, pageable)
|
||||
|
||||
assertThat(pageOfBooks.isFirst).isTrue()
|
||||
assertThat(pageOfBooks.isLast).isFalse()
|
||||
|
|
@ -87,4 +87,4 @@ class BookRepositoryTest(
|
|||
assertThat(pageOfBooks.content).hasSize(20)
|
||||
assertThat(pageOfBooks.content.map { it.name }).startsWith("1", "2", "3", "5")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import org.gotson.komga.domain.model.Status
|
|||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeBookPage
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSerie
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.BeforeAll
|
||||
|
|
@ -21,7 +21,7 @@ import org.springframework.transaction.annotation.Transactional
|
|||
@DataJpaTest
|
||||
@Transactional
|
||||
class PersistenceTest(
|
||||
@Autowired private val serieRepository: SerieRepository,
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val bookRepository: BookRepository,
|
||||
@Autowired private val bookMetadataRepository: BookMetadataRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository
|
||||
|
|
@ -41,27 +41,27 @@ class PersistenceTest(
|
|||
|
||||
@AfterEach
|
||||
fun `clear repository`() {
|
||||
serieRepository.deleteAll()
|
||||
seriesRepository.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given serie with book when saving then metadata is also saved`() {
|
||||
fun `given series with book when saving then metadata is also saved`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
|
||||
// when
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
// then
|
||||
assertThat(serieRepository.count()).isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).isEqualTo(1)
|
||||
assertThat(bookRepository.count()).isEqualTo(1)
|
||||
assertThat(bookMetadataRepository.count()).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given serie with unordered books when saving then books are ordered with natural sort`() {
|
||||
fun `given series with unordered books when saving then books are ordered with natural sort`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(
|
||||
val series = makeSeries(name = "series", books = listOf(
|
||||
makeBook("book 1"),
|
||||
makeBook("book 05"),
|
||||
makeBook("book 6"),
|
||||
|
|
@ -69,20 +69,20 @@ class PersistenceTest(
|
|||
)).also { it.library = library }
|
||||
|
||||
// when
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
// then
|
||||
assertThat(serieRepository.count()).isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).isEqualTo(1)
|
||||
assertThat(bookRepository.count()).isEqualTo(4)
|
||||
assertThat(serieRepository.findAll().first().books.map { it.name })
|
||||
assertThat(seriesRepository.findAll().first().books.map { it.name })
|
||||
.containsExactly("book 1", "book 002", "book 05", "book 6")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given existing book when updating metadata then new metadata is saved`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
seriesRepository.save(series)
|
||||
|
||||
// when
|
||||
val book = bookRepository.findAll().first()
|
||||
|
|
@ -91,7 +91,7 @@ class PersistenceTest(
|
|||
bookRepository.save(book)
|
||||
|
||||
// then
|
||||
assertThat(serieRepository.count()).isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).isEqualTo(1)
|
||||
assertThat(bookRepository.count()).isEqualTo(1)
|
||||
assertThat(bookMetadataRepository.count()).isEqualTo(1)
|
||||
bookMetadataRepository.findAll().first().let {
|
||||
|
|
@ -105,8 +105,8 @@ class PersistenceTest(
|
|||
@Test
|
||||
fun `given book pages unordered when saving then pages are ordered with natural sort`() {
|
||||
// given
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"))).also { it.library = library }
|
||||
seriesRepository.save(series)
|
||||
|
||||
// when
|
||||
val book = bookRepository.findAll().first()
|
||||
|
|
@ -119,14 +119,14 @@ class PersistenceTest(
|
|||
bookRepository.save(book)
|
||||
|
||||
// then
|
||||
assertThat(serieRepository.count()).isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).isEqualTo(1)
|
||||
assertThat(bookRepository.count()).isEqualTo(1)
|
||||
assertThat(bookMetadataRepository.count()).isEqualTo(1)
|
||||
bookMetadataRepository.findAll().first().let {
|
||||
assertThat(it.status == Status.READY)
|
||||
assertThat(it.mediaType == "test")
|
||||
assertThat(it.pages).hasSize(3)
|
||||
assertThat(it.pages.map { it.fileName }).containsExactly("001", "2", "003")
|
||||
bookMetadataRepository.findAll().first().let { metadata ->
|
||||
assertThat(metadata.status == Status.READY)
|
||||
assertThat(metadata.mediaType == "test")
|
||||
assertThat(metadata.pages).hasSize(3)
|
||||
assertThat(metadata.pages.map { it.fileName }).containsExactly("001", "2", "003")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class FileSystemScannerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `given root directory with only files when scanning then return 1 serie containing those files as books`() {
|
||||
fun `given root directory with only files when scanning then return 1 series containing those files as books`() {
|
||||
Jimfs.newFileSystem(Configuration.unix()).use { fs ->
|
||||
val root = fs.getPath("/root")
|
||||
Files.createDirectory(root)
|
||||
|
|
@ -41,7 +41,7 @@ class FileSystemScannerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `given directory with unsupported files when scanning then return a serie excluding those files as books`() {
|
||||
fun `given directory with unsupported files when scanning then return a series excluding those files as books`() {
|
||||
Jimfs.newFileSystem(Configuration.unix()).use { fs ->
|
||||
val root = fs.getPath("/root")
|
||||
Files.createDirectory(root)
|
||||
|
|
@ -58,14 +58,14 @@ class FileSystemScannerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
fun `given directory with sub-directories containing files when scanning then return 1 serie per folder containing direct files as books`() {
|
||||
fun `given directory with sub-directories containing files when scanning then return 1 series per folder containing direct files as books`() {
|
||||
Jimfs.newFileSystem(Configuration.unix()).use { fs ->
|
||||
val root = fs.getPath("/root")
|
||||
Files.createDirectory(root)
|
||||
|
||||
val subDirs = listOf(
|
||||
"serie1" to listOf("volume1.cbz", "volume2.cbz"),
|
||||
"serie2" to listOf("book1.cbz", "book2.cbz")
|
||||
"series1" to listOf("volume1.cbz", "volume2.cbz"),
|
||||
"series2" to listOf("book1.cbz", "book2.cbz")
|
||||
).toMap()
|
||||
|
||||
subDirs.forEach { (dir, files) ->
|
||||
|
|
@ -73,14 +73,14 @@ class FileSystemScannerTest {
|
|||
files.forEach { Files.createFile(root.resolve(fs.getPath(dir, it))) }
|
||||
}
|
||||
|
||||
val series = scanner.scanRootFolder(root)
|
||||
val scannedSeries = scanner.scanRootFolder(root)
|
||||
|
||||
assertThat(series).hasSize(2)
|
||||
assertThat(scannedSeries).hasSize(2)
|
||||
|
||||
assertThat(series.map { it.name }).containsExactlyInAnyOrderElementsOf(subDirs.keys)
|
||||
series.forEach { serie ->
|
||||
assertThat(serie.books.map { it.name }).containsExactlyInAnyOrderElementsOf(subDirs[serie.name]?.map { FilenameUtils.removeExtension(it) })
|
||||
assertThat(scannedSeries.map { it.name }).containsExactlyInAnyOrderElementsOf(subDirs.keys)
|
||||
scannedSeries.forEach { series ->
|
||||
assertThat(series.books.map { it.name }).containsExactlyInAnyOrderElementsOf(subDirs[series.name]?.map { FilenameUtils.removeExtension(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ import org.gotson.komga.domain.model.Status
|
|||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeBookPage
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSerie
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
import org.gotson.komga.domain.persistence.BookRepository
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
|
|
@ -27,11 +27,11 @@ import java.nio.file.Paths
|
|||
@SpringBootTest
|
||||
@AutoConfigureTestDatabase
|
||||
class LibraryScannerTest(
|
||||
@Autowired private val serieRepository: SerieRepository,
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository,
|
||||
@Autowired private val bookRepository: BookRepository,
|
||||
@Autowired private val libraryScanner: LibraryScanner,
|
||||
@Autowired private val bookLifecyle: BookLifecyle
|
||||
@Autowired private val bookLifecycle: BookLifecycle
|
||||
) {
|
||||
|
||||
@MockkBean
|
||||
|
|
@ -42,22 +42,22 @@ class LibraryScannerTest(
|
|||
|
||||
@AfterEach
|
||||
fun `clear repositories`() {
|
||||
serieRepository.deleteAll()
|
||||
seriesRepository.deleteAll()
|
||||
libraryRepository.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
fun `given existing Serie when adding files and scanning then only updated Books are persisted`() {
|
||||
fun `given existing series when adding files and scanning then only updated Books are persisted`() {
|
||||
// given
|
||||
val library = libraryRepository.save(makeLibrary())
|
||||
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1")))
|
||||
val serieWithMoreBooks = makeSerie(name = "serie", books = listOf(makeBook("book1"), makeBook("book2")))
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1")))
|
||||
val seriesWithMoreBooks = makeSeries(name = "series", books = listOf(makeBook("book1"), makeBook("book2")))
|
||||
|
||||
every { mockScanner.scanRootFolder(any()) }.returnsMany(
|
||||
listOf(serie),
|
||||
listOf(serieWithMoreBooks)
|
||||
listOf(series),
|
||||
listOf(seriesWithMoreBooks)
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
|
|
@ -65,28 +65,28 @@ class LibraryScannerTest(
|
|||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
// then
|
||||
val series = serieRepository.findAll()
|
||||
val allSeries = seriesRepository.findAll()
|
||||
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(any()) }
|
||||
|
||||
assertThat(series).hasSize(1)
|
||||
assertThat(series.first().books).hasSize(2)
|
||||
assertThat(series.first().books.map { it.name }).containsExactly("book1", "book2")
|
||||
assertThat(allSeries).hasSize(1)
|
||||
assertThat(allSeries.first().books).hasSize(2)
|
||||
assertThat(allSeries.first().books.map { it.name }).containsExactly("book1", "book2")
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
fun `given existing Serie when removing files and scanning then only updated Books are persisted`() {
|
||||
fun `given existing series when removing files and scanning then only updated Books are persisted`() {
|
||||
// given
|
||||
val library = libraryRepository.save(makeLibrary())
|
||||
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1"), makeBook("book2")))
|
||||
val serieWithLessBooks = makeSerie(name = "serie", books = listOf(makeBook("book1")))
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1"), makeBook("book2")))
|
||||
val seriesWithLessBooks = makeSeries(name = "series", books = listOf(makeBook("book1")))
|
||||
|
||||
every { mockScanner.scanRootFolder(any()) }
|
||||
.returnsMany(
|
||||
listOf(serie),
|
||||
listOf(serieWithLessBooks)
|
||||
listOf(series),
|
||||
listOf(seriesWithLessBooks)
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
|
|
@ -94,29 +94,29 @@ class LibraryScannerTest(
|
|||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
// then
|
||||
val series = serieRepository.findAll()
|
||||
val allSeries = seriesRepository.findAll()
|
||||
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(any()) }
|
||||
|
||||
assertThat(series).hasSize(1)
|
||||
assertThat(series.first().books).hasSize(1)
|
||||
assertThat(series.first().books.map { it.name }).containsExactly("book1")
|
||||
assertThat(allSeries).hasSize(1)
|
||||
assertThat(allSeries.first().books).hasSize(1)
|
||||
assertThat(allSeries.first().books.map { it.name }).containsExactly("book1")
|
||||
assertThat(bookRepository.count()).describedAs("Orphan book has been removed").isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
fun `given existing Serie when updating files and scanning then Books are updated`() {
|
||||
fun `given existing series when updating files and scanning then Books are updated`() {
|
||||
// given
|
||||
val library = libraryRepository.save(makeLibrary())
|
||||
|
||||
val serie = makeSerie(name = "serie", books = listOf(makeBook("book1")))
|
||||
val serieWithUpdatedBooks = makeSerie(name = "serie", books = listOf(makeBook("book1updated", "file:/book1")))
|
||||
val series = makeSeries(name = "series", books = listOf(makeBook("book1")))
|
||||
val seriesWithUpdatedBooks = makeSeries(name = "series", books = listOf(makeBook("book1updated", "file:/book1")))
|
||||
|
||||
every { mockScanner.scanRootFolder(any()) }
|
||||
.returnsMany(
|
||||
listOf(serie),
|
||||
listOf(serieWithUpdatedBooks)
|
||||
listOf(series),
|
||||
listOf(seriesWithUpdatedBooks)
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
|
|
@ -124,25 +124,25 @@ class LibraryScannerTest(
|
|||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
// then
|
||||
val series = serieRepository.findAll()
|
||||
val allSeries = seriesRepository.findAll()
|
||||
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(any()) }
|
||||
|
||||
assertThat(series).hasSize(1)
|
||||
assertThat(series.first().lastModifiedDate).isNotEqualTo(series.first().createdDate)
|
||||
assertThat(series.first().books).hasSize(1)
|
||||
assertThat(series.first().books.map { it.name }).containsExactly("book1updated")
|
||||
assertThat(series.first().books.first().lastModifiedDate).isNotEqualTo(series.first().books.first().createdDate)
|
||||
assertThat(allSeries).hasSize(1)
|
||||
assertThat(allSeries.first().lastModifiedDate).isNotEqualTo(allSeries.first().createdDate)
|
||||
assertThat(allSeries.first().books).hasSize(1)
|
||||
assertThat(allSeries.first().books.map { it.name }).containsExactly("book1updated")
|
||||
assertThat(allSeries.first().books.first().lastModifiedDate).isNotEqualTo(allSeries.first().books.first().createdDate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given existing Serie when deleting all books and scanning then Series and Books are removed`() {
|
||||
fun `given existing series when deleting all books and scanning then Series and Books are removed`() {
|
||||
// given
|
||||
val library = libraryRepository.save(makeLibrary())
|
||||
|
||||
every { mockScanner.scanRootFolder(any()) }
|
||||
.returnsMany(
|
||||
listOf(makeSerie(name = "serie", books = listOf(makeBook("book1")))),
|
||||
listOf(makeSeries(name = "series", books = listOf(makeBook("book1")))),
|
||||
emptyList()
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
|
@ -153,19 +153,19 @@ class LibraryScannerTest(
|
|||
// then
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(any()) }
|
||||
|
||||
assertThat(serieRepository.count()).describedAs("Serie repository should be empty").isEqualTo(0)
|
||||
assertThat(seriesRepository.count()).describedAs("Series repository should be empty").isEqualTo(0)
|
||||
assertThat(bookRepository.count()).describedAs("Book repository should be empty").isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `given existing Series when deleting all books of one serie and scanning then Serie and its Books are removed`() {
|
||||
fun `given existing Series when deleting all books of one series and scanning then series and its Books are removed`() {
|
||||
// given
|
||||
val library = libraryRepository.save(makeLibrary())
|
||||
|
||||
every { mockScanner.scanRootFolder(any()) }
|
||||
.returnsMany(
|
||||
listOf(makeSerie(name = "serie", books = listOf(makeBook("book1"))), makeSerie(name = "serie2", books = listOf(makeBook("book2")))),
|
||||
listOf(makeSerie(name = "serie", books = listOf(makeBook("book1"))))
|
||||
listOf(makeSeries(name = "series", books = listOf(makeBook("book1"))), makeSeries(name = "series2", books = listOf(makeBook("book2")))),
|
||||
listOf(makeSeries(name = "series", books = listOf(makeBook("book1"))))
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ class LibraryScannerTest(
|
|||
// then
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(any()) }
|
||||
|
||||
assertThat(serieRepository.count()).describedAs("Serie repository should be empty").isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).describedAs("Series repository should be empty").isEqualTo(1)
|
||||
assertThat(bookRepository.count()).describedAs("Book repository should be empty").isEqualTo(1)
|
||||
}
|
||||
|
||||
|
|
@ -187,13 +187,13 @@ class LibraryScannerTest(
|
|||
val book1 = makeBook("book1")
|
||||
every { mockScanner.scanRootFolder(any()) }
|
||||
.returnsMany(
|
||||
listOf(makeSerie(name = "serie", books = listOf(book1))),
|
||||
listOf(makeSerie(name = "serie", books = listOf(makeBook(name = "book1", fileLastModified = book1.fileLastModified))))
|
||||
listOf(makeSeries(name = "series", books = listOf(book1))),
|
||||
listOf(makeSeries(name = "series", books = listOf(makeBook(name = "book1", fileLastModified = book1.fileLastModified))))
|
||||
)
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
||||
every { mockParser.parse(any()) } returns BookMetadata(status = Status.READY, mediaType = "application/zip", pages = mutableListOf(makeBookPage("1.jpg"), makeBookPage("2.jpg")))
|
||||
bookRepository.findAll().map { bookLifecyle.parseAndPersist(it) }.map { it.get() }
|
||||
bookRepository.findAll().map { bookLifecycle.parseAndPersist(it) }.map { it.get() }
|
||||
|
||||
// when
|
||||
libraryScanner.scanRootFolder(library)
|
||||
|
|
@ -217,17 +217,17 @@ class LibraryScannerTest(
|
|||
val library2 = libraryRepository.save(makeLibrary(name = "library2"))
|
||||
|
||||
every { mockScanner.scanRootFolder(Paths.get(library1.root.toURI())) } returns
|
||||
listOf(makeSerie(name = "serie1", books = listOf(makeBook("book1"))))
|
||||
listOf(makeSeries(name = "series1", books = listOf(makeBook("book1"))))
|
||||
|
||||
every { mockScanner.scanRootFolder(Paths.get(library2.root.toURI())) }.returnsMany(
|
||||
listOf(makeSerie(name = "serie2", books = listOf(makeBook("book2")))),
|
||||
listOf(makeSeries(name = "series2", books = listOf(makeBook("book2")))),
|
||||
emptyList()
|
||||
)
|
||||
|
||||
libraryScanner.scanRootFolder(library1)
|
||||
libraryScanner.scanRootFolder(library2)
|
||||
|
||||
assertThat(serieRepository.count()).describedAs("Serie repository should be empty").isEqualTo(2)
|
||||
assertThat(seriesRepository.count()).describedAs("Series repository should be empty").isEqualTo(2)
|
||||
assertThat(bookRepository.count()).describedAs("Book repository should be empty").isEqualTo(2)
|
||||
|
||||
// when
|
||||
|
|
@ -237,7 +237,7 @@ class LibraryScannerTest(
|
|||
verify(exactly = 1) { mockScanner.scanRootFolder(Paths.get(library1.root.toURI())) }
|
||||
verify(exactly = 2) { mockScanner.scanRootFolder(Paths.get(library2.root.toURI())) }
|
||||
|
||||
assertThat(serieRepository.count()).describedAs("Serie repository should be empty").isEqualTo(1)
|
||||
assertThat(seriesRepository.count()).describedAs("Series repository should be empty").isEqualTo(1)
|
||||
assertThat(bookRepository.count()).describedAs("Book repository should be empty").isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import org.gotson.komga.domain.model.BookMetadata
|
|||
import org.gotson.komga.domain.model.Status
|
||||
import org.gotson.komga.domain.model.makeBook
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.model.makeSerie
|
||||
import org.gotson.komga.domain.model.makeSeries
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
import org.gotson.komga.domain.persistence.SerieRepository
|
||||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.junit.jupiter.api.AfterAll
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
|
|
@ -27,8 +27,8 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers
|
|||
@SpringBootTest
|
||||
@AutoConfigureTestDatabase
|
||||
@AutoConfigureMockMvc(printOnlyOnFailure = false)
|
||||
class SerieControllerTest(
|
||||
@Autowired private val serieRepository: SerieRepository,
|
||||
class SeriesControllerTest(
|
||||
@Autowired private val seriesRepository: SeriesRepository,
|
||||
@Autowired private val libraryRepository: LibraryRepository,
|
||||
@Autowired private val mockMvc: MockMvc
|
||||
|
||||
|
|
@ -48,22 +48,22 @@ class SerieControllerTest(
|
|||
|
||||
@AfterEach
|
||||
fun `clear repository`() {
|
||||
serieRepository.deleteAll()
|
||||
seriesRepository.deleteAll()
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
fun `given books with unordered index when requesting via api then books are ordered`() {
|
||||
val serie = makeSerie(
|
||||
name = "serie",
|
||||
val series = makeSeries(
|
||||
name = "series",
|
||||
books = listOf(makeBook("1"), makeBook("3"))
|
||||
).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
serie.books = serie.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
serieRepository.save(serie)
|
||||
series.books = series.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
seriesRepository.save(series)
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${serie.id}/books?readyonly=false"))
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${series.id}/books?readyonly=false"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk)
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[0].name", equalTo("1")))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[1].name", equalTo("2")))
|
||||
|
|
@ -73,16 +73,16 @@ class SerieControllerTest(
|
|||
@Test
|
||||
@WithMockUser
|
||||
fun `given many books with unordered index when requesting via api then books are ordered and paged`() {
|
||||
val serie = makeSerie(
|
||||
name = "serie",
|
||||
val series = makeSeries(
|
||||
name = "series",
|
||||
books = (1..100 step 2).map { makeBook("$it") }
|
||||
).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
serie.books = serie.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
serieRepository.save(serie)
|
||||
series.books = series.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
seriesRepository.save(series)
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${serie.id}/books?readyonly=false"))
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${series.id}/books?readyonly=false"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk)
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[0].name", equalTo("1")))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[1].name", equalTo("2")))
|
||||
|
|
@ -96,17 +96,17 @@ class SerieControllerTest(
|
|||
@Test
|
||||
@WithMockUser
|
||||
fun `given many books in ready state with unordered index when requesting via api then books are ordered and paged`() {
|
||||
val serie = makeSerie(
|
||||
name = "serie",
|
||||
val series = makeSeries(
|
||||
name = "series",
|
||||
books = (1..100 step 2).map { makeBook("$it") }
|
||||
).also { it.library = library }
|
||||
serieRepository.save(serie)
|
||||
seriesRepository.save(series)
|
||||
|
||||
serie.books = serie.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
serie.books.forEach { it.metadata = BookMetadata(Status.READY) }
|
||||
serieRepository.save(serie)
|
||||
series.books = series.books.toMutableList().also { it.add(makeBook("2")) }
|
||||
series.books.forEach { it.metadata = BookMetadata(Status.READY) }
|
||||
seriesRepository.save(series)
|
||||
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${serie.id}/books?readyonly=true"))
|
||||
mockMvc.perform(MockMvcRequestBuilders.get("/api/v1/series/${series.id}/books?readyonly=true"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk)
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[0].name", equalTo("1")))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.content[1].name", equalTo("2")))
|
||||
|
|
@ -116,4 +116,4 @@ class SerieControllerTest(
|
|||
.andExpect(MockMvcResultMatchers.jsonPath("$.first", equalTo(true)))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.number", equalTo(0)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue