125 行
5.0 KiB
TypeScript
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)
|
|
})
|
|
})
|