タグ “廃止” 追加 (#378) (#379)

Reviewed-on: #379
Co-authored-by: miteruzo <miteruzo@naver.com>
Co-committed-by: miteruzo <miteruzo@naver.com>
このコミットはPull リクエスト #379 でマージされました.
このコミットが含まれているのは:
2026-06-22 08:40:06 +09:00
committed by みてるぞ
コミット ec2b3d2254
51個のファイルの変更1095行の追加100行の削除
+54
ファイルの表示
@@ -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 ()
})
})
+6 -2
ファイルの表示
@@ -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}/>}
+23
ファイルの表示
@@ -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 ()
})
})
+5 -2
ファイルの表示
@@ -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
? (
+38
ファイルの表示
@@ -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 ()
})
})
+1
ファイルの表示
@@ -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 ? '新規' : '更新'}
+17
ファイルの表示
@@ -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 ()
})
})
+1
ファイルの表示
@@ -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)}