import { fireEvent, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import SettingPage from '@/pages/users/SettingPage' import { buildUser } from '@/test/factories' import { renderWithProviders } from '@/test/render' const api = vi.hoisted (() => ({ apiPut: vi.fn (), isApiError: vi.fn (), })) const toastApi = vi.hoisted (() => ({ toast: vi.fn (), })) vi.mock ('@/lib/api', () => api) vi.mock ('@/components/ui/use-toast', () => toastApi) vi.mock ('@/components/users/UserCodeDialogue', () => ({ default: () => null, })) vi.mock ('@/components/users/InheritDialogue', () => ({ default: () => null, })) describe ('SettingPage', () => { beforeEach (() => { vi.clearAllMocks () api.isApiError.mockReturnValue (false) }) it ('shows loading when user is absent', () => { renderWithProviders () expect (screen.getByText ('Loading...')).toBeInTheDocument () }) it ('updates the current user name', async () => { const user = buildUser ({ id: 11, name: 'old' }) const setUser = vi.fn () api.apiPut.mockResolvedValueOnce ({ ...user, name: 'new' }) renderWithProviders () fireEvent.change (screen.getByRole ('textbox'), { target: { value: 'new' } }) fireEvent.click (screen.getByRole ('button', { name: '更新' })) await waitFor (() => { expect (api.apiPut).toHaveBeenCalledWith ( '/users/11', expect.any (FormData), { headers: { 'Content-Type': 'multipart/form-data' } }, ) }) const formData = api.apiPut.mock.calls[0]?.[1] as FormData expect (formData.get ('name')).toBe ('new') expect (setUser).toHaveBeenCalled () expect (toastApi.toast).toHaveBeenCalledWith ({ title: '設定を更新しました.' }) }) it ('shows validation errors returned for the name field', async () => { const user = buildUser ({ id: 11, name: 'old' }) api.isApiError.mockReturnValue (true) api.apiPut.mockRejectedValueOnce ({ response: { status: 422, data: { type: 'validation_error', message: '入力内容を確認してください.', errors: { name: ['名前は必須です.'] }, base_errors: [], }, }, }) renderWithProviders () fireEvent.change (screen.getByRole ('textbox'), { target: { value: '' } }) fireEvent.click (screen.getByRole ('button', { name: '更新' })) expect (await screen.findByText ('名前は必須です.')).toBeInTheDocument () expect (screen.getByRole ('textbox')).toHaveAttribute ('aria-invalid', 'true') }) })