expria-frontend/src/features/billing/__tests__/useCustomerPortal.test.tsx
Hermann_Kitio de16deede3 feat(billing): Customer Portal + page Paramètres + Standard→Premium via portal
- useCustomerPortal hook (mutation + redirect full-page)
- AccountBillingSection: badge plan + bouton Gérer mon abonnement (Standard/Premium)
- ParametresPage: page conteneur /parametres avec section billing
- PricingPage: Standard→Premium redirige vers Customer Portal (prorata natif Stripe)
- Tests: 212 → 219 verts (+7)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 05:43:06 +03:00

97 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
}
// ─── 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 dabord à 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)
})
})
})