import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { act, render, screen, waitFor, within } from '@testing-library/react' import { HelmetProvider } from 'react-helmet-async' import { beforeEach, describe, expect, it, vi } from 'vitest' import { apiGet } from '@/lib/api' import { helpKeys } from '@/lib/queryKeys' import App, { pageRoutes } from '@/App' import { helpFixture } from '@/test/helpFixtures' vi.hoisted (() => { window.history.replaceState (null, '', '/ja/help/changes') }) vi.mock ('@/lib/help', async () => (await import ('@/test/helpFixtures')).helpFixture.api) vi.mock ('@/lib/api', () => ({ apiGet: vi.fn (), apiPost: async () => ({}), isApiError: () => false })) vi.mock ('@/components/TopNav', () => ({ default: () => null })) vi.mock ('@/components/DevModeWatermark', () => ({ default: () => null })) vi.mock ('@/lib/useClientBehaviourSettings', () => ({ useClientBehaviourSettings: () => ({ animation: 'off', linkPreload: 'off' }) })) describe ('Help global edition history', () => { beforeEach (() => { window.history.replaceState (null, '', '/ja/help/changes') helpFixture.reset () vi.mocked (apiGet).mockResolvedValue ({ locales: [{ code: 'ja', name: '日本語' }] }) }) it ('routes /help/changes to published editions in date and numeric order', async () => { // Resolve the real lazy route before waiting for its asynchronously loaded data. const route = pageRoutes (null, () => {}).find (route => route.path === 'help/changes')! expect (route.handle?.preload).toBeTypeOf ('function') await act (async () => { await route.handle!.preload! ('ja') }) const client = new QueryClient ({ defaultOptions: { queries: { retry: false } } }) const { container } = render ( ) // Wait for the query started by the actual route, separately from DOM discovery. await waitFor (() => expect (client.getQueryCache ().find ({ queryKey: helpKeys.changes ('ja') })).toBeDefined ()) const changes = client.getQueryCache ().find ({ queryKey: helpKeys.changes ('ja') }) await act (async () => { await changes!.promise }) expect (changes!.state.status).toBe ('success') expect (changes!.state.data).toHaveLength (6) const table = await screen.findByRole ('table') const links = within (table).getAllByRole ('link') const editions = links.map (link => link.getAttribute ('href')) .filter (href => href?.startsWith ('/ja/help/') && href.includes ('edition=')) expect (editions).toEqual ([ `/ja/help/${encodeURIComponent ('設定 手順')}?edition=2026-10-03`, '/ja/help/guide?edition=2026-10-02.10', '/ja/help/guide?edition=2026-10-02.3', '/ja/help/guide?edition=2026-10-02.2', '/ja/help/guide?edition=2026-10-02', '/ja/help/guide?edition=2026-10-01']) expect (container).toHaveTextContent ('旧ホーム') expect (screen.getAllByRole ('columnheader').map (cell => cell.textContent)) .toEqual (['差分', 'タイトル', '有効開始年月日']) expect (container).not.toHaveTextContent ('未公開ホーム') expect (container).not.toHaveTextContent ('Invalid Date') expect (container.textContent).not.toMatch (/\d{1,2}:\d{2}/) expect (screen.getAllByRole ('link', { name: '差分' }).map (link => link.getAttribute ('href'))).toEqual ([ '/ja/help/guide/diff?from=2026-10-02.3&to=2026-10-02.10', '/ja/help/guide/diff?from=2026-10-02.2&to=2026-10-02.3', '/ja/help/guide/diff?from=2026-10-02&to=2026-10-02.2', '/ja/help/guide/diff?from=2026-10-01&to=2026-10-02']) expect (apiGet).toHaveBeenCalledWith ('/locales') expect (window.location.pathname).toBe ('/ja/help/changes') }) })