@@ -39,7 +39,7 @@
-
+
{{ $strings.MessageNoEpisodes }}
@@ -80,7 +80,7 @@ export default {
episodeComponentRefs: {},
windowHeight: 0,
episodesTableOffsetTop: 0,
- episodeRowHeight: 176,
+ episodeRowHeight: 44 * 4, // h-44,
currScrollTop: 0
}
},
@@ -538,9 +538,10 @@ export default {
this.episodesTableOffsetTop = (lazyEpisodesTableEl?.offsetTop || 0) + 64
this.windowHeight = window.innerHeight
- this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight)
this.$nextTick(() => {
+ this.recalcEpisodeRowHeight()
+ this.episodesPerPage = Math.ceil(this.windowHeight / this.episodeRowHeight)
// Maybe update currScrollTop if items were removed
const itemPageWrapper = document.getElementById('item-page-wrapper')
const { scrollHeight, clientHeight } = itemPageWrapper
@@ -548,6 +549,13 @@ export default {
this.currScrollTop = Math.min(this.currScrollTop, maxScrollTop)
this.handleScroll()
})
+ },
+ recalcEpisodeRowHeight() {
+ const episodeRowEl = document.getElementById('episode-0') || document.getElementById('no-episodes')
+ if (episodeRowEl) {
+ const height = getComputedStyle(episodeRowEl).height
+ this.episodeRowHeight = parseInt(height) || this.episodeRowHeight
+ }
}
},
mounted() {
diff --git a/client/cypress/tests/utils/ElapsedPrettyExtended.cy.js b/client/cypress/tests/utils/ElapsedPrettyExtended.cy.js
new file mode 100644
index 00000000..fd603113
--- /dev/null
+++ b/client/cypress/tests/utils/ElapsedPrettyExtended.cy.js
@@ -0,0 +1,188 @@
+import Vue from 'vue'
+import '@/plugins/utils'
+
+// This is the actual function that is being tested
+const elapsedPrettyExtended = Vue.prototype.$elapsedPrettyExtended
+
+// Helper function to convert days, hours, minutes, seconds to total seconds
+function DHMStoSeconds(days, hours, minutes, seconds) {
+ return seconds + minutes * 60 + hours * 3600 + days * 86400
+}
+
+describe('$elapsedPrettyExtended', () => {
+ describe('function is on the Vue Prototype', () => {
+ it('exists as a function on Vue.prototype', () => {
+ expect(Vue.prototype.$elapsedPrettyExtended).to.exist
+ expect(Vue.prototype.$elapsedPrettyExtended).to.be.a('function')
+ })
+ })
+
+ describe('param default values', () => {
+ const testSeconds = DHMStoSeconds(0, 25, 1, 5) // 25h 1m 5s = 90065 seconds
+
+ it('uses useDays=true showSeconds=true by default', () => {
+ expect(elapsedPrettyExtended(testSeconds)).to.equal('1d 1h 1m 5s')
+ })
+
+ it('only useDays=false overrides useDays but keeps showSeconds=true', () => {
+ expect(elapsedPrettyExtended(testSeconds, false)).to.equal('25h 1m 5s')
+ })
+
+ it('explicit useDays=false showSeconds=false overrides both', () => {
+ expect(elapsedPrettyExtended(testSeconds, false, false)).to.equal('25h 1m')
+ })
+ })
+
+ describe('useDays=false showSeconds=true', () => {
+ const useDaysFalse = false
+ const showSecondsTrue = true
+ const testCases = [
+ [[0, 0, 0, 0], '', '0s -> ""'],
+ [[0, 1, 0, 1], '1h 1s', '1h 1s -> 1h 1s'],
+ [[0, 25, 0, 1], '25h 1s', '25h 1s -> 25h 1s']
+ ]
+
+ testCases.forEach(([dhms, expected, description]) => {
+ it(description, () => {
+ expect(elapsedPrettyExtended(DHMStoSeconds(...dhms), useDaysFalse, showSecondsTrue)).to.equal(expected)
+ })
+ })
+ })
+
+ describe('useDays=true showSeconds=true', () => {
+ const useDaysTrue = true
+ const showSecondsTrue = true
+ const testCases = [
+ [[0, 0, 0, 0], '', '0s -> ""'],
+ [[0, 1, 0, 1], '1h 1s', '1h 1s -> 1h 1s'],
+ [[0, 25, 0, 1], '1d 1h 1s', '25h 1s -> 1d 1h 1s']
+ ]
+
+ testCases.forEach(([dhms, expected, description]) => {
+ it(description, () => {
+ expect(elapsedPrettyExtended(DHMStoSeconds(...dhms), useDaysTrue, showSecondsTrue)).to.equal(expected)
+ })
+ })
+ })
+
+ describe('useDays=true showSeconds=false', () => {
+ const useDaysTrue = true
+ const showSecondsFalse = false
+ const testCases = [
+ [[0, 0, 0, 0], '', '0s -> ""'],
+ [[0, 1, 0, 0], '1h', '1h -> 1h'],
+ [[0, 1, 0, 1], '1h', '1h 1s -> 1h'],
+ [[0, 1, 1, 0], '1h 1m', '1h 1m -> 1h 1m'],
+ [[0, 25, 0, 0], '1d 1h', '25h -> 1d 1h'],
+ [[0, 25, 0, 1], '1d 1h', '25h 1s -> 1d 1h'],
+ [[2, 0, 0, 0], '2d', '2d -> 2d']
+ ]
+
+ testCases.forEach(([dhms, expected, description]) => {
+ it(description, () => {
+ expect(elapsedPrettyExtended(DHMStoSeconds(...dhms), useDaysTrue, showSecondsFalse)).to.equal(expected)
+ })
+ })
+ })
+
+ describe('rounding useDays=true showSeconds=true', () => {
+ const useDaysTrue = true
+ const showSecondsTrue = true
+ const testCases = [
+ // Seconds rounding
+ [[0, 0, 0, 1], '1s', '1s -> 1s'],
+ [[0, 0, 0, 29.9], '30s', '29.9s -> 30s'],
+ [[0, 0, 0, 30], '30s', '30s -> 30s'],
+ [[0, 0, 0, 30.1], '30s', '30.1s -> 30s'],
+ [[0, 0, 0, 59.4], '59s', '59.4s -> 59s'],
+ [[0, 0, 0, 59.5], '1m', '59.5s -> 1m'],
+
+ // Minutes rounding
+ [[0, 0, 59, 29], '59m 29s', '59m 29s -> 59m 29s'],
+ [[0, 0, 59, 30], '59m 30s', '59m 30s -> 59m 30s'],
+ [[0, 0, 59, 59.5], '1h', '59m 59.5s -> 1h'],
+
+ // Hours rounding
+ [[0, 23, 59, 29], '23h 59m 29s', '23h 59m 29s -> 23h 59m 29s'],
+ [[0, 23, 59, 30], '23h 59m 30s', '23h 59m 30s -> 23h 59m 30s'],
+ [[0, 23, 59, 59.5], '1d', '23h 59m 59.5s -> 1d'],
+
+ // The actual bug case
+ [[44, 23, 59, 30], '44d 23h 59m 30s', '44d 23h 59m 30s -> 44d 23h 59m 30s']
+ ]
+
+ testCases.forEach(([dhms, expected, description]) => {
+ it(description, () => {
+ expect(elapsedPrettyExtended(DHMStoSeconds(...dhms), useDaysTrue, showSecondsTrue)).to.equal(expected)
+ })
+ })
+ })
+
+ describe('rounding useDays=true showSeconds=false', () => {
+ const useDaysTrue = true
+ const showSecondsFalse = false
+ const testCases = [
+ // Seconds rounding - these cases changed behavior from original
+ [[0, 0, 0, 1], '', '1s -> ""'],
+ [[0, 0, 0, 29.9], '', '29.9s -> ""'],
+ [[0, 0, 0, 30], '', '30s -> ""'],
+ [[0, 0, 0, 30.1], '', '30.1s -> ""'],
+ [[0, 0, 0, 59.4], '', '59.4s -> ""'],
+ [[0, 0, 0, 59.5], '1m', '59.5s -> 1m'],
+ // This is unexpected behavior, but it's consistent with the original behavior
+ // We preserved the test case, to document the current behavior
+ // - with showSeconds=false,
+ // one might expect: 1m 29.5s --round(1.4901m)-> 1m
+ // actual implementation: 1h 29.5s --roundSeconds-> 1h 30s --roundMinutes-> 2m
+ // So because of the separate rounding of seconds, and then minutes, it returns 2m
+ [[0, 0, 1, 29.5], '2m', '1m 29.5s -> 2m'],
+
+ // Minutes carry - actual bug fixes below
+ [[0, 0, 59, 29], '59m', '59m 29s -> 59m'],
+ [[0, 0, 59, 30], '1h', '59m 30s -> 1h'], // This was an actual bug, used to return 60m
+ [[0, 0, 59, 59.5], '1h', '59m 59.5s -> 1h'],
+
+ // Hours carry
+ [[0, 23, 59, 29], '23h 59m', '23h 59m 29s -> 23h 59m'],
+ [[0, 23, 59, 30], '1d', '23h 59m 30s -> 1d'], // This was an actual bug, used to return 23h 60m
+ [[0, 23, 59, 59.5], '1d', '23h 59m 59.5s -> 1d'],
+
+ // The actual bug case
+ [[44, 23, 59, 30], '45d', '44d 23h 59m 30s -> 45d'] // This was an actual bug, used to return 44d 23h 60m
+ ]
+
+ testCases.forEach(([dhms, expected, description]) => {
+ it(description, () => {
+ expect(elapsedPrettyExtended(DHMStoSeconds(...dhms), useDaysTrue, showSecondsFalse)).to.equal(expected)
+ })
+ })
+ })
+
+ describe('empty values', () => {
+ const paramCombos = [
+ // useDays, showSeconds, description
+ [true, true, 'with days and seconds'],
+ [true, false, 'with days, no seconds'],
+ [false, true, 'no days, with seconds'],
+ [false, false, 'no days, no seconds']
+ ]
+
+ const emptyInputs = [
+ // input, description
+ [null, 'null input'],
+ [undefined, 'undefined input'],
+ [0, 'zero'],
+ [0.49, 'rounds to zero'] // Just under rounding threshold
+ ]
+
+ paramCombos.forEach(([useDays, showSeconds, paramDesc]) => {
+ describe(paramDesc, () => {
+ emptyInputs.forEach(([input, desc]) => {
+ it(desc, () => {
+ expect(elapsedPrettyExtended(input, useDays, showSeconds)).to.equal('')
+ })
+ })
+ })
+ })
+ })
+})
diff --git a/client/plugins/utils.js b/client/plugins/utils.js
index ad08ebf6..5ad909d3 100644
--- a/client/plugins/utils.js
+++ b/client/plugins/utils.js
@@ -69,17 +69,22 @@ Vue.prototype.$elapsedPrettyExtended = (seconds, useDays = true, showSeconds = t
let hours = Math.floor(minutes / 60)
minutes -= hours * 60
+ // Handle rollovers before days calculation
+ if (minutes && seconds && !showSeconds) {
+ if (seconds >= 30) minutes++
+ if (minutes >= 60) {
+ hours++ // Increment hours if minutes roll over
+ minutes -= 60 // adjust minutes
+ }
+ }
+
+ // Now calculate days with the final hours value
let days = 0
if (useDays || Math.floor(hours / 24) >= 100) {
days = Math.floor(hours / 24)
hours -= days * 24
}
- // If not showing seconds then round minutes up
- if (minutes && seconds && !showSeconds) {
- if (seconds >= 30) minutes++
- }
-
const strs = []
if (days) strs.push(`${days}d`)
if (hours) strs.push(`${hours}h`)