// @vitest-environment jsdom import {afterEach, describe, expect, it, vi} from 'vitest'; import {cleanup, screen, waitFor} from '@testing-library/react'; import InboxPage from './InboxPage.jsx'; import {fetchRoutes, json} from '../test/fetchRoutes.js'; import {renderWithProviders} from '../test/renderWithProviders.jsx'; vi.mock('react-i18next', () => import('../test/i18n-mock.js')); const note = (id, extra) => ({id, kind: 'DIGEST', displayName: 'Lobo', newGames: 0, achievements: 0, statusChanges: 0, wishlistAdds: 0, createdAt: '2026-10-06T10:00:00Z', read: false, ...extra}); const putCalls = () => fetch.mock.calls.filter(([, init]) => init?.method === 'PUT'); afterEach(() => { cleanup(); vi.clearAllMocks(); }); describe('InboxPage', () => { it('showsADigestWithOnlyTheNonZeroPartsAndMarksTheNotesRead', async () => { fetchRoutes({'GET /api/inbox': json(200, {results: [note(1, {newGames: 12, wishlistAdds: 2})], unread: 1}), 'PUT /api/inbox/read': json(204)}); renderWithProviders(); expect(await screen.findByText('INBOX.DIGEST')).toBeTruthy(); await waitFor(() => expect(putCalls()).toHaveLength(1)); }); it('showsAVisibilityNote', async () => { fetchRoutes({'GET /api/inbox': json(200, {results: [note(1, {kind: 'VISIBILITY'})], unread: 1}), 'PUT /api/inbox/read': json(204)}); renderWithProviders(); expect(await screen.findByText('INBOX.VISIBILITY')).toBeTruthy(); }); it.each(['PSN_EXPIRING', 'PSN_EXPIRED'])('shows the %s note with a link to the settings', async (kind) => { fetchRoutes({'GET /api/inbox': json(200, {results: [note(1, {kind, displayName: null})], unread: 1}), 'PUT /api/inbox/read': json(204)}); renderWithProviders(); expect(await screen.findByText(`INBOX.${kind}`)).toBeTruthy(); expect(screen.getByRole('link', {name: 'INBOX.OPEN_SETTINGS'}).getAttribute('href')).toBe('/settings'); expect(screen.queryByText('INBOX.DIGEST')).toBeNull(); }); it('gives a digest or a visibility note no settings link', async () => { fetchRoutes({'GET /api/inbox': json(200, {results: [note(1, {newGames: 2}), note(2, {kind: 'VISIBILITY'})], unread: 0})}); renderWithProviders(); expect(await screen.findByText('INBOX.VISIBILITY')).toBeTruthy(); expect(screen.queryByRole('link', {name: 'INBOX.OPEN_SETTINGS'})).toBeNull(); }); it('saysSoWhenThereAreNoNotesAndMarksNothing', async () => { fetchRoutes({'GET /api/inbox': json(200, {results: [], unread: 0})}); renderWithProviders(); expect(await screen.findByText('INBOX.EMPTY')).toBeTruthy(); expect(putCalls()).toEqual([]); }); it('showsAnErrorAndMarksNothingWhenTheLoadFails', async () => { fetchRoutes({'GET /api/inbox': json(500, {})}); renderWithProviders(); expect(await screen.findByText('INBOX.LOAD_ERROR')).toBeTruthy(); expect(putCalls()).toEqual([]); }); });