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) }) })