Reviewed-on: #379 Co-authored-by: miteruzo <miteruzo@naver.com> Co-committed-by: miteruzo <miteruzo@naver.com>
このコミットはPull リクエスト #379 でマージされました.
このコミットが含まれているのは:
@@ -0,0 +1,54 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import { Route, Routes } from 'react-router-dom'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import WikiDetailPage from '@/pages/wiki/WikiDetailPage'
|
||||
import { buildTag, buildWikiPage } from '@/test/factories'
|
||||
import { renderWithProviders } from '@/test/render'
|
||||
|
||||
const wikiApi = vi.hoisted (() => ({
|
||||
fetchWikiPage: vi.fn (),
|
||||
fetchWikiPageByTitle: vi.fn (),
|
||||
}))
|
||||
|
||||
const tagsApi = vi.hoisted (() => ({
|
||||
fetchTagByName: vi.fn (),
|
||||
}))
|
||||
|
||||
const postsApi = vi.hoisted (() => ({
|
||||
fetchPosts: vi.fn (),
|
||||
}))
|
||||
|
||||
vi.mock ('@/lib/wiki', () => wikiApi)
|
||||
vi.mock ('@/lib/tags', () => tagsApi)
|
||||
vi.mock ('@/lib/posts', () => postsApi)
|
||||
|
||||
describe ('WikiDetailPage', () => {
|
||||
it ('renders deprecated state outside the wiki title link', async () => {
|
||||
wikiApi.fetchWikiPageByTitle.mockResolvedValueOnce (buildWikiPage ({
|
||||
title: '旧タグ',
|
||||
deprecatedAt: '2026-06-01T00:00:00.000Z',
|
||||
}))
|
||||
tagsApi.fetchTagByName.mockResolvedValueOnce (buildTag ({
|
||||
name: '旧タグ',
|
||||
deprecatedAt: '2026-06-01T00:00:00.000Z',
|
||||
}))
|
||||
postsApi.fetchPosts.mockResolvedValueOnce ({ posts: [], count: 0 })
|
||||
|
||||
renderWithProviders (
|
||||
<Routes>
|
||||
<Route path="/wiki/:title" element={<WikiDetailPage/>}/>
|
||||
</Routes>,
|
||||
{ route: '/wiki/%E6%97%A7%E3%82%BF%E3%82%B0' },
|
||||
)
|
||||
|
||||
const marker = await screen.findByText ('(廃止)')
|
||||
const heading = marker.closest ('h1')
|
||||
const link = screen.getByRole ('link', { name: '旧タグ' })
|
||||
|
||||
expect (heading).not.toBeNull ()
|
||||
expect (heading!).toHaveTextContent ('旧タグ(廃止)')
|
||||
expect (link).toBeInTheDocument ()
|
||||
expect (marker.closest ('a')).toBeNull ()
|
||||
})
|
||||
})
|
||||
@@ -39,6 +39,7 @@ const WikiDetailPage: FC = () => {
|
||||
queryFn: () => fetchWikiPageByTitle (title, { version }) })
|
||||
|
||||
const effectiveTitle = wikiPage?.title ?? title
|
||||
const deprecated = wikiPage?.deprecatedAt != null
|
||||
|
||||
const { data: tag } = useQuery ({
|
||||
enabled: Boolean (effectiveTitle),
|
||||
@@ -88,7 +89,7 @@ const WikiDetailPage: FC = () => {
|
||||
return (
|
||||
<MainArea>
|
||||
<Helmet>
|
||||
<title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
|
||||
<title>{`${ effectiveTitle }${ deprecated ? '(廃止)' : '' } Wiki | ${ SITE_TITLE }`}</title>
|
||||
{!(wikiPage?.body) && <meta name="robots" content="noindex"/>}
|
||||
</Helmet>
|
||||
|
||||
@@ -110,10 +111,13 @@ const WikiDetailPage: FC = () => {
|
||||
|
||||
<article className="prose dark:prose-invert mx-auto p-4">
|
||||
<h1 className="prose-a:no-underline">
|
||||
<TagLink tag={tag ?? defaultTag}
|
||||
<TagLink tag={tag ?? { ...defaultTag,
|
||||
name: effectiveTitle,
|
||||
deprecatedAt: wikiPage?.deprecatedAt ?? null }}
|
||||
withWiki={false}
|
||||
withCount={false}
|
||||
{...(version && { to: `/wiki/${ encodeURIComponent (title) }` })}/>
|
||||
{deprecated && <span>(廃止)</span>}
|
||||
</h1>
|
||||
{loading ? <div>Loading...</div> : <WikiBody title={title} body={wikiPage?.body}/>}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ describe ('WikiDiffPage', () => {
|
||||
api.apiGet.mockResolvedValueOnce ({
|
||||
wikiPageId: 3,
|
||||
title: '差分対象',
|
||||
deprecatedAt: null,
|
||||
olderRevisionId: 1,
|
||||
newerRevisionId: 2,
|
||||
diff: [
|
||||
@@ -43,4 +44,26 @@ describe ('WikiDiffPage', () => {
|
||||
expect (screen.getByText ('added line')).toBeInTheDocument ()
|
||||
expect (screen.getByText ('removed line')).toBeInTheDocument ()
|
||||
})
|
||||
|
||||
it ('appends deprecated state to the wiki title', async () => {
|
||||
api.apiGet.mockResolvedValueOnce ({
|
||||
wikiPageId: 3,
|
||||
title: '廃止 Wiki',
|
||||
deprecatedAt: '2026-06-01T00:00:00.000Z',
|
||||
olderRevisionId: 1,
|
||||
newerRevisionId: 2,
|
||||
diff: [],
|
||||
})
|
||||
|
||||
renderWithProviders (
|
||||
<Routes>
|
||||
<Route path="/wiki/:id/diff" element={<WikiDiffPage/>}/>
|
||||
</Routes>,
|
||||
{ route: '/wiki/3/diff?from=1&to=2' },
|
||||
)
|
||||
|
||||
expect (await screen.findByRole ('heading', {
|
||||
name: '廃止 Wiki(廃止)',
|
||||
})).toBeInTheDocument ()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -23,6 +23,9 @@ const WikiDiffPage: FC = () => {
|
||||
const query = new URLSearchParams (location.search)
|
||||
const from = query.get ('from')
|
||||
const to = query.get ('to')
|
||||
const displayTitle = diff
|
||||
? `${ diff.title }${ diff.deprecatedAt != null ? '(廃止)' : '' }`
|
||||
: ''
|
||||
|
||||
useEffect (() => {
|
||||
void (async () => {
|
||||
@@ -33,9 +36,9 @@ const WikiDiffPage: FC = () => {
|
||||
return (
|
||||
<MainArea>
|
||||
<Helmet>
|
||||
<title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title>
|
||||
<title>{`Wiki 差分: ${ displayTitle } | ${ SITE_TITLE }`}</title>
|
||||
</Helmet>
|
||||
<PageTitle>{diff?.title}</PageTitle>
|
||||
<PageTitle>{displayTitle}</PageTitle>
|
||||
<div className="prose mx-auto p-4">
|
||||
{diff
|
||||
? (
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { screen } from '@testing-library/react'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import WikiHistoryPage from '@/pages/wiki/WikiHistoryPage'
|
||||
import { renderWithProviders } from '@/test/render'
|
||||
|
||||
const api = vi.hoisted (() => ({
|
||||
apiGet: vi.fn (),
|
||||
}))
|
||||
|
||||
vi.mock ('@/lib/api', () => api)
|
||||
|
||||
describe ('WikiHistoryPage', () => {
|
||||
it ('renders deprecated state outside the wiki title link', async () => {
|
||||
api.apiGet.mockResolvedValueOnce ([{
|
||||
revisionId: 2,
|
||||
pred: 1,
|
||||
succ: null,
|
||||
wikiPage: {
|
||||
id: 3,
|
||||
title: '旧タグ',
|
||||
deprecatedAt: '2026-06-01T00:00:00.000Z',
|
||||
},
|
||||
user: { id: 4, name: 'tester' },
|
||||
kind: 'content',
|
||||
message: 'updated',
|
||||
timestamp: '2026-06-02T00:00:00.000Z',
|
||||
}])
|
||||
|
||||
renderWithProviders (<WikiHistoryPage/>)
|
||||
|
||||
const link = await screen.findByRole ('link', { name: '旧タグ' })
|
||||
const marker = screen.getByText ('(廃止)')
|
||||
|
||||
expect (link).toHaveAttribute ('href', '/wiki/%E6%97%A7%E3%82%BF%E3%82%B0?version=2')
|
||||
expect (marker.closest ('a')).toBeNull ()
|
||||
})
|
||||
})
|
||||
@@ -59,6 +59,7 @@ const WikiHistoryPage: FC = () => {
|
||||
to={`/wiki/${ encodeURIComponent (change.wikiPage.title) }?version=${ change.revisionId }`}>
|
||||
{change.wikiPage.title}
|
||||
</PrefetchLink>
|
||||
{change.wikiPage.deprecatedAt != null && <span>(廃止)</span>}
|
||||
</td>
|
||||
<td className="p-2">
|
||||
{change.pred == null ? '新規' : '更新'}
|
||||
|
||||
@@ -42,4 +42,21 @@ describe ('WikiSearchPage', () => {
|
||||
})
|
||||
expect (await screen.findByRole ('link', { name: '検索結果' })).toBeInTheDocument ()
|
||||
})
|
||||
|
||||
it ('marks deprecated wiki tags in the result title', async () => {
|
||||
api.apiGet.mockResolvedValueOnce ([
|
||||
buildWikiPage ({
|
||||
title: '旧タグ',
|
||||
deprecatedAt: '2026-06-01T00:00:00.000Z',
|
||||
}),
|
||||
])
|
||||
|
||||
renderWithProviders (<WikiSearchPage/>)
|
||||
|
||||
const link = await screen.findByRole ('link', { name: '旧タグ' })
|
||||
const marker = screen.getByText ('(廃止)')
|
||||
|
||||
expect (link).toBeInTheDocument ()
|
||||
expect (marker.closest ('a')).toBeNull ()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -86,6 +86,7 @@ const WikiSearchPage: FC = () => {
|
||||
<PrefetchLink to={`/wiki/${ encodeURIComponent (page.title) }`}>
|
||||
{page.title}
|
||||
</PrefetchLink>
|
||||
{page.deprecatedAt != null && <span>(廃止)</span>}
|
||||
</td>
|
||||
<td className="p-2">
|
||||
{dateString (page.updatedAt)}
|
||||
|
||||
新しい課題から参照
ユーザをブロックする