// @vitest-environment jsdom import {afterEach, describe, expect, it, vi} from 'vitest'; import {cleanup, fireEvent, render, screen} from '@testing-library/react'; import {MemoryRouter} from 'react-router-dom'; import AchievementsCard from './AchievementsCard.jsx'; import {StatDrillProvider} from './stats/StatDrill.jsx'; import {fetchRoutes, json} from '../test/fetchRoutes.js'; vi.mock('react-i18next', () => import('../test/i18n-mock.js')); const summary = (extra = {}) => ({ unlocked: 24, startedGames: 4, perfectGames: 2, averageCompletion: 71.3, pendingGames: 0, hiddenGames: 0, closest: [{appid: 20, name: 'Portal 2', unlocked: 3, total: 4}], ...extra, }); const renderCard = (data) => render(); describe('AchievementsCard', () => { afterEach(() => { cleanup(); }); it('shows the totals and links the games closest to 100 %', () => { renderCard(summary()); expect(screen.getByText('24')).toBeTruthy(); expect(screen.getByText('2')).toBeTruthy(); expect(screen.getByText('71,3 %')).toBeTruthy(); expect(screen.getByRole('link', {name: /Portal 2/}).getAttribute('href')).toBe('/library/20'); expect(screen.getByText('3 / 4')).toBeTruthy(); expect(screen.queryByText(/DASHBOARD.ACHIEVEMENTS.PENDING/)).toBeNull(); }); it('says how many games are still syncing', () => { renderCard(summary({pendingGames: 7})); expect(screen.getByText('DASHBOARD.ACHIEVEMENTS.PENDING:7')).toBeTruthy(); }); it('explains hidden achievements when nothing is visible', () => { renderCard(summary({unlocked: 0, startedGames: 0, perfectGames: 0, averageCompletion: null, hiddenGames: 5, pendingGames: 200, closest: []})); expect(screen.getByText('DASHBOARD.ACHIEVEMENTS.HIDDEN')).toBeTruthy(); expect(screen.queryByText(/DASHBOARD.ACHIEVEMENTS.PENDING/)).toBeNull(); expect(screen.getByText('–')).toBeTruthy(); }); it('says so when nothing is unlocked yet', () => { renderCard(summary({unlocked: 0, startedGames: 0, perfectGames: 0, averageCompletion: null, closest: []})); expect(screen.getByText('DASHBOARD.ACHIEVEMENTS.NONE')).toBeTruthy(); }); it('opensThePerfectGamesInTheOwnLibrary', async () => { fetchRoutes({'GET /api/library/stats/games': json(200, { content: [{appid: -7, name: 'Manual Game'}], page: 0, size: 40, totalElements: 1, totalPages: 1})}); render(); fireEvent.click(screen.getByRole('button', {name: 'DASHBOARD.ACHIEVEMENTS.PERFECT: 2'})); const link = await screen.findByRole('link', {name: /Manual Game/}); expect(fetch.mock.calls[0][0]).toContain('key=PERFECT&page=0'); expect(link.getAttribute('href')).toBe('/library/-7'); }); it('perfectGamesAreNotClickableAtZero', () => { render(); expect(screen.queryByRole('button')).toBeNull(); }); });