1
0

fix: loan error surfacing, non-admin export, guarded atomic migration, expanded player controls

This commit is contained in:
2026-09-03 23:50:54 +02:00
parent 9b2bc22d59
commit 3edf7574f9
7 changed files with 99 additions and 35 deletions

View File

@@ -25,7 +25,7 @@ vi.mock('../src/api.js', async (importOriginal) => {
}
})
import { api } from '../src/api.js'
import { api, ApiError } from '../src/api.js'
const item: ItemDetail = {
id: 1,
@@ -227,4 +227,12 @@ describe('ItemPage', () => {
await userEvent.click(screen.getByRole('button', { name: /mark returned/i }))
await waitFor(() => expect(api.returnLoan).toHaveBeenCalledWith(9))
})
it('lend failure surfaces the inline message', async () => {
vi.mocked(api.lendItem).mockRejectedValue(new ApiError(409, 'already_on_loan'))
renderItem()
await userEvent.type(await screen.findByLabelText(/borrower/i), 'Bob')
await userEvent.click(screen.getByRole('button', { name: /^lend$/i }))
await waitFor(() => expect(screen.getByText(/already out to someone/i)).toBeTruthy())
})
})

View File

@@ -69,4 +69,13 @@ describe('MiniBar', () => {
await userEvent.click(screen.getByRole('button', { name: /close player/i }))
await waitFor(() => expect(screen.queryByText('Motion')).toBeNull())
})
it('expanded view has prev/next/pause controls', async () => {
renderBar()
await userEvent.click(screen.getByRole('button', { name: 'load' }))
await userEvent.click(await screen.findByRole('button', { name: /expand/i }))
expect(screen.getByRole('button', { name: /previous track/i })).toBeTruthy()
expect(screen.getByRole('button', { name: /next track/i })).toBeTruthy()
expect(screen.getByRole('button', { name: /pause/i })).toBeTruthy()
})
})

View File

@@ -201,4 +201,11 @@ describe('SettingsPage', () => {
await userEvent.click(await screen.findByRole('button', { name: /back up now/i }))
await waitFor(() => expect(screen.getByText(/backup failed/i)).toBeTruthy())
})
it('non-admin sees the Export link but not backups', async () => {
stubAuthFetch({ id: 2, username: 'bob', isAdmin: false })
renderSettings()
expect(await screen.findByRole('link', { name: /export json/i })).toBeTruthy()
expect(screen.queryByRole('button', { name: /back up now/i })).toBeNull()
})
})