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 ()
})
})