750aa40e8e
Reviewed-on: #355 Co-authored-by: miteruzo <miteruzo@naver.com> Co-committed-by: miteruzo <miteruzo@naver.com>
97 行
3.6 KiB
TypeScript
97 行
3.6 KiB
TypeScript
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import PostNewPage from '@/pages/posts/PostNewPage'
|
|
import { buildUser } from '@/test/factories'
|
|
import { renderWithProviders } from '@/test/render'
|
|
|
|
const api = vi.hoisted (() => ({
|
|
apiGet: vi.fn (),
|
|
apiPost: vi.fn (),
|
|
isApiError: vi.fn (),
|
|
}))
|
|
|
|
const toastApi = vi.hoisted (() => ({
|
|
toast: vi.fn (),
|
|
}))
|
|
|
|
vi.mock ('@/lib/api', () => api)
|
|
vi.mock ('@/components/ui/use-toast', () => toastApi)
|
|
|
|
describe ('PostNewPage', () => {
|
|
beforeEach (() => {
|
|
vi.clearAllMocks ()
|
|
api.isApiError.mockReturnValue (false)
|
|
})
|
|
|
|
it ('blocks guests', () => {
|
|
renderWithProviders (<PostNewPage user={buildUser ({ role: 'guest' })}/>)
|
|
|
|
expect (screen.getByText ('403')).toBeInTheDocument ()
|
|
})
|
|
|
|
it ('submits a new post with manual title and thumbnail settings', async () => {
|
|
api.apiPost.mockResolvedValueOnce ({})
|
|
api.apiGet.mockResolvedValue ([])
|
|
|
|
renderWithProviders (<PostNewPage user={buildUser ({ role: 'member' })}/>)
|
|
|
|
const checkboxes = screen.getAllByRole ('checkbox', { name: '自動' })
|
|
fireEvent.click (checkboxes[0])
|
|
fireEvent.click (checkboxes[1])
|
|
|
|
const textboxes = screen.getAllByRole ('textbox')
|
|
fireEvent.change (textboxes[0], { target: { value: 'https://example.com/post' } })
|
|
fireEvent.change (textboxes[1], { target: { value: '投稿タイトル' } })
|
|
fireEvent.change (textboxes[2], { target: { value: '1 2' } })
|
|
fireEvent.change (textboxes[3], { target: { value: 'tag1 tag2' } })
|
|
fireEvent.click (screen.getByRole ('button', { name: '追加' }))
|
|
|
|
await waitFor (() => {
|
|
expect (api.apiPost).toHaveBeenCalledWith (
|
|
'/posts',
|
|
expect.any (FormData),
|
|
{ headers: { 'Content-Type': 'multipart/form-data' } },
|
|
)
|
|
})
|
|
const formData = api.apiPost.mock.calls[0]?.[1] as FormData
|
|
expect (formData.get ('url')).toBe ('https://example.com/post')
|
|
expect (formData.get ('title')).toBe ('投稿タイトル')
|
|
expect (formData.get ('parent_post_ids')).toBe ('1 2')
|
|
expect (formData.get ('tags')).toBe ('tag1 tag2')
|
|
expect (toastApi.toast).toHaveBeenCalledWith ({ title: '投稿成功!' })
|
|
})
|
|
|
|
it ('shows 422 validation errors for post fields', async () => {
|
|
api.apiGet.mockResolvedValue ([])
|
|
api.isApiError.mockReturnValue (true)
|
|
api.apiPost.mockRejectedValueOnce ({
|
|
response: {
|
|
status: 422,
|
|
data: {
|
|
type: 'validation_error',
|
|
message: '入力内容を確認してください.',
|
|
errors: { tags: ['ニコニコ・タグは直接指定できません.'] },
|
|
base_errors: ['投稿内容を確認してください.'],
|
|
},
|
|
},
|
|
})
|
|
|
|
renderWithProviders (<PostNewPage user={buildUser ({ role: 'member' })}/>)
|
|
|
|
const checkboxes = screen.getAllByRole ('checkbox', { name: '自動' })
|
|
fireEvent.click (checkboxes[0])
|
|
fireEvent.click (checkboxes[1])
|
|
|
|
const textboxes = screen.getAllByRole ('textbox')
|
|
fireEvent.change (textboxes[0], { target: { value: 'https://example.com/post' } })
|
|
fireEvent.change (textboxes[1], { target: { value: '投稿タイトル' } })
|
|
fireEvent.change (textboxes[3], { target: { value: 'nico:nico_tag' } })
|
|
fireEvent.click (screen.getByRole ('button', { name: '追加' }))
|
|
|
|
expect (await screen.findByText ('投稿内容を確認してください.')).toBeInTheDocument ()
|
|
expect (screen.getByText ('ニコニコ・タグは直接指定できません.')).toBeInTheDocument ()
|
|
expect (screen.getAllByRole ('textbox')[3]).toHaveAttribute ('aria-invalid', 'true')
|
|
})
|
|
})
|