diff --git a/client/src/features/book-requests/__tests__/RequestListTable.spec.ts b/client/src/features/book-requests/__tests__/RequestListTable.spec.ts index 373acaceb..9a6f01832 100644 --- a/client/src/features/book-requests/__tests__/RequestListTable.spec.ts +++ b/client/src/features/book-requests/__tests__/RequestListTable.spec.ts @@ -106,6 +106,18 @@ describe('RequestListTable', () => { expect(titleButton?.text()).toBe(LONG_TITLE) }) + + // A format asked for from a book's page carries no art, and used to show a blank placeholder. + it('falls back to the cover of the book a format request joins', () => { + const wrapper = render(request({ status: 'approved', matchedBookId: null, targetBookId: 434, coverUrl: null })) + const covers = wrapper.findAllComponents({ name: 'RequestCover' }) + + expect(covers.length).toBeGreaterThan(0) + for (const cover of covers) { + expect(cover.props('src')).toBeNull() + expect(cover.props('fallbackSources')).toEqual(['/api/v1/books/434/thumbnail?medium=audio']) + } + }) }) describe('RequestListTable pairs', () => { diff --git a/client/src/features/book-requests/__tests__/requestBookCover.spec.ts b/client/src/features/book-requests/__tests__/requestBookCover.spec.ts new file mode 100644 index 000000000..54118a999 --- /dev/null +++ b/client/src/features/book-requests/__tests__/requestBookCover.spec.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest' +import { requestBookCoverSources } from '../requestBookCover' + +describe('requestBookCoverSources', () => { + it('offers nothing for a request that names no book', () => { + expect(requestBookCoverSources({ mediaKind: 'audiobook', matchedBookId: null, targetBookId: null })).toEqual([]) + }) + + it("asks the book a format request joins for that format's cover", () => { + expect(requestBookCoverSources({ mediaKind: 'audiobook', matchedBookId: null, targetBookId: 434 })).toEqual([ + '/api/v1/books/434/thumbnail?medium=audio', + ]) + expect(requestBookCoverSources({ mediaKind: 'ebook', matchedBookId: null, targetBookId: 434 })).toEqual([ + '/api/v1/books/434/thumbnail?medium=ebook', + ]) + }) + + it('prefers the book the request became over the one it was aimed at', () => { + expect(requestBookCoverSources({ mediaKind: 'audiobook', matchedBookId: 500, targetBookId: 434 })).toEqual([ + '/api/v1/books/500/thumbnail?medium=audio', + ]) + }) +}) diff --git a/client/src/features/book-requests/components/ReleasePickerPanel.vue b/client/src/features/book-requests/components/ReleasePickerPanel.vue index 8dbe68162..eb14d694f 100644 --- a/client/src/features/book-requests/components/ReleasePickerPanel.vue +++ b/client/src/features/book-requests/components/ReleasePickerPanel.vue @@ -48,6 +48,7 @@ import RequestDrawerToolbar from './RequestDrawerToolbar.vue' import RequestEmptyState from './RequestEmptyState.vue' import EntityNotFound from '@/components/EntityNotFound.vue' import { formatKey, formatKeys, languageKey } from '../releaseFacets' +import { requestBookCoverSources } from '../requestBookCover' import { requestFailureText } from '../requestOutcome' import { protocolChipClass, sourceChipClass } from '../sourceColors' import { useBookRequestActions } from '../composables/useBookRequests' @@ -199,6 +200,7 @@ const busy = computed(() => grabbing.value || actions.isPending(request.value?.i const isRetry = computed(() => request.value?.status === 'failed') const failureText = computed(() => (request.value ? requestFailureText(request.value, (key, named) => t(key, named)) : null)) const authorLine = computed(() => request.value?.authors.join(', ') ?? '') +const bookCoverSources = computed(() => (request.value ? requestBookCoverSources(request.value) : [])) const localOnlyCriteriaFacts = computed(() => (criteria.value ? localOnlyFacts(criteria.value) : [])) /** * Adding a source or switching one back on happens under Settings > System > Requests, which is @@ -789,7 +791,13 @@ function showEverySource(): void {