import { fireEvent, screen, waitFor } from '@testing-library/react' import { Route, Routes } from 'react-router-dom' import { beforeEach, describe, expect, it, vi } from 'vitest' import MaterialDetailPage from '@/pages/materials/MaterialDetailPage' import { buildMaterial, buildTag } from '@/test/factories' import { renderWithProviders } from '@/test/render' const api = vi.hoisted (() => ({ apiGet: vi.fn (), apiPatch: vi.fn (), apiPut: vi.fn (), })) const wikiApi = vi.hoisted (() => ({ fetchWikiPages: vi.fn (), })) const toastApi = vi.hoisted (() => ({ toast: vi.fn (), })) vi.mock ('@/lib/api', () => api) vi.mock ('@/lib/wiki', () => wikiApi) vi.mock ('@/components/ui/use-toast', () => toastApi) const renderPage = () => renderWithProviders ( }/> , { route: '/materials/8' }, ) describe ('MaterialDetailPage', () => { beforeEach (() => { vi.clearAllMocks () api.apiGet.mockResolvedValue ([]) wikiApi.fetchWikiPages.mockResolvedValue ([]) vi.stubGlobal ('fetch', vi.fn (async () => ({ blob: async () => new Blob (['image'], { type: 'image/png' }), }))) }) it ('loads and displays material detail', async () => { api.apiGet.mockResolvedValueOnce ( buildMaterial ({ id: 8, tag: buildTag ({ name: '素材タグ' }), file: 'image.png', contentType: 'image/png', }), ) renderPage () await waitFor (() => { expect (api.apiGet).toHaveBeenCalledWith ('/materials/8') }) expect (await screen.findByAltText ('素材タグ')).toHaveAttribute ('src', 'image.png') }) it ('submits edited material fields', async () => { api.apiGet.mockResolvedValueOnce ( buildMaterial ({ id: 8, tag: buildTag ({ name: 'old' }), url: '' }), ) api.apiPut.mockResolvedValueOnce ( buildMaterial ({ id: 8, tag: buildTag ({ name: 'new' }) }), ) renderPage () fireEvent.click (await screen.findByText ('編輯')) const textboxes = screen.getAllByRole ('textbox') fireEvent.change (textboxes[0], { target: { value: 'new' } }) fireEvent.change (textboxes[1], { target: { value: 'https://example.com/ref' } }) fireEvent.change (textboxes[2], { target: { value: '素材/new.png' } }) fireEvent.click (screen.getByRole ('button', { name: '更新' })) await waitFor (() => { expect (api.apiPut).toHaveBeenCalledWith ('/materials/8', expect.any (FormData)) }) const formData = api.apiPut.mock.calls[0]?.[1] as FormData expect (formData.get ('tag')).toBe ('new') expect (formData.get ('url')).toBe ('https://example.com/ref') expect (formData.get ('export_paths[legacy_drive]')).toBe ('素材/new.png') expect (toastApi.toast).toHaveBeenCalledWith ({ title: '更新成功!' }) }) })