Add tests for LazySeriesCard.vue

This commit is contained in:
mikiher 2024-04-17 23:27:31 +03:00
parent 9b332f0e66
commit e5bababeae
2 changed files with 219 additions and 10 deletions

View File

@ -0,0 +1,209 @@
import LazySeriesCard from "./LazySeriesCard.vue"
import GroupCover from "../covers/GroupCover.vue"
describe("LazySeriesCard", () => {
const series = {
id: 1,
name: "The Lord of the Rings",
nameIgnorePrefix: "Lord of the Rings",
books: [
{ id: 1, updatedAt: /* 04/14/2024 */ 1713099600000, addedAt: 1713099600000, media: { coverPath: "cover1.jpg" }, title: "The Fellowship of the Ring" },
{ id: 2, updatedAt: /* 04/15/2024 */ 1713186000000, addedAt: 1713186000000, media: { coverPath: "cover2.jpg" }, title: "The Two Towers" },
{ id: 3, updatedAt: /* 04/16/2024 */ 1713272400000, addedAt: 1713272400000, media: { coverPath: "cover3.jpg" }, title: "The Return of the King" }
],
addedAt: /* 04/17/2024 */ 1713358800000,
totalDuration: /* 7h 30m */ 3600 * 7 + 60 * 30,
rssFeed: "https://example.com/feed.rss"
}
const propsData = {
index: 0,
width: 192 * 2,
height: 192,
sizeMultiplier: 1,
bookCoverAspectRatio: 1,
bookshelfView: 1,
isCategorized: false,
seriesMount: series,
sortingIgnorePrefix: false,
orderBy: "addedAt",
}
const stubs = {
"covers-group-cover": GroupCover
}
const mocks = {
$store: {
getters: {
"user/getUserCanUpdate": true,
"user/getUserMediaProgress": (id) => null,
"libraries/getLibraryProvider": () => "audible.us",
"globals/getLibraryItemCoverSrc": () => "http://localhost:3333//book_placeholder.jpg"
},
state: {
libraries: {
currentLibraryId: "library-123"
},
serverSettings: {
dateFormat: "MM/dd/yyyy"
}
}
}
}
it("renders the component", () => {
cy.mount(LazySeriesCard, { propsData, stubs, mocks })
cy.get('#series-card-0').should(($el) => {
const width = $el.width()
const height = $el.height()
expect(width).to.be.closeTo(propsData.width, 0.01)
expect(height).to.be.closeTo(propsData.height, 0.01)
})
cy.get("#seriesLengthMarker").should("be.visible").and("have.text", propsData.seriesMount.books.length)
cy.get("#seriesProgressBar").should("not.exist")
cy.get("#HoveringDisplayTitle").should("be.hidden")
cy.get("#rssFeedMarker").should("be.visible")
cy.get("#standardBottomDisplayTitle").should("not.exist")
cy.get("#detailBottomDisplayTitle").should("be.visible")
cy.get("#detailBottomDisplayTitle").should("have.text", "The Lord of the Rings")
cy.get("#detailBottomSortLine").should("have.text", "Added 04/17/2024")
})
it("shows series name and hides rss feed marker on mouseover", () => {
cy.mount(LazySeriesCard, { propsData, stubs, mocks })
cy.get("#series-card-0").trigger("mouseover")
cy.get("#HoveringDisplayTitle").should("be.visible").should("have.text", "The Lord of the Rings")
cy.get("#rssFeedMarker").should("not.exist")
})
it("routes properly when clicked", () => {
const updatedMocks = {
...mocks,
$router: {
push: cy.stub().as("routerPush")
}
}
cy.mount(LazySeriesCard, { propsData, stubs, mocks: updatedMocks})
cy.get("#series-card-0").click()
cy.get("@routerPush").should("have.been.calledOnceWithExactly", "/library/library-123/series/1")
})
it("shows progress bar when progress is available", () => {
const updatedMocks = {
...mocks,
$store: {
...mocks.$store,
getters: {
...mocks.$store.getters,
"user/getUserMediaProgress": (id) => {
switch (id) {
case 1:
return { isFinished: true }
case 2:
return { progress: 0.5 }
default:
return null
}
}
}
}
}
cy.mount(LazySeriesCard, { propsData, stubs, mocks: updatedMocks })
cy.get("#seriesProgressBar")
.should("be.visible")
.and("have.class", "bg-yellow-400")
.and(($el) => {
const width = $el.width()
expect(width).to.be.closeTo((2/3) * propsData.width, 0.01)
})
})
it("shows full green progress bar when all books are finished", () => {
const updatedMocks = {
...mocks,
$store: {
...mocks.$store,
getters: {
...mocks.$store.getters,
"user/getUserMediaProgress": (id) => { return { isFinished: true } }
}
}
}
cy.mount(LazySeriesCard, { propsData, stubs, mocks: updatedMocks })
cy.get("#seriesProgressBar")
.should("be.visible")
.and("have.class", "bg-success")
.and(($el) => {
const width = $el.width()
expect(width).to.equal(propsData.width)
})
})
it("hides the rss feed marker when there is no rss feed", () => {
const updatedPropsData = {
...propsData,
seriesMount: { ...series, rssFeed: null }
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#rssFeedMarker").should("not.exist")
})
it("shows the standard bottom display when bookshelf view is 0", () => {
const updatedPropsData = {
...propsData,
bookshelfView: 0
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#standardBottomDisplayTitle").should("be.visible")
cy.get("#detailBottomDisplayTitle").should("not.exist")
})
it("shows total duration in sort line when orderBy is totalDuration", () => {
const updatedPropsData = {
...propsData,
orderBy: "totalDuration"
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#detailBottomSortLine").should("have.text", "Duration 7h 30m")
})
it("shows last book updated date in sort line when orderBy is lastBookUpdated", () => {
const updatedPropsData = {
...propsData,
orderBy: "lastBookUpdated"
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#detailBottomSortLine").should("have.text", "Last Book Updated 04/16/2024")
})
it("shows last book added date in sort line when orderBy is lastBookAdded", () => {
const updatedPropsData = {
...propsData,
orderBy: "lastBookAdded"
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#detailBottomSortLine").should("have.text", "Last Book Added 04/16/2024")
})
it("shows nameIgnorePrefix when sortingIgnorePrefix is true", () => {
const updatedPropsData = {
...propsData,
sortingIgnorePrefix: true
}
cy.mount(LazySeriesCard, { propsData: updatedPropsData, stubs, mocks })
cy.get("#detailBottomDisplayTitle").should("have.text", "Lord of the Rings")
})
})

View File

@ -1,28 +1,28 @@
<template>
<div ref="card" :id="`series-card-${index}`" :style="{ width: width + 'px', height: height + 'px' }" class="rounded-sm z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard">
<div ref="card" :id="`series-card-${index}`" :style="{ width: width + 'px', height: height + 'px' }" class="relative rounded-sm z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard">
<div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" />
<div class="w-full h-full bg-primary relative rounded overflow-hidden z-0">
<covers-group-cover v-if="series" ref="cover" :id="seriesId" :name="displayTitle" :book-items="books" :width="width" :height="height" :book-cover-aspect-ratio="bookCoverAspectRatio" />
</div>
<div class="absolute z-10 top-1.5 right-1.5 rounded-md leading-3 text-sm p-1 font-semibold text-white flex items-center justify-center" style="background-color: #cd9d49dd">{{ books.length }}</div>
<div id="seriesLengthMarker" class="absolute z-10 top-1.5 right-1.5 rounded-md leading-3 text-sm p-1 font-semibold text-white flex items-center justify-center" style="background-color: #cd9d49dd">{{ books.length }}</div>
<div v-if="seriesPercentInProgress > 0" class="absolute bottom-0 left-0 h-1 shadow-sm max-w-full z-10 rounded-b w-full" :class="isSeriesFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: seriesPercentInProgress * 100 + '%' }" />
<div id="seriesProgressBar" v-if="seriesPercentInProgress > 0" class="absolute bottom-0 left-0 h-1 shadow-sm max-w-full z-10 rounded-b w-full" :class="isSeriesFinished ? 'bg-success' : 'bg-yellow-400'" :style="{ width: seriesPercentInProgress * 100 + '%' }" />
<div v-if="hasValidCovers" class="bg-black bg-opacity-60 absolute top-0 left-0 w-full h-full flex items-center justify-center text-center transition-opacity" :class="isHovering ? '' : 'opacity-0'" :style="{ padding: `${sizeMultiplier}rem` }">
<div id="HoveringDisplayTitle" v-if="hasValidCovers" class="bg-black bg-opacity-60 absolute top-0 left-0 w-full h-full flex items-center justify-center text-center transition-opacity" :class="isHovering ? '' : 'opacity-0'" :style="{ padding: `${sizeMultiplier}rem` }">
<p :style="{ fontSize: 1.2 * sizeMultiplier + 'rem' }">{{ displayTitle }}</p>
</div>
<span v-if="!isHovering && rssFeed" class="absolute z-10 material-icons text-success" :style="{ top: 0.5 * sizeMultiplier + 'rem', left: 0.5 * sizeMultiplier + 'rem', fontSize: 1.5 * sizeMultiplier + 'rem' }">rss_feed</span>
<span id="rssFeedMarker" v-if="!isHovering && rssFeed" class="absolute z-10 material-icons text-success" :style="{ top: 0.5 * sizeMultiplier + 'rem', left: 0.5 * sizeMultiplier + 'rem', fontSize: 1.5 * sizeMultiplier + 'rem' }">rss_feed</span>
<div v-if="!isAlternativeBookshelfView" class="categoryPlacard absolute z-10 left-0 right-0 mx-auto -bottom-6 h-6 rounded-md text-center" :style="{ width: Math.min(200, width) + 'px' }">
<div id="standardBottomText" v-if="!isAlternativeBookshelfView" class="categoryPlacard absolute z-10 left-0 right-0 mx-auto -bottom-6 h-6 rounded-md text-center" :style="{ width: Math.min(200, width) + 'px' }">
<div class="w-full h-full shinyBlack flex items-center justify-center rounded-sm border" :style="{ padding: `0rem ${0.5 * sizeMultiplier}rem` }">
<p class="truncate" :style="{ fontSize: labelFontSize + 'rem' }">{{ displayTitle }}</p>
<p id="standardBottomDisplayTitle" class="truncate" :style="{ fontSize: labelFontSize + 'rem' }">{{ displayTitle }}</p>
</div>
</div>
<div v-else class="absolute z-30 left-0 right-0 mx-auto -bottom-8 h-8 py-1 rounded-md text-center">
<p class="truncate" :style="{ fontSize: labelFontSize * sizeMultiplier + 'rem' }">{{ displayTitle }}</p>
<p v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displaySortLine }}</p>
<div id="detailBottomText" v-else class="absolute z-30 left-0 right-0 mx-auto -bottom-8 h-8 py-1 rounded-md text-center">
<p id="detailBottomDisplayTitle" class="truncate" :style="{ fontSize: labelFontSize * sizeMultiplier + 'rem' }">{{ displayTitle }}</p>
<p id="detailBottomSortLine" v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 * sizeMultiplier + 'rem' }">{{ displaySortLine }}</p>
</div>
</div>
</template>