import { QueryClient } from '@tanstack/react-query' import { beforeEach, describe, expect, it, vi } from 'vitest' import { prefetchForURL } from '@/lib/prefetchers' const postsApi = vi.hoisted (() => ({ fetchPost: vi.fn (), fetchPostChanges: vi.fn (), fetchPosts: vi.fn (), })) const tagsApi = vi.hoisted (() => ({ fetchNicoTags: vi.fn (), fetchTag: vi.fn (), fetchTagByName: vi.fn (), fetchTagChanges: vi.fn (), fetchTags: vi.fn (), })) const wikiApi = vi.hoisted (() => ({ fetchWikiPage: vi.fn (), fetchWikiPageByTitle: vi.fn (), fetchWikiPages: vi.fn (), fetchWikiPageByReference: vi.fn (), fetchWikiAutolinkCandidates: vi.fn (), fetchWikiTag: vi.fn (), })) vi.mock ('@/lib/posts', () => postsApi) vi.mock ('@/lib/tags', () => tagsApi) vi.mock ('@/lib/wiki', () => wikiApi) const qc = () => new QueryClient ({ defaultOptions: { queries: { retry: false } }, }) describe ('prefetchForURL', () => { beforeEach (() => { vi.clearAllMocks () postsApi.fetchPosts.mockResolvedValue ({ posts: [], count: 0 }) postsApi.fetchPost.mockResolvedValue ({ id: 1 }) postsApi.fetchPostChanges.mockResolvedValue ({ versions: [], count: 0 }) tagsApi.fetchTags.mockResolvedValue ({ tags: [], count: 0 }) tagsApi.fetchNicoTags.mockResolvedValue ({ tags: [], count: 0 }) tagsApi.fetchTag.mockResolvedValue ({ id: 1 }) tagsApi.fetchTagByName.mockResolvedValue (null) tagsApi.fetchTagChanges.mockResolvedValue ({ versions: [], count: 0 }) wikiApi.fetchWikiPages.mockResolvedValue ([]) wikiApi.fetchWikiPage.mockResolvedValue ({ id: 1 }) wikiApi.fetchWikiPageByTitle.mockResolvedValue (null) wikiApi.fetchWikiPageByReference.mockResolvedValue (null) wikiApi.fetchWikiAutolinkCandidates.mockResolvedValue ([]) wikiApi.fetchWikiTag.mockResolvedValue (null) }) it ('prefetches post indexes from query parameters', async () => { await prefetchForURL ( qc (), '/ja/posts?tags=a+b&match=any&page=2&limit=5&order=title%3Aasc', ) expect (postsApi.fetchPosts).toHaveBeenCalledWith ( expect.objectContaining ({ tags: 'a b', match: 'any', page: 2, limit: 5, order: 'title:asc', }), 'ja', ) }) it ('prefetches post detail pages', async () => { await prefetchForURL (qc (), '/ja/posts/12') expect (postsApi.fetchPost).toHaveBeenCalledWith ('12', 'ja') }) it ('prefetches tag indexes from query parameters', async () => { await prefetchForURL ( qc (), '/ja/tags?post=9&name=x&category=general&page=4&post_count_lte=10', ) expect (tagsApi.fetchTags).toHaveBeenCalledWith ( expect.objectContaining ({ post: 9, name: 'x', category: 'general', page: 4, postCountLTE: 10, }), 'ja', ) }) it ('prefetches nico tag indexes and their alias from query parameters', async () => { await prefetchForURL ( qc (), '/ja/tags/nico?name=source&linked_tag=destination' + '&link_status=linked&page=3&limit=10', ) await prefetchForURL (qc (), '/ja/nico/tags?page=2') expect (tagsApi.fetchNicoTags).toHaveBeenNthCalledWith (1, { name: 'source', linkedTag: 'destination', linkStatus: 'linked', page: 3, limit: 10, order: 'updated_at:desc', }, 'ja') expect (tagsApi.fetchNicoTags).toHaveBeenNthCalledWith (2, { name: '', linkedTag: '', linkStatus: 'all', page: 2, limit: 20, order: 'updated_at:desc', }, 'ja') }) it ('prefetches wiki show pages and related tag/post data', async () => { wikiApi.fetchWikiPageByReference.mockResolvedValueOnce ({ id: 3, title: 'Actual', body: 'body', }) await prefetchForURL (qc (), '/ja/wiki/Alias') expect (wikiApi.fetchWikiPageByReference).toHaveBeenCalledWith ( 'Alias', { version: undefined }, 'ja') expect (wikiApi.fetchWikiPage).not.toHaveBeenCalled () expect (wikiApi.fetchWikiTag).toHaveBeenCalledWith ({ name: 'Actual' }, 'ja') expect (postsApi.fetchPosts).toHaveBeenCalledWith ( expect.objectContaining ({ tags: 'Actual', limit: 8 }), 'ja', ) }) it ('ignores routes without a prefetcher', async () => { await prefetchForURL (qc (), '/ja/unknown') expect (postsApi.fetchPosts).not.toHaveBeenCalled () expect (tagsApi.fetchTags).not.toHaveBeenCalled () expect (wikiApi.fetchWikiPages).not.toHaveBeenCalled () }) it ('prefetches external tag post history without treating it as an internal tag', async () => { await prefetchForURL ( qc (), '/ja/posts/changes?external_tag=12&page=2&limit=50', ) expect (postsApi.fetchPostChanges).toHaveBeenCalledWith ({ externalTag: '12', page: 2, limit: 50, }, 'ja') expect (tagsApi.fetchTag).not.toHaveBeenCalled () }) })