import { fireEvent, screen, waitFor } from '@testing-library/react' import { Route, Routes } from 'react-router-dom' import { beforeEach, describe, expect, it, vi } from 'vitest' import PostDetailPage from '@/pages/posts/PostDetailPage' import { buildPost, buildUser } from '@/test/factories' import { renderWithProviders } from '@/test/render' import type { ReactNode } from 'react' const postsApi = vi.hoisted (() => ({ fetchPost: vi.fn (), toggleViewedFlg: vi.fn (), })) const api = vi.hoisted (() => ({ isApiError: vi.fn (() => false), })) vi.mock ('@/lib/posts', () => postsApi) vi.mock ('@/lib/api', () => api) vi.mock ('@/components/PostEmbed', () => ({ default: ({ post }: { post: { url: string } }) =>
Embed:{post.url}
, })) vi.mock ('@/components/TagDetailSidebar', () => ({ default: () => , })) vi.mock ('@/components/PostEditForm', () => ({ default: () =>
Post edit form
, })) vi.mock ('framer-motion', () => ({ motion: { div: ({ children }: { children?: ReactNode }) =>
{children}
, main: ({ children }: { children?: ReactNode }) =>
{children}
, }, })) const renderPage = (user = buildUser ({ role: 'member' })) => renderWithProviders ( }/> , { route: '/posts/9' }, ) describe ('PostDetailPage', () => { beforeEach (() => { vi.clearAllMocks () postsApi.toggleViewedFlg.mockResolvedValue (undefined) }) it ('loads and displays a post detail', async () => { postsApi.fetchPost.mockResolvedValue ( buildPost ({ id: 9, url: 'https://example.com/9', related: [], thumbnail: null, thumbnailBase: null, }), ) renderPage () await waitFor (() => { expect (postsApi.fetchPost).toHaveBeenCalledWith ('9') }) expect (await screen.findByText ('Embed:https://example.com/9')).toBeInTheDocument () expect (screen.getByRole ('button', { name: '未閲覧' })).toBeInTheDocument () expect (screen.getByText ('まだないよ(笑)')).toBeInTheDocument () }) it ('toggles viewed state through the mutation', async () => { postsApi.fetchPost.mockResolvedValue ( buildPost ({ id: 9, viewed: false, thumbnail: null, thumbnailBase: null }), ) renderPage () fireEvent.click (await screen.findByRole ('button', { name: '未閲覧' })) await waitFor (() => { expect (postsApi.toggleViewedFlg).toHaveBeenCalledWith ('9', true) }) }) it ('shows the edit tab for members', async () => { postsApi.fetchPost.mockResolvedValue ( buildPost ({ id: 9, thumbnail: null, thumbnailBase: null }), ) renderPage (buildUser ({ role: 'member' })) fireEvent.click (await screen.findByText ('編輯')) expect (screen.getByText ('Post edit form')).toBeInTheDocument () }) it ('hides the edit tab for guests', async () => { postsApi.fetchPost.mockResolvedValue ( buildPost ({ id: 9, thumbnail: null, thumbnailBase: null }), ) renderPage (buildUser ({ role: 'guest' })) expect (await screen.findByText ('関聯')).toBeInTheDocument () expect (screen.queryByText ('編輯')).not.toBeInTheDocument () }) })