feat: add create and edit book form
Claude-Session: https://claude.ai/code/session_01M9MLit5Ko3X4s7rzC5Kv7X
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { dune, renderApp, signedIn } from '../test/helpers'
|
||||
|
||||
const fresh = { ...dune, current_page: 0, status: 'not_started' as const }
|
||||
|
||||
describe('BookForm', () => {
|
||||
it('adds a book and opens it', async () => {
|
||||
const calls = signedIn({
|
||||
'POST /api/books': () => [201, fresh],
|
||||
'GET /api/books/7': () => [200, fresh],
|
||||
})
|
||||
const user = renderApp('/books/new')
|
||||
await screen.findByRole('option', { name: 'Science Fiction' })
|
||||
await user.type(screen.getByLabelText('Title'), 'Dune')
|
||||
await user.type(screen.getByLabelText('Author'), 'Frank Herbert')
|
||||
await user.selectOptions(screen.getByLabelText('Genre'), 'Science Fiction')
|
||||
await user.type(screen.getByLabelText('Total pages'), '380')
|
||||
await user.click(screen.getByRole('button', { name: 'Add book' }))
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Dune', level: 1 })).toBeInTheDocument()
|
||||
expect(calls).toContainEqual({
|
||||
method: 'POST',
|
||||
path: '/api/books',
|
||||
body: { title: 'Dune', author: 'Frank Herbert', genre_id: 5, total_pages: 380, current_page: 0 },
|
||||
})
|
||||
})
|
||||
|
||||
it('shows a server validation error against the field', async () => {
|
||||
signedIn({ 'POST /api/books': () => [400, { error: 'Unknown genre_id; see GET /api/genres', field: 'genre_id' }] })
|
||||
const user = renderApp('/books/new')
|
||||
await screen.findByRole('option', { name: 'Science Fiction' })
|
||||
await user.type(screen.getByLabelText('Title'), 'Dune')
|
||||
await user.type(screen.getByLabelText('Author'), 'Frank Herbert')
|
||||
await user.selectOptions(screen.getByLabelText('Genre'), 'Science Fiction')
|
||||
await user.type(screen.getByLabelText('Total pages'), '380')
|
||||
await user.click(screen.getByRole('button', { name: 'Add book' }))
|
||||
|
||||
expect(await screen.findByRole('alert')).toHaveTextContent('Unknown genre_id')
|
||||
expect(screen.getByLabelText('Genre')).toHaveAttribute('aria-invalid', 'true')
|
||||
})
|
||||
|
||||
it('edits an existing book', async () => {
|
||||
let saved = dune
|
||||
const calls = signedIn({
|
||||
'GET /api/books/7': () => [200, saved],
|
||||
'PATCH /api/books/7': ({ body }) => {
|
||||
saved = { ...saved, ...(body as object) }
|
||||
return [200, saved]
|
||||
},
|
||||
})
|
||||
const user = renderApp('/books/7/edit')
|
||||
const title = await screen.findByDisplayValue('Dune')
|
||||
await user.clear(title)
|
||||
await user.type(title, 'Dune Messiah')
|
||||
await user.click(screen.getByRole('button', { name: 'Save changes' }))
|
||||
|
||||
expect(await screen.findByRole('heading', { name: 'Dune Messiah', level: 1 })).toBeInTheDocument()
|
||||
expect(calls).toContainEqual({
|
||||
method: 'PATCH',
|
||||
path: '/api/books/7',
|
||||
body: { title: 'Dune Messiah', author: 'Frank Herbert', genre_id: 5, total_pages: 380, current_page: 142 },
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user