fix(ui/alerts): remove dead usePageVisible subscription; align alerts test mock with DTO

NotificationBell used a usePageVisible() subscription that re-rendered on
every visibilitychange without consuming the value. TanStack Query's
refetchIntervalInBackground:false already pauses polling; the extra
subscription was speculative generality. Dropped the import + call + JSDoc
reference; usePageVisible hook + test retained as a reusable primitive.

Also: alerts.test.tsx 'returns the server payload unmodified' asserted a
pre-plan {total, bySeverity} shape, but UnreadCountResponse is actually
{count}. Fixed mock + assertion to {count: 3}.
This commit is contained in:
hsiegeln
2026-04-20 13:30:07 +02:00
parent 197c60126c
commit 38083d7c3f
2 changed files with 6 additions and 20 deletions

View File

@@ -60,14 +60,11 @@ describe('useUnreadCount', () => {
it('returns the server payload unmodified', async () => {
(apiClient.GET as any).mockResolvedValue({
data: { total: 3, bySeverity: { CRITICAL: 1, WARNING: 2, INFO: 0 } },
data: { count: 3 },
error: null,
});
const { result } = renderHook(() => useUnreadCount(), { wrapper });
await waitFor(() => expect(result.current.isSuccess).toBe(true));
expect(result.current.data).toEqual({
total: 3,
bySeverity: { CRITICAL: 1, WARNING: 2, INFO: 0 },
});
expect(result.current.data).toEqual({ count: 3 });
});
});

View File

@@ -2,7 +2,6 @@ import { Link } from 'react-router';
import { Bell } from 'lucide-react';
import { useUnreadCount } from '../api/queries/alerts';
import { useSelectedEnv } from '../api/queries/alertMeta';
import { usePageVisible } from '../hooks/usePageVisible';
import css from './NotificationBell.module.css';
/**
@@ -10,23 +9,13 @@ import css from './NotificationBell.module.css';
* inbox and renders a badge with the unread-alert count for the currently
* selected environment.
*
* Polling is driven by `useUnreadCount` (30s interval, paused in background
* via TanStack Query's `refetchIntervalInBackground: false`). The
* `usePageVisible` hook is retained as a defense-in-depth signal so future
* UI behavior (e.g. animations, live-region updates) can key off visibility
* without re-wiring the polling logic.
*
* TODO (spec §13): per-severity badge coloring — the backend
* `UnreadCountResponse` currently exposes only a scalar `count` field. To
* colour the badge by max unread severity (CRITICAL → error, WARNING →
* amber, INFO → muted) the DTO must grow a `bySeverity` map; deferred to a
* future task. Until then the badge uses a single `var(--error)` tint.
* Polling pause when the tab is hidden is handled by `useUnreadCount`'s
* `refetchIntervalInBackground: false`; no separate visibility subscription
* is needed. If per-severity coloring (spec §13) is re-introduced, the
* backend `UnreadCountResponse` must grow a `bySeverity` map.
*/
export function NotificationBell() {
const env = useSelectedEnv();
// Subscribe to visibility so the component re-renders on tab focus, even
// though the polling pause itself is handled inside useUnreadCount.
usePageVisible();
const { data } = useUnreadCount();
const count = data?.count ?? 0;