// @vitest-environment jsdom import {afterEach, describe, expect, it, vi} from 'vitest'; import {cleanup, render, screen, waitFor} from '@testing-library/react'; import {MemoryRouter, Route, Routes} from 'react-router-dom'; import PublicProfilePage from './PublicProfilePage.jsx'; import {PreferencesProvider} from '../context/PreferencesContext.jsx'; vi.mock('react-i18next', () => import('../test/i18n-mock.js')); const library = { totalGames: 233, totalPlaytimeMinutes: 60000, byStatus: {BACKLOG: 142, PLAYING: 6, FINISHED: 51, COMPLETED: 9, DROPPED: 25}, playing: [{appid: 220, name: 'Half-Life 2', playtimeMinutes: 300, status: 'PLAYING', rating: null}], finished: [{appid: 620, name: 'Portal 2', playtimeMinutes: 900, status: 'COMPLETED', rating: 5}], }; function mockBackends({profileStatus = 200, libraryStatus = 200} = {}) { globalThis.fetch = vi.fn(async (url) => { if (url.includes('/api/public/profiles/library')) { return {ok: libraryStatus === 200, status: libraryStatus, json: async () => library}; } return {ok: profileStatus === 200, status: profileStatus, json: async () => ({displayName: 'Lobo', memberSince: '2026-03-02', ticket: 'the-ticket'})}; }); } const renderPage = (name = 'Lobo') => render( }/> , ); describe('PublicProfilePage', () => { afterEach(cleanup); it('asks Auth for the ticket, then Core for the library with it', async () => { mockBackends(); renderPage('Lo bo'); expect(await screen.findByText('Portal 2')).toBeTruthy(); expect(fetch.mock.calls[0][0]).toMatch(/\/api\/public\/profiles\/Lo%20bo$/); expect(fetch.mock.calls[1][1].headers['X-Profile-Ticket']).toBe('the-ticket'); expect(screen.getByText('Lobo')).toBeTruthy(); expect(screen.getByText('Half-Life 2')).toBeTruthy(); expect(screen.getByText('233')).toBeTruthy(); expect(screen.queryByText('PROFILE.PERFECT_GAMES')).toBeNull(); }); it('shows perfect games and the average completion when there are achievements', async () => { library.perfectGames = 12; library.averageCompletion = 64.5; try { mockBackends(); renderPage(); expect(await screen.findByText('PROFILE.PERFECT_GAMES')).toBeTruthy(); expect(screen.getByText('12')).toBeTruthy(); expect(screen.getByText('64,5 %')).toBeTruthy(); } finally { delete library.perfectGames; delete library.averageCompletion; } }); it('says the profile is unknown or private on a 404', async () => { mockBackends({profileStatus: 404}); renderPage(); expect(await screen.findByText('PROFILE.NOT_FOUND')).toBeTruthy(); expect(fetch).toHaveBeenCalledTimes(1); }); it('shows an error when Core fails', async () => { mockBackends({libraryStatus: 500}); renderPage(); await waitFor(() => expect(screen.getByText('PROFILE.ERROR_LOAD')).toBeTruthy()); }); });