import { describe, it, expect, vi, afterEach } from 'vitest' import { renderHook, act, waitFor } from '@testing-library/react' import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import type { ReactNode } from 'react' // ─── Mocks ─────────────────────────────────────────────────────────────────── const { createCustomerPortalSessionMock } = vi.hoisted(() => ({ createCustomerPortalSessionMock: vi.fn(), })) vi.mock('../api', () => ({ createCustomerPortalSession: createCustomerPortalSessionMock, })) import { useCustomerPortal } from '../hooks/useCustomerPortal' afterEach(() => { createCustomerPortalSessionMock.mockReset() }) function wrapper({ children }: { children: ReactNode }) { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, mutations: { retry: false } }, }) return {children} } // ─── Tests ─────────────────────────────────────────────────────────────────── describe('useCustomerPortal', () => { it("openPortal() succès → window.location.href set sur l'URL portal", async () => { const originalLocation = window.location const hrefSetter = vi.fn() Object.defineProperty(window, 'location', { configurable: true, writable: true, value: { ...originalLocation, get href() { return originalLocation.href }, set href(v: string) { hrefSetter(v) }, }, }) createCustomerPortalSessionMock.mockResolvedValue({ url: 'https://billing.stripe.com/p/session/abc', }) const { result } = renderHook(() => useCustomerPortal(), { wrapper }) act(() => { result.current.openPortal() }) await waitFor(() => { expect(hrefSetter).toHaveBeenCalledWith('https://billing.stripe.com/p/session/abc') }) Object.defineProperty(window, 'location', { configurable: true, writable: true, value: originalLocation, }) }) it('erreur backend → message backend propagé dans `error`', async () => { createCustomerPortalSessionMock.mockRejectedValue( new Error('Aucun abonnement actif trouvé. Souscrivez d’abord à un plan.'), ) const { result } = renderHook(() => useCustomerPortal(), { wrapper }) act(() => { result.current.openPortal() }) await waitFor(() => { expect(result.current.error).toMatch(/Aucun abonnement actif trouvé/) }) }) it('isLoading vrai pendant la mutation pending', async () => { createCustomerPortalSessionMock.mockReturnValue(new Promise(() => {})) const { result } = renderHook(() => useCustomerPortal(), { wrapper }) expect(result.current.isLoading).toBe(false) act(() => { result.current.openPortal() }) await waitFor(() => { expect(result.current.isLoading).toBe(true) }) }) })