// @vitest-environment jsdom import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest'; import {act, cleanup, screen} from '@testing-library/react'; import {toast} from 'sonner'; import SettingsPage from './SettingsPage.jsx'; import {fetchRoutes, json} from '../test/fetchRoutes.js'; import {renderWithProviders} from '../test/renderWithProviders.jsx'; // Like react-i18next: a language change re-renders every subscriber with a fresh `t`. vi.mock('react-i18next', async () => { const {useSyncExternalStore} = await import('react'); const listeners = new Set(); const state = {language: 'de', t: (key) => key}; const i18n = { get language() { return state.language; }, changeLanguage: vi.fn((language) => { state.language = language; state.t = (key) => key; listeners.forEach((listener) => listener()); }), }; const subscribe = (listener) => { listeners.add(listener); return () => listeners.delete(listener); }; return {useTranslation: () => ({t: useSyncExternalStore(subscribe, () => state.t), i18n}), i18n}; }); vi.mock('sonner', () => ({toast: {success: vi.fn(), error: vi.fn(), info: vi.fn()}})); const profile = { id: 1, email: 'a@b.de', role: 'USER', displayName: 'Lobo', steamId: '76561198005679788', steamIdVerified: true, settings: {useDarkTheme: true, language: 'de', publicProfile: false}, }; describe('SettingsPage Steam toast', () => { beforeEach(() => { localStorage.setItem('tbp_session', '1'); fetchRoutes({ 'GET /api/users/me': json(200, profile), 'POST /api/auth/refresh': {ok: true, status: 204, json: async () => { throw new SyntaxError('no body'); }}, 'GET /api/version': json(404, {}), 'GET /api/follows': json(200, {following: [], followers: []}), }); }); afterEach(() => { cleanup(); localStorage.clear(); vi.clearAllMocks(); }); it('shows the linked toast once, also after a language change', async () => { renderWithProviders(, {path: '/settings', entries: ['/settings?steam=linked']}); await screen.findByText('SETTINGS.STEAM_LINK.VERIFIED'); expect(toast.success).toHaveBeenCalledTimes(1); const {i18n} = await import('react-i18next'); await act(async () => { i18n.changeLanguage('en'); }); expect(toast.success).toHaveBeenCalledTimes(1); }); });