refactor(frontend): lint, one session guard, one request helper, one user context

This commit is contained in:
lobo committed 2026-09-29 15:40:55 +02:00
1 parent 111ab1e200
commit d0ea9e900d
78 files changed
+2138 -624

No files matched your search

+26 -5
View File
@@ -2,8 +2,10 @@
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {cleanup, fireEvent, render, screen, waitFor} from '@testing-library/react';
import {MemoryRouter, Route, Routes, useLocation} from 'react-router-dom';
import RequireSession from '../components/RequireSession.jsx';
import Dashboard from './Dashboard.jsx';
import {PreferencesProvider} from '../context/PreferencesContext.jsx';
import {CurrentUserProvider} from '../context/CurrentUserContext.jsx';
vi.mock('react-i18next', () => import('../test/i18n-mock.js'));
vi.mock('../hooks/useLibrarySync.js', () => ({default: () => ({status: 'OK', lastSyncedAt: null, isRunning: false})}));
@@ -33,12 +35,12 @@ describe('Dashboard', () => {
globalThis.fetch = vi.fn(async (url) =>
url.includes('/api/users/me') ? ok({email: 'a@b.de', steamId: '76561198000000000'}) : unauthorized());
render(
<MemoryRouter initialEntries={['/dashboard']}><PreferencesProvider>
<MemoryRouter initialEntries={['/dashboard']}><PreferencesProvider><CurrentUserProvider>
<Routes>
<Route path="/dashboard" element={<><Dashboard/><Spy/></>}/>
<Route element={<RequireSession/>}><Route path="/dashboard" element={<><Dashboard/><Spy/></>}/></Route>
<Route path="/login" element={<Spy/>}/>
</Routes>
</PreferencesProvider></MemoryRouter>,
</CurrentUserProvider></PreferencesProvider></MemoryRouter>,
);
await waitFor(() => expect(fetch.mock.calls.length).toBeGreaterThanOrEqual(5));
@@ -65,9 +67,9 @@ describe('Dashboard', () => {
return ok({content: [], total: 0, byStatus: {}});
});
return render(
<MemoryRouter initialEntries={['/dashboard']}><PreferencesProvider>
<MemoryRouter initialEntries={['/dashboard']}><PreferencesProvider><CurrentUserProvider>
<Dashboard/>
</PreferencesProvider></MemoryRouter>,
</CurrentUserProvider></PreferencesProvider></MemoryRouter>,
).container;
};
@@ -150,4 +152,23 @@ describe('Dashboard', () => {
await waitFor(() => expect(container.querySelector(`img[src="${avatar}"]`)).not.toBeNull());
expect(container.querySelector('img[src*="library_hero"]')).toBeNull();
});
it('shows the page when a card answers 200 without a JSON body', async () => {
// No Steam ID, so no activity and achievements are asked.
globalThis.fetch = vi.fn(async (url) => {
if (url.includes('/api/users/me')) return ok({email: 'a@b.de', displayName: 'Lobo'});
if (url.includes('/api/library/games-count')) return ok({count: 1, hasSteamId: true});
if (url.includes('sort=playtimeMinutes') && !url.includes('status=')) {
return {ok: true, status: 200, json: async () => { throw new SyntaxError('Unexpected token <'); }};
}
return ok({content: [], total: 0, byStatus: {}});
});
render(
<MemoryRouter initialEntries={['/dashboard']}><PreferencesProvider><CurrentUserProvider>
<Dashboard/>
</CurrentUserProvider></PreferencesProvider></MemoryRouter>,
);
expect(await screen.findByText(/DASHBOARD.HELLO/)).toBeTruthy();
});
});