import type { ComponentProps, ReactNode } from 'react'; import { cleanup, fireEvent, render, screen } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { api } from '@spoon/backend/convex/_generated/api.js'; import { NotificationPreferencesPanel } from '../../src/components/settings/notification-preferences-panel'; // Stable sentinels: the real Convex `api` proxy hands back a fresh reference on // every access, so `===` comparisons in the mocks below would never match. vi.mock('@spoon/backend/convex/_generated/api.js', () => ({ api: { notifications: { getPreferences: 'notifications:getPreferences', updatePreferences: 'notifications:updatePreferences', }, }, })); const { mockUpdatePreferences, mockUseMutation, mockUseQuery } = vi.hoisted( () => ({ mockUpdatePreferences: vi.fn(), mockUseMutation: vi.fn(), mockUseQuery: vi.fn(), }), ); vi.mock('convex/react', () => ({ useMutation: mockUseMutation, useQuery: mockUseQuery, })); vi.mock('sonner', () => ({ toast: { error: vi.fn(), success: vi.fn() }, })); // Pass-through UI primitives so the switches are deterministically present and // clickable under jsdom (Radix pointer behavior is flaky here). We exercise the // panel's logic, not the design-system components. vi.mock('@spoon/ui', () => ({ Card: ({ children }: { children?: ReactNode }) =>
{children}
, Label: ({ children }: { children?: ReactNode }) => , Switch: ({ checked, onCheckedChange, disabled, ...props }: { checked?: boolean; onCheckedChange?: (value: boolean) => void; disabled?: boolean; } & ComponentProps<'button'>) => (