ファイル
btrc-hub/frontend/src/lib/wiki.test.ts
T
2026-10-20 20:44:14 +09:00

125 行
5.0 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest'
import { fetchWikiPage, fetchWikiPageByTitle, fetchWikiPages,
switchWikiLocale } from '@/lib/wiki'
const api = vi.hoisted (() => ({ apiGet: vi.fn () }))
vi.mock ('@/lib/api', () => api)
describe ('wiki API functions', () => {
beforeEach (() => {
api.apiGet.mockReset ()
})
it.each (['detail', 'edit', 'diff', 'history'] as const) (
'switches only the Locale for a missing resource on the %s screen',
async view => {
api.apiGet.mockRejectedValue ({
isAxiosError: true, response: { status: 404 } })
const pathname = view === 'history' ? '/wiki/changes'
: `/wiki/${encodeURIComponent ('げいかうい')}${
view === 'detail' ? '' : `/${view}`}`
const search = '?id=missing&from=11&to=12&version=3&page=2'
const params = view === 'history' ? { }
: (view === 'detail' ? { title: 'げいかうい' } : { id: 'げいかうい' })
const path = await switchWikiLocale ({
location: { pathname: `/ain-Kana${pathname}`, search, hash: '#section' },
params,
locale: 'ain-Kana', targetLocale: 'ja' }, view)
expect (path).toBe (`/ja${pathname}${search}#section`)
})
it.each (['wiki', 'tag'] as const) (
'rejects communication failures during the %s lookup', async lookup => {
const error = new Error ('network failure')
if (lookup === 'tag')
api.apiGet.mockRejectedValueOnce ({
isAxiosError: true, response: { status: 404 } })
api.apiGet.mockRejectedValueOnce (error)
await expect (switchWikiLocale ({
location: { pathname: '/ain-Kana/wiki/missing', search: '', hash: '' },
params: { title: 'missing' }, locale: 'ain-Kana', targetLocale: 'ja' }))
.rejects.toBe (error)
})
it.each (['edit', 'diff'] as const) ('keeps the %s screen with the target Wiki ID',
async view => {
api.apiGet.mockResolvedValueOnce ({ id: 101, tagId: 7, resourceType: 'tag_description' })
api.apiGet.mockResolvedValueOnce ({ id: 202, tagId: 7, resourceType: 'tag_description' })
const path = await switchWikiLocale ({
location: { pathname: `/ja/wiki/101/${view}`, search: '?from=11&to=12&keep=1',
hash: '#section' },
params: { id: '101' }, locale: 'ja', targetLocale: 'ain-Kana' }, view)
expect (path).toBe (`/ain-Kana/wiki/202/${view}?keep=1#section`)
expect (api.apiGet).toHaveBeenNthCalledWith (2, '/wiki/101', {
locale: 'ain-Kana', params: { } })
})
it ('keeps filtered history with the target-language description ID', async () => {
api.apiGet.mockResolvedValueOnce ({ id: 101 })
api.apiGet.mockResolvedValueOnce ({ id: 202 })
const path = await switchWikiLocale ({
location: { pathname: '/ja/wiki/changes', search: '?id=101&keep=1', hash: '' },
params: { }, locale: 'ja', targetLocale: 'ain-Kana' }, 'history')
expect (path).toBe ('/ain-Kana/wiki/changes?id=202&keep=1')
})
it ('keeps history and clears its ID filter when the translation is missing', async () => {
api.apiGet.mockResolvedValueOnce ({ id: 101, resourceType: 'tag_description' })
api.apiGet.mockRejectedValueOnce ({
isAxiosError: true, response: { status: 404 } })
api.apiGet.mockResolvedValueOnce ({ id: 7, name: 'シロシ' })
api.apiGet.mockRejectedValueOnce ({
isAxiosError: true, response: { status: 404 } })
api.apiGet.mockResolvedValueOnce ({ id: 7, name: 'シロシ' })
const path = await switchWikiLocale ({
location: { pathname: '/ja/wiki/changes',
search: '?id=101&page=2&keep=1', hash: '#history' },
params: { }, locale: 'ja', targetLocale: 'ain-Kana' }, 'history')
expect (path).toBe ('/ain-Kana/wiki/changes?page=2&keep=1#history')
})
it ('fetches wiki index and show pages with expected parameters', async () => {
api.apiGet.mockResolvedValueOnce ([])
api.apiGet.mockResolvedValueOnce ({ id: 1 })
await fetchWikiPages ({ title: '虹' })
await fetchWikiPage ('1', { version: '3' })
expect (api.apiGet).toHaveBeenNthCalledWith (
1,
'/wiki',
{ locale: 'ja', params: { title: '虹' } })
expect (api.apiGet).toHaveBeenNthCalledWith (
2,
'/wiki/1',
{ locale: 'ja', params: { version: '3' } })
})
it ('encodes title path segments and returns null on misses', async () => {
api.apiGet.mockResolvedValueOnce ({ id: 2 })
api.apiGet.mockRejectedValueOnce ({ isAxiosError: true, response: { status: 404 } })
await fetchWikiPageByTitle ('a/b c', { version: undefined })
await expect (fetchWikiPageByTitle ('missing', { })).resolves.toBeNull ()
expect (api.apiGet).toHaveBeenNthCalledWith (
1,
'/wiki/title/a%2Fb%20c',
{ locale: 'ja', params: { version: undefined } })
})
it.each ([403, 500]) ('preserves HTTP %s errors', async status => {
const error = { isAxiosError: true, response: { status } }
api.apiGet.mockRejectedValueOnce (error)
await expect (fetchWikiPageByTitle ('ホーム', { })).rejects.toBe (error)
})
it ('preserves network failures for callers', async () => {
const error = new Error ('network failure')
api.apiGet.mockRejectedValueOnce (error)
await expect (fetchWikiPageByTitle ('ホーム', { })).rejects.toBe (error)
})
})