- useStripeCheckout: mutation + redirect full-page, pendingPriceType exposed - PricingPage migré vers useStripeCheckout (suppression useMutation inline) - useUpgradeSuccessHandler: détecte ?upgrade=success, invalide plan cache, clean URL - UpgradeSuccessBanner: callout success dans DashboardPage - Tests: 203 → 212 verts (+9) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88 lines
3.1 KiB
TypeScript
88 lines
3.1 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
import { renderHook, act } from '@testing-library/react'
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
import type { ReactNode } from 'react'
|
|
|
|
import { PLAN_QUERY_KEY } from '@/entities/user/query-keys'
|
|
import { useUpgradeSuccessHandler } from '../useUpgradeSuccessHandler'
|
|
|
|
let invalidateSpy: ReturnType<typeof vi.fn>
|
|
let queryClient: QueryClient
|
|
|
|
function wrapper({ children }: { children: ReactNode }) {
|
|
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
}
|
|
|
|
function setLocation(search: string) {
|
|
window.history.replaceState(null, '', `/dashboard${search}`)
|
|
}
|
|
|
|
beforeEach(() => {
|
|
queryClient = new QueryClient({
|
|
defaultOptions: { queries: { retry: false } },
|
|
})
|
|
invalidateSpy = vi.fn().mockResolvedValue(undefined)
|
|
// Spy sur la méthode invalidateQueries pour vérifier la clé exacte.
|
|
queryClient.invalidateQueries = invalidateSpy as unknown as typeof queryClient.invalidateQueries
|
|
})
|
|
|
|
afterEach(() => {
|
|
setLocation('')
|
|
})
|
|
|
|
describe('useUpgradeSuccessHandler', () => {
|
|
it('?upgrade=success → showSuccess=true, invalidate(PLAN_QUERY_KEY) appelé, URL nettoyée', () => {
|
|
setLocation('?upgrade=success')
|
|
|
|
const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })
|
|
|
|
expect(result.current.showSuccess).toBe(true)
|
|
expect(invalidateSpy).toHaveBeenCalledTimes(1)
|
|
expect(invalidateSpy).toHaveBeenCalledWith({ queryKey: PLAN_QUERY_KEY })
|
|
// URL nettoyée : plus de `upgrade` dans la query string.
|
|
expect(window.location.search).toBe('')
|
|
})
|
|
|
|
it('absence de query param → showSuccess=false, invalidate non appelé', () => {
|
|
setLocation('')
|
|
|
|
const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })
|
|
|
|
expect(result.current.showSuccess).toBe(false)
|
|
expect(invalidateSpy).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it("?upgrade=cancelled (autre valeur) → showSuccess=false, pas d'action", () => {
|
|
setLocation('?upgrade=cancelled')
|
|
|
|
const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })
|
|
|
|
expect(result.current.showSuccess).toBe(false)
|
|
expect(invalidateSpy).not.toHaveBeenCalled()
|
|
// URL conservée intacte (autre valeur, hors scope du nettoyage).
|
|
expect(window.location.search).toBe('?upgrade=cancelled')
|
|
})
|
|
|
|
it('dismiss() bascule showSuccess à false', () => {
|
|
setLocation('?upgrade=success')
|
|
|
|
const { result } = renderHook(() => useUpgradeSuccessHandler(), { wrapper })
|
|
expect(result.current.showSuccess).toBe(true)
|
|
|
|
act(() => {
|
|
result.current.dismiss()
|
|
})
|
|
expect(result.current.showSuccess).toBe(false)
|
|
})
|
|
|
|
it('conserve les autres query params (utm_*, etc.) lors du nettoyage', () => {
|
|
setLocation('?upgrade=success&utm_source=email&ref=abc')
|
|
|
|
renderHook(() => useUpgradeSuccessHandler(), { wrapper })
|
|
|
|
const params = new URLSearchParams(window.location.search)
|
|
expect(params.has('upgrade')).toBe(false)
|
|
expect(params.get('utm_source')).toBe('email')
|
|
expect(params.get('ref')).toBe('abc')
|
|
})
|
|
})
|