/** * Server Pricing Suite * * The server — never the client — decides what a plan costs. These tests pin * the pure checkout builder against the shared price catalog (src/lib/billing/ * pricing.ts): bogus plans fall back to annual, the catalog amounts (499 / * 3999 / 5999) are used verbatim when no Stripe Price ID is configured, and an * env Price ID wins when present. No real Stripe calls are made. */ import { describe, test, expect } from "./runner"; import { buildCheckoutParams } from "../../src/lib/billing/checkout"; import { PLAN_CONFIGS } from "../../src/lib/billing/pricing"; const user = { id: "usr_test_checkout_1" }; describe("ServerPricing — plan resolution", () => { test("unknown or missing plans fall back to annual", () => { expect(buildCheckoutParams(user, "enterprise-ultra", {}).metadata.plan).toBe("annual"); expect(buildCheckoutParams(user, undefined, {}).metadata.plan).toBe("annual"); expect(buildCheckoutParams(user, null, {}).metadata.plan).toBe("annual"); expect(buildCheckoutParams(user, "", {}).metadata.plan).toBe("annual"); }); test("a bogus plan is charged the annual price, never an invented one", () => { const params = buildCheckoutParams(user, "FREE_FOREVER", {}); expect(params.metadata.plan).toBe("annual"); expect(params.lineItems[0].price_data?.unit_amount).toBe(PLAN_CONFIGS.annual.unitAmountMinor); expect(params.lineItems[0].price_data?.unit_amount).toBe(3999); }); test("known plan ids resolve to themselves", () => { expect(buildCheckoutParams(user, "weekly", {}).metadata.plan).toBe("weekly"); expect(buildCheckoutParams(user, "annual", {}).metadata.plan).toBe("annual"); expect(buildCheckoutParams(user, "lifetime", {}).metadata.plan).toBe("lifetime"); }); }); describe("ServerPricing — catalog amounts", () => { test("without an env Price ID, unit_amount is exactly the catalog value per plan", () => { expect(buildCheckoutParams(user, "weekly", {}).lineItems[0].price_data?.unit_amount).toBe(499); expect(buildCheckoutParams(user, "annual", {}).lineItems[0].price_data?.unit_amount).toBe(3999); expect(buildCheckoutParams(user, "lifetime", {}).lineItems[0].price_data?.unit_amount).toBe(5999); }); test("the amounts stay pinned to PLAN_CONFIGS and never drift apart", () => { expect(buildCheckoutParams(user, "weekly", {}).lineItems[0].price_data?.unit_amount).toBe( PLAN_CONFIGS.weekly.unitAmountMinor ); expect(buildCheckoutParams(user, "annual", {}).lineItems[0].price_data?.unit_amount).toBe( PLAN_CONFIGS.annual.unitAmountMinor ); expect(buildCheckoutParams(user, "lifetime", {}).lineItems[0].price_data?.unit_amount).toBe( PLAN_CONFIGS.lifetime.unitAmountMinor ); }); test("a client-supplied amount cannot influence the charged price", () => { // The builder accepts no amount parameter; the body can only carry a plan // id, so the catalog amount is what gets charged no matter what else a // tampered request tries to inject. const params = buildCheckoutParams(user, "annual", {} as any); expect(params.lineItems[0].price_data?.unit_amount).toBe(PLAN_CONFIGS.annual.unitAmountMinor); expect(params.lineItems[0].price_data?.unit_amount).toBe(3999); }); }); describe("ServerPricing — env Price ID precedence", () => { test("a configured env Price ID wins and suppresses price_data entirely", () => { const weekly = buildCheckoutParams(user, "weekly", { STRIPE_WEEKLY_PRICE_ID: "price_weekly_test", }); expect(weekly.lineItems[0].price).toBe("price_weekly_test"); expect(weekly.lineItems[0].price_data).toBeUndefined(); const annual = buildCheckoutParams(user, "annual", { STRIPE_ANNUAL_PRICE_ID: "price_annual_test", }); expect(annual.lineItems[0].price).toBe("price_annual_test"); expect(annual.lineItems[0].price_data).toBeUndefined(); const lifetime = buildCheckoutParams(user, "lifetime", { STRIPE_LIFETIME_PRICE_ID: "price_lifetime_test", }); expect(lifetime.lineItems[0].price).toBe("price_lifetime_test"); expect(lifetime.lineItems[0].price_data).toBeUndefined(); }); test("the env Price ID comes from the plan's own catalog entry", () => { const weekly = buildCheckoutParams(user, "weekly", { [PLAN_CONFIGS.weekly.priceIdEnv]: "price_weekly_test", }); expect(weekly.lineItems[0].price).toBe("price_weekly_test"); expect(weekly.lineItems[0].price_data).toBeUndefined(); }); }); describe("ServerPricing — subscription shape", () => { test("weekly is a subscription with a 3-day trial and weekly billing", () => { const params = buildCheckoutParams(user, "weekly", {}); expect(params.mode).toBe("subscription"); expect(params.subscriptionData?.trial_period_days).toBe(3); expect(params.subscriptionData?.metadata?.plan).toBe("weekly"); expect(params.lineItems[0].price_data?.recurring?.interval).toBe("week"); }); test("annual is a subscription billed yearly, without any trial", () => { const params = buildCheckoutParams(user, "annual", {}); expect(params.mode).toBe("subscription"); expect(params.subscriptionData?.trial_period_days).toBeUndefined(); expect(params.subscriptionData?.metadata?.plan).toBe("annual"); expect(params.lineItems[0].price_data?.recurring?.interval).toBe("year"); }); test("lifetime is a one-off payment without subscription data", () => { const params = buildCheckoutParams(user, "lifetime", {}); expect(params.mode).toBe("payment"); expect(params.subscriptionData).toBeUndefined(); expect(params.lineItems[0].price_data?.recurring).toBeUndefined(); }); test("only the weekly pass ever carries a trial", () => { const plans = ["weekly", "annual", "lifetime"] as const; for (const plan of plans) { const params = buildCheckoutParams(user, plan, {}); const trial = params.subscriptionData?.trial_period_days; expect(trial).toBe(plan === "weekly" ? 3 : undefined); } }); }); describe("ServerPricing — metadata & reference", () => { test("metadata always carries the resolved plan and the user id", () => { for (const plan of ["weekly", "annual", "lifetime"]) { const params = buildCheckoutParams(user, plan, {}); expect(params.metadata.plan).toBe(plan); expect(params.metadata.userId).toBe(user.id); expect(params.clientReferenceId).toBe(user.id); } }); test("the fallback plan keeps the authenticated user's id attached", () => { const params = buildCheckoutParams(user, "hacker-plan", {}); expect(params.metadata.plan).toBe("annual"); expect(params.metadata.userId).toBe(user.id); expect(params.clientReferenceId).toBe(user.id); }); });