diff --git a/CLAUDE.md b/CLAUDE.md index 9ca1969..76c3aba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,7 +49,7 @@ src/ │ ├── shared/ # Composants réutilisables │ └── transactions/ # Transactions ├── contexts/ # ProfileContext (état global profil) -├── hooks/ # 12 hooks custom (useReducer) +├── hooks/ # 13 hooks custom (useReducer) ├── pages/ # 11 pages ├── services/ # 14 services métier ├── shared/ # Types et constantes partagés diff --git a/src/hooks/useIsPremium.test.ts b/src/hooks/useIsPremium.test.ts new file mode 100644 index 0000000..4ca5c8a --- /dev/null +++ b/src/hooks/useIsPremium.test.ts @@ -0,0 +1,42 @@ +import { describe, it, expect, vi } from "vitest"; +import { useIsPremium } from "./useIsPremium"; + +vi.mock("./useLicense", () => ({ + useLicense: vi.fn(), +})); + +import { useLicense } from "./useLicense"; + +const mockUseLicense = vi.mocked(useLicense); + +describe("useIsPremium", () => { + it('returns true when edition is "premium"', () => { + mockUseLicense.mockReturnValue({ + state: { status: "ready", edition: "premium", info: null, error: null }, + refresh: vi.fn(), + submitKey: vi.fn(), + checkEntitlement: vi.fn(), + }); + expect(useIsPremium()).toBe(true); + }); + + it('returns false when edition is "base"', () => { + mockUseLicense.mockReturnValue({ + state: { status: "ready", edition: "base", info: null, error: null }, + refresh: vi.fn(), + submitKey: vi.fn(), + checkEntitlement: vi.fn(), + }); + expect(useIsPremium()).toBe(false); + }); + + it('returns false when edition is "free"', () => { + mockUseLicense.mockReturnValue({ + state: { status: "ready", edition: "free", info: null, error: null }, + refresh: vi.fn(), + submitKey: vi.fn(), + checkEntitlement: vi.fn(), + }); + expect(useIsPremium()).toBe(false); + }); +}); diff --git a/src/hooks/useIsPremium.ts b/src/hooks/useIsPremium.ts new file mode 100644 index 0000000..fdfbc7d --- /dev/null +++ b/src/hooks/useIsPremium.ts @@ -0,0 +1,10 @@ +import { useLicense } from "./useLicense"; + +/** + * Returns true if the active license edition is "premium". + * Ergonomic helper only — the server enforces entitlements independently (cf. ADR 0011 §UX). + */ +export function useIsPremium(): boolean { + const { state } = useLicense(); + return state.edition === "premium"; +}