|
- 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 } }) => <div>Embed:{post.url}</div>,
- }))
- vi.mock ('@/components/TagDetailSidebar', () => ({
- default: () => <aside>Tag sidebar</aside>,
- }))
- vi.mock ('@/components/PostEditForm', () => ({
- default: () => <div>Post edit form</div>,
- }))
- vi.mock ('framer-motion', () => ({
- motion: {
- div: ({ children }: { children?: ReactNode }) => <div>{children}</div>,
- main: ({ children }: { children?: ReactNode }) => <main>{children}</main>,
- },
- }))
-
- const renderPage = (user = buildUser ({ role: 'member' })) =>
- renderWithProviders (
- <Routes>
- <Route path="/posts/:id" element={<PostDetailPage user={user}/>}/>
- </Routes>,
- { 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 ()
- })
- })
|