refactor(notification): rename markRead/markAllRead to optimistic helpers without fetch
Removes raw fetch() calls from the store. optimisticMarkRead(id) and optimisticMarkAllRead() now only mutate local $state — the actual API calls move to SvelteKit form actions on /aktivitaeten. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -108,12 +108,46 @@ describe('notificationStore (singleton)', () => {
|
|||||||
expect(notificationStore.unreadCount).toBe(1);
|
expect(notificationStore.unreadCount).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('markAllRead resets unreadCount', async () => {
|
it('optimisticMarkRead marks the notification read and decrements unreadCount without fetching', () => {
|
||||||
mockFetch.mockResolvedValue(new Response(null, { status: 200 }));
|
notificationStore.init();
|
||||||
await notificationStore.markAllRead();
|
const notification = makeNotification({ id: 'sse-1', read: false });
|
||||||
|
lastEventSource!.simulate('notification', JSON.stringify(notification));
|
||||||
|
mockFetch.mockReset(); // clear the fetchUnreadCount call from init
|
||||||
|
|
||||||
expect(mockFetch).toHaveBeenCalledWith('/api/notifications/read-all', { method: 'POST' });
|
notificationStore.optimisticMarkRead('sse-1');
|
||||||
|
|
||||||
|
expect(notificationStore.notifications[0].read).toBe(true);
|
||||||
expect(notificationStore.unreadCount).toBe(0);
|
expect(notificationStore.unreadCount).toBe(0);
|
||||||
|
expect(mockFetch).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('optimisticMarkRead on an already-read notification does not decrement unreadCount below 0', () => {
|
||||||
|
notificationStore.init();
|
||||||
|
const notification = makeNotification({ id: 'sse-1', read: true });
|
||||||
|
lastEventSource!.simulate('notification', JSON.stringify(notification));
|
||||||
|
|
||||||
|
notificationStore.optimisticMarkRead('sse-1');
|
||||||
|
|
||||||
|
expect(notificationStore.unreadCount).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('optimisticMarkAllRead resets unreadCount and marks all notifications read without fetching', () => {
|
||||||
|
notificationStore.init();
|
||||||
|
lastEventSource!.simulate(
|
||||||
|
'notification',
|
||||||
|
JSON.stringify(makeNotification({ id: 'n1', read: false }))
|
||||||
|
);
|
||||||
|
lastEventSource!.simulate(
|
||||||
|
'notification',
|
||||||
|
JSON.stringify(makeNotification({ id: 'n2', read: false }))
|
||||||
|
);
|
||||||
|
mockFetch.mockReset();
|
||||||
|
|
||||||
|
notificationStore.optimisticMarkAllRead();
|
||||||
|
|
||||||
|
expect(notificationStore.unreadCount).toBe(0);
|
||||||
|
expect(notificationStore.notifications.every((n) => n.read)).toBe(true);
|
||||||
|
expect(mockFetch).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -35,28 +35,19 @@ async function fetchUnreadCount(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markRead(notification: NotificationItem): Promise<void> {
|
function optimisticMarkRead(id: string): void {
|
||||||
if (!notification.read) {
|
const notification = notifications.find((n) => n.id === id);
|
||||||
try {
|
if (notification && !notification.read) {
|
||||||
await fetch(`/api/notifications/${notification.id}/read`, { method: 'PATCH' });
|
notification.read = true;
|
||||||
notification.read = true;
|
unreadCount = Math.max(0, unreadCount - 1);
|
||||||
unreadCount = Math.max(0, unreadCount - 1);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to mark notification as read', e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function markAllRead(): Promise<void> {
|
function optimisticMarkAllRead(): void {
|
||||||
try {
|
for (const n of notifications) {
|
||||||
await fetch('/api/notifications/read-all', { method: 'POST' });
|
n.read = true;
|
||||||
for (const n of notifications) {
|
|
||||||
n.read = true;
|
|
||||||
}
|
|
||||||
unreadCount = 0;
|
|
||||||
} catch (e) {
|
|
||||||
console.error('Failed to mark all notifications as read', e);
|
|
||||||
}
|
}
|
||||||
|
unreadCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(): void {
|
function init(): void {
|
||||||
@@ -123,8 +114,8 @@ export const notificationStore = {
|
|||||||
},
|
},
|
||||||
fetchNotifications,
|
fetchNotifications,
|
||||||
fetchUnreadCount,
|
fetchUnreadCount,
|
||||||
markRead,
|
optimisticMarkRead,
|
||||||
markAllRead,
|
optimisticMarkAllRead,
|
||||||
init,
|
init,
|
||||||
destroy
|
destroy
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user