Public Access
feat: add What's new feature
Dashboard dialog shows unseen news entries. Users mark them seen with "Got it" or revisit via the /whats-new page. Admins publish, edit, and delete entries on /admin/news. Full i18n support and test coverage included.
This commit is contained in:
1 parent
79b086c525
commit
b811255c16
17 files changed
+690
-1
No files matched your search
@@ -0,0 +1,45 @@
|
||||
// @vitest-environment jsdom
|
||||
import {afterEach, describe, expect, it, vi} from 'vitest';
|
||||
import {cleanup, screen} from '@testing-library/react';
|
||||
import WhatsNewPage from './WhatsNewPage.jsx';
|
||||
import {fetchRoutes, json} from '../test/fetchRoutes.js';
|
||||
import {renderWithProviders} from '../test/renderWithProviders.jsx';
|
||||
|
||||
vi.mock('react-i18next', () => import('../test/i18n-mock.js'));
|
||||
|
||||
const entry = (id, title) => ({id, titleEn: title, titleDe: null, textEn: `${title} text`, textDe: null,
|
||||
publishedAt: '2026-10-01T10:00:00Z', seen: false});
|
||||
const putCalls = () => fetch.mock.calls.filter(([, init]) => init?.method === 'PUT');
|
||||
|
||||
describe('WhatsNewPage', () => {
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('lists the entries in the given order and marks them seen once', async () => {
|
||||
fetchRoutes({'GET /api/news': json(200, {results: [entry(2, 'Second'), entry(1, 'First')]}),
|
||||
'PUT /api/news/seen': json(204)});
|
||||
renderWithProviders(<WhatsNewPage/>);
|
||||
|
||||
await screen.findByText('Second');
|
||||
|
||||
expect(screen.getAllByRole('heading', {level: 3}).map((heading) => heading.textContent)).toEqual(['Second', 'First']);
|
||||
expect(putCalls()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('says so when there are no entries', async () => {
|
||||
fetchRoutes({'GET /api/news': json(200, {results: []}), 'PUT /api/news/seen': json(204)});
|
||||
renderWithProviders(<WhatsNewPage/>);
|
||||
|
||||
expect(await screen.findByText('NEWS.EMPTY')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('shows an error and marks nothing when the load fails', async () => {
|
||||
fetchRoutes({'GET /api/news': json(500, {})});
|
||||
renderWithProviders(<WhatsNewPage/>);
|
||||
|
||||
expect(await screen.findByText('NEWS.LOAD_ERROR')).toBeTruthy();
|
||||
expect(putCalls()).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user