Consolidate shared vi.mock bodies + migrate confirm/notification specs (#560) #719

Merged
marcel merged 17 commits from feat/issue-560-shared-vimock-mocks into main 2026-06-03 11:38:23 +02:00
Showing only changes of commit 30a8e36563 - Show all commits

View File

@@ -30,11 +30,12 @@ class NoopEventSource {
beforeEach(() => {
vi.stubGlobal('EventSource', NoopEventSource);
// init()'s fetchUnreadCount() never settles, so the bell's announced count is
// driven solely by setNotifications() — removes the init-fetch-vs-setNotifications
// race (the real fetch would resolve to {count:0} and clobber the seeded count).
vi.stubGlobal(
'fetch',
vi
.fn()
.mockResolvedValue(new Response(JSON.stringify({ count: 0, content: [] }), { status: 200 }))
vi.fn(() => new Promise(() => {}))
);
});
@@ -89,7 +90,6 @@ describe('NotificationBell — rendering', () => {
describe('NotificationBell — announced unread count across a11y states', () => {
it('empty: announces no unread count and hides the live badge', async () => {
const { setNotifications } = renderBell();
await tick();
setNotifications([]);
await tick();
@@ -101,7 +101,6 @@ describe('NotificationBell — announced unread count across a11y states', () =>
it('single: announces one unread notification', async () => {
const { setNotifications } = renderBell();
await tick();
setNotifications([makeNotification({ id: 'n1', read: false })]);
await tick();
@@ -114,7 +113,6 @@ describe('NotificationBell — announced unread count across a11y states', () =>
it('many: announces the exact unread count', async () => {
const { setNotifications } = renderBell();
await tick();
setNotifications([
makeNotification({ id: 'n1', read: false }),
makeNotification({ id: 'n2', read: false }),
@@ -128,16 +126,21 @@ describe('NotificationBell — announced unread count across a11y states', () =>
expect(unreadBadge().textContent?.trim()).toBe('3');
});
it('error: degrades to a zero announced count when the unread-count load fails', async () => {
it('error: a failed unread-count load does not wipe the announced count', async () => {
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('network down')));
renderBell();
const { setNotifications } = renderBell();
setNotifications([
makeNotification({ id: 'n1', read: false }),
makeNotification({ id: 'n2', read: false })
]);
await tick();
// A failed load leaves the count at 0; the bell still announces a valid,
// non-urgent state rather than a broken count.
// init()'s fetchUnreadCount rejects; its catch must leave the already-set
// count intact rather than silently zeroing the live region. This is a
// distinct state from "empty" — the count survived a transient load failure.
const btn = bellButton();
expect(btn.getAttribute('title')).toBe(m.notification_bell_label());
expect(btn.getAttribute('title')).toBe(m.notification_bell_unread_label({ count: 2 }));
expect(btn.getAttribute('aria-label')).toBe(btn.getAttribute('title'));
expect(unreadBadge().classList.contains('hidden')).toBe(true);
expect(unreadBadge().textContent?.trim()).toBe('2');
});
});