Files
ToBePlayed-Frontend/src/components/GameMergeDialog.test.jsx
T

84 lines
3.6 KiB
React

// @vitest-environment jsdom
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {cleanup, fireEvent, render, screen, waitFor} from '@testing-library/react';
import {MemoryRouter} from 'react-router-dom';
import {toast} from 'sonner';
import GameMergeDialog from './GameMergeDialog.jsx';
import {fetchRoutes, json} from '../test/fetchRoutes.js';
vi.mock('react-i18next', () => import('../test/i18n-mock.js'));
vi.mock('sonner', () => ({toast: {success: vi.fn(), error: vi.fn()}}));
const hades = {appid: 1145360, name: 'Hades'};
const hit = (appid, name) => ({appid, igdbId: Math.abs(appid), name, year: 2020, imageUrl: null,
platforms: ['Switch'], inLibrary: false, inCatalog: true});
function renderDialog(game, post, results) {
fetchRoutes({
'GET /api/library/game-search': json(200, {available: true, results}),
[`POST /api/library/games/${game.appid}/merge`]: post,
});
const onMerged = vi.fn();
render(<MemoryRouter><GameMergeDialog game={game} open onOpenChange={vi.fn()} onMerged={onMerged}/></MemoryRouter>);
return onMerged;
}
const search = (value) => fireEvent.change(screen.getByRole('searchbox'), {target: {value}});
beforeEach(() => {
localStorage.setItem('tbp_session', '1');
});
afterEach(() => {
cleanup();
localStorage.clear();
vi.clearAllMocks();
});
describe('GameMergeDialog', () => {
it('merges the picked game after the confirm step', async () => {
const onMerged = renderDialog(hades, json(200, {appid: 1145360}),
[hit(1145360, 'Hades'), hit(-113112, 'Hades (Switch)'), hit(1145350, 'Hades II'),
{...hit(-4711, 'Hades Fan Remake'), inCatalog: false}]);
search('hades');
const offered = await screen.findByRole('button', {name: /Hades \(Switch\)/});
// The page's own game, other Steam games and games not in ToBePlayed are not offered.
expect(screen.queryByRole('button', {name: /^Hades \(2020\)/})).toBeNull();
expect(screen.queryByRole('button', {name: /Hades II/})).toBeNull();
expect(screen.queryByRole('button', {name: /Fan Remake/})).toBeNull();
fireEvent.click(offered);
expect(fetch).toHaveBeenCalledTimes(1);
fireEvent.click(screen.getByRole('button', {name: 'MERGE.CONFIRM_BUTTON'}));
await waitFor(() => expect(onMerged).toHaveBeenCalledWith(1145360));
const [url, init] = fetch.mock.calls[1];
expect(url).toContain('/api/library/games/1145360/merge');
expect(JSON.parse(init.body)).toEqual({otherAppid: -113112});
expect(toast.success).toHaveBeenCalledWith('MERGE.DONE');
});
it('goes back from the confirm step without merging', async () => {
renderDialog(hades, json(200, {}), [hit(-113112, 'Hades (Switch)')]);
search('hades');
fireEvent.click(await screen.findByRole('button', {name: /Hades \(Switch\)/}));
fireEvent.click(screen.getByRole('button', {name: 'MERGE.BACK'}));
expect(await screen.findByRole('searchbox')).toBeTruthy();
expect(fetch).toHaveBeenCalledTimes(1);
});
it('says why Core refused the merge', async () => {
const onMerged = renderDialog({appid: -113112, name: 'Hades (Switch)'},
json(404, {code: 'GAME_NOT_FOUND'}), [hit(1145360, 'Hades')]);
search('hades');
fireEvent.click(await screen.findByRole('button', {name: /Hades \(2020\)/}));
fireEvent.click(screen.getByRole('button', {name: 'MERGE.CONFIRM_BUTTON'}));
await waitFor(() => expect(toast.error).toHaveBeenCalledWith('MERGE.ERROR.GAME_NOT_FOUND'));
expect(onMerged).not.toHaveBeenCalled();
});
});