feat(stats): add chart form pickers to dashboard and profile tiles
Build, Test & Push Frontend / quality-check (push) Successful in 31s
Build, Test & Push Frontend / docker (push) Successful in 23s

This commit is contained in:
lobo committed 2026-10-04 21:06:21 +02:00
1 parent 13b0d5e7e9
commit de199a20b7
19 files changed
+507 -98

No files matched your search

+42 -2
View File
@@ -1,6 +1,6 @@
// @vitest-environment jsdom
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
import {cleanup, fireEvent, screen, waitFor} from '@testing-library/react';
import {cleanup, fireEvent, screen, waitFor, within} from '@testing-library/react';
import Dashboard from './Dashboard.jsx';
import {fetchRoutes, json} from '../test/fetchRoutes.js';
import {renderWithProviders} from '../test/renderWithProviders.jsx';
@@ -113,7 +113,47 @@ describe('Dashboard', () => {
expect(screen.getByRole('button', {name: /2024/})).toBeTruthy();
expect(screen.getByText('2023: 0')).toBeTruthy();
expect(screen.queryByRole('button', {name: /2023/})).toBeNull();
expect(screen.queryByRole('group', {name: 'STATS.CHART.LABEL'})).toBeNull();
expect(screen.getByRole('group', {name: 'STATS.CHART.LABEL'})).toBeTruthy();
});
const putBodies = () => fetch.mock.calls.filter(([, init]) => init?.method === 'PUT').map(([, init]) => JSON.parse(init.body));
it('aTasteTilePickerSavesAndRedraws', async () => {
fetchRoutes({
...dashboardRoutes({dashboardTiles: [{id: 'STATS_TASTE', size: 'M'}]}),
'GET /api/library/stats': json(200, {trend: null, taste: {genres: [{name: 'Shooter', games: 2, minutes: 1200},
{name: 'Puzzle', games: 1, minutes: 300}], moods: []}}),
'PUT /api/users/settings/stat-chart': json(204, {}),
});
const {container} = renderDashboard();
await screen.findByText('STATS.TASTE.TITLE');
fireEvent.click(within(screen.getByRole('group', {name: 'STATS.CHART.LABEL'})).getByRole('button', {name: 'STATS.CHART.PIE'}));
await waitFor(() => expect(container.querySelectorAll('path.stroke-card').length).toBeGreaterThan(0));
expect(putBodies()).toEqual([{group: 'TASTE', chart: 'PIE'}]);
});
it('theMostPlayedCardShowsTheTopGamesForm', async () => {
const container = mockDashboard({dashboardTiles: [{id: 'MOST_PLAYED', size: 'L'}], statCharts: {TOP_GAMES: 'DONUT'}});
await screen.findByRole('group', {name: 'STATS.CHART.LABEL'});
expect(container.querySelectorAll('path.stroke-card')).toHaveLength(6);
const card = container.querySelector('[data-tile="MOST_PLAYED"]');
expect(within(card).getAllByRole('link', {name: /Game/})).toHaveLength(5);
expect(within(card).getByText('STATS.CHART.OTHER').closest('a,button')).toBeNull();
});
it('theActivityPickerSavesTheForm', async () => {
fetchRoutes({...dashboardRoutes(), 'PUT /api/users/settings/stat-chart': json(204, {})});
const {container} = renderDashboard();
await screen.findByText('DASHBOARD.ACTIVITY');
const card = container.querySelector('[data-tile="ACTIVITY"]');
fireEvent.click(within(card).getByRole('button', {name: 'STATS.CHART.LINE'}));
await waitFor(() => expect(container.querySelector('polyline')).not.toBeNull());
expect(putBodies()).toEqual([{group: 'ACTIVITY', chart: 'LINE'}]);
});
it('leaves out a stat tile whose data did not come', async () => {