mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(client): constrain request title column width
Keep long request titles from widening the auto-layout table and hiding row actions. Guard the intrinsic-sizing chain with focused component regression tests. Fixes #1613
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
import { mount, RouterLinkStub } from '@vue/test-utils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { BookRequestItem } from '@bookorbit/types'
|
||||
|
||||
import RequestListTable from '../components/RequestListTable.vue'
|
||||
|
||||
const LONG_TITLE = 'Teddy and Booker T: How Two American Icons Blazed a Path for Racial Equality (Unabridged)'
|
||||
|
||||
function request(overrides: Partial<BookRequestItem> = {}): BookRequestItem {
|
||||
return {
|
||||
id: 1613,
|
||||
userId: 1,
|
||||
requesterUsername: 'reporter',
|
||||
requesterName: 'Issue Reporter',
|
||||
title: LONG_TITLE,
|
||||
subtitle: null,
|
||||
authors: ['Brian Kilmeade'],
|
||||
seriesName: null,
|
||||
seriesIndex: null,
|
||||
isbn10: null,
|
||||
isbn13: null,
|
||||
publishedYear: 2021,
|
||||
language: 'en',
|
||||
coverUrl: null,
|
||||
providerKey: null,
|
||||
providerId: null,
|
||||
metadataSources: [],
|
||||
mediaKind: 'audiobook',
|
||||
status: 'available',
|
||||
preferredFormats: [],
|
||||
note: null,
|
||||
targetLibraryId: 1,
|
||||
targetLibraryName: 'Audiobooks',
|
||||
targetFolderId: null,
|
||||
decidedByUserId: null,
|
||||
decidedByUsername: null,
|
||||
decidedAt: null,
|
||||
decisionNote: null,
|
||||
matchedBookId: 42,
|
||||
bookDockFileId: null,
|
||||
selfServe: false,
|
||||
fulfillerUserId: null,
|
||||
statusReason: null,
|
||||
failureCode: null,
|
||||
failureMeta: null,
|
||||
subscribers: [],
|
||||
download: null,
|
||||
dismissed: false,
|
||||
createdAt: '2026-09-29T12:00:00.000Z',
|
||||
updatedAt: '2026-09-29T12:00:00.000Z',
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
function render(item = request()) {
|
||||
return mount(RequestListTable, {
|
||||
props: {
|
||||
requests: [item],
|
||||
canManage: true,
|
||||
canSelfFulfil: true,
|
||||
currentUserId: 1,
|
||||
busyIds: new Set<number>(),
|
||||
progressByRequest: {},
|
||||
density: 'comfortable',
|
||||
sortBy: 'createdAt',
|
||||
sortDir: 'desc',
|
||||
selectedIds: [],
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
RouterLink: RouterLinkStub,
|
||||
RequestCover: true,
|
||||
RequestPipeline: true,
|
||||
RequestRowActions: true,
|
||||
RequestStatusBadge: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
describe('RequestListTable', () => {
|
||||
it('constrains every intrinsic sizing boundary around a long title', () => {
|
||||
const wrapper = render()
|
||||
const titleButton = wrapper.findAll('tbody button').find((button) => button.text() === LONG_TITLE)
|
||||
|
||||
expect(titleButton).toBeDefined()
|
||||
expect(titleButton!.classes()).toEqual(expect.arrayContaining(['min-w-0', 'truncate']))
|
||||
|
||||
const titleRow = titleButton!.element.parentElement
|
||||
const titleBlock = titleRow?.parentElement
|
||||
const titleLayout = titleBlock?.parentElement
|
||||
const titleCell = titleLayout?.parentElement
|
||||
|
||||
expect(titleRow?.classList.contains('min-w-0')).toBe(true)
|
||||
expect(titleBlock?.classList.contains('min-w-0')).toBe(true)
|
||||
expect(titleLayout?.classList.contains('min-w-0')).toBe(true)
|
||||
expect(titleCell?.tagName).toBe('TD')
|
||||
expect(titleCell?.classList.contains('max-w-0')).toBe(true)
|
||||
})
|
||||
|
||||
it('keeps the complete title available to the title button', () => {
|
||||
const wrapper = render()
|
||||
const titleButton = wrapper.findAll('tbody button').find((button) => button.text() === LONG_TITLE)
|
||||
|
||||
expect(titleButton?.text()).toBe(LONG_TITLE)
|
||||
})
|
||||
})
|
||||
@@ -332,7 +332,8 @@ function handleGrab(request: BookRequestItem) {
|
||||
/>
|
||||
</td>
|
||||
|
||||
<td class="px-3" :class="isCompact ? 'py-1.5' : 'py-2.5'">
|
||||
<!-- Auto table layout uses the nowrap title's intrinsic width unless the cell itself is bounded. -->
|
||||
<td class="max-w-0 px-3" :class="isCompact ? 'py-1.5' : 'py-2.5'">
|
||||
<div class="flex min-w-0 items-center gap-2.5">
|
||||
<RequestCover
|
||||
:src="request.coverUrl"
|
||||
|
||||
Reference in New Issue
Block a user