feat(library): hide and unhide games
Build, Test & Push Frontend / quality-check (push) Successful in 16s
Build, Test & Push Frontend / docker (push) Successful in 22s

This commit is contained in:
lobo committed 2026-09-26 12:27:58 +02:00
1 parent 42ed0afe51
commit 011711fe4f
9 files changed
+180 -14

No files matched your search

+41
View File
@@ -5,6 +5,7 @@ import {MemoryRouter, Route, Routes} from 'react-router-dom';
import GameDetail from './GameDetail.jsx';
import {PreferencesProvider} from '../context/PreferencesContext.jsx';
import {resetBrokenImageReports} from '../utils/brokenImages.js';
import {toast} from 'sonner';
vi.mock('react-i18next', () => import('../test/i18n-mock.js'));
vi.mock('sonner', () => ({toast: {success: vi.fn(), error: vi.fn()}}));
@@ -37,6 +38,46 @@ afterEach(() => {
});
describe('GameDetail', () => {
it('hides a Steam game and shows it again', async () => {
globalThis.fetch = vi.fn(async (url, init) => init?.method === 'PUT'
? {ok: true, status: 200, json: async () => JSON.parse(init.body)}
: {ok: true, status: 200, json: async () => ({...game, source: 'STEAM', hidden: false})});
renderDetail();
fireEvent.click(await screen.findByRole('button', {name: 'GAME_DETAIL.HIDE'}));
expect(await screen.findByText('GAME_DETAIL.HIDDEN_NOTE')).toBeTruthy();
const [url, init] = fetch.mock.calls.find(([, call]) => call?.method === 'PUT');
expect(url).toContain('/api/library/games/220/hidden');
expect(JSON.parse(init.body)).toEqual({hidden: true});
fireEvent.click(screen.getByRole('button', {name: 'GAME_DETAIL.UNHIDE'}));
await waitFor(() => expect(screen.queryByText('GAME_DETAIL.HIDDEN_NOTE')).toBeNull());
expect(screen.getByRole('button', {name: 'GAME_DETAIL.HIDE'})).toBeTruthy();
});
it('keeps the game shown when Core refuses', async () => {
globalThis.fetch = vi.fn(async (url, init) => init?.method === 'PUT'
? {ok: false, status: 409, json: async () => ({code: 'MANUAL_GAME'})}
: {ok: true, status: 200, json: async () => ({...game, source: 'STEAM', hidden: false})});
renderDetail();
fireEvent.click(await screen.findByRole('button', {name: 'GAME_DETAIL.HIDE'}));
await waitFor(() => expect(toast.error).toHaveBeenCalledWith('GAME_DETAIL.HIDE_ERROR'));
expect(screen.queryByText('GAME_DETAIL.HIDDEN_NOTE')).toBeNull();
});
it('offers no hide for a game added by hand', async () => {
globalThis.fetch = vi.fn(async () => ({ok: true, status: 200,
json: async () => ({...game, source: 'MANUAL', platform: 'PS5', hidden: false})}));
renderDetail();
await screen.findByText('GAME_DETAIL.OPEN_IN_STEAM');
expect(screen.queryByRole('button', {name: 'GAME_DETAIL.HIDE'})).toBeNull();
});
it('reports a broken achievement icon once and shows the empty tile', async () => {
const achievement = (apiName) => ({apiName, displayName: apiName, unlocked: false, iconUrl: `https://x/${apiName}.jpg`,
iconGrayUrl: `https://x/${apiName}_gray.jpg`});