import { describe, expect, it } from "vitest"; import { PaymentPlanSchema, type PaymentPlan, type PaymentPlanInput, } from "@/data/schemas/payment"; import { canCheckoutSubscriptionPlan, findSelectedSubscriptionPlan, getDefaultSubscriptionPlanId, getFirstRechargeOfferView, requiresVipPlanConfirmation, toCoinsOfferPlanViews, toVipOfferPlanViews, } from "../subscription-screen.helpers"; function makePlan(overrides: Partial): PaymentPlan { return PaymentPlanSchema.parse({ planId: "plan", planName: "Plan", orderType: "vip_monthly", vipDays: 30, dolAmount: null, creditBalance: 0, amountCents: 1990, originalAmountCents: null, dailyPriceCents: null, currency: "USD", ...overrides, }); } describe("subscription screen helpers", () => { it("maps at most three VIP plans and all coin plans", () => { const plans = [ makePlan({ planId: "vip_monthly", planName: "Monthly" }), makePlan({ planId: "vip_quarterly", planName: "Quarterly", vipDays: 90 }), makePlan({ planId: "vip_annual", planName: "Annual", vipDays: 365 }), makePlan({ planId: "vip_extra", planName: "Extra", vipDays: 30 }), makePlan({ planId: "coin_1000", planName: "Coins", orderType: "coins_1000", vipDays: null, dolAmount: 1000, amountCents: 990, }), ]; expect(toVipOfferPlanViews(plans).map((plan) => plan.id)).toEqual([ "vip_monthly", "vip_quarterly", "vip_annual", ]); expect(toCoinsOfferPlanViews(plans)).toMatchObject([ { id: "coin_1000", coins: 1000, price: "9.9", currency: "US$", }, ]); }); it("finds selected coin plans in VIP mode", () => { const selected = findSelectedSubscriptionPlan({ canSubscribeVip: true, selectedPlanId: "coin_1000", vipPlans: [ { id: "vip_monthly", title: "Monthly", price: "19.90", currency: "usd", originalPrice: "", }, ], coinPlans: [ { id: "coin_1000", coins: 1000, price: "9.90", currency: "US$" }, ], }); expect(selected?.id).toBe("coin_1000"); }); it("formats plan amounts from cents with a dot decimal separator", () => { expect( toVipOfferPlanViews([ makePlan({ planId: "vip_test", amountCents: 7790, }), ]), ).toMatchObject([ { id: "vip_test", price: "77.9", }, ]); }); it("maps first recharge offer fields to plan views", () => { const vipViews = toVipOfferPlanViews([ makePlan({ planId: "vip_monthly", amountCents: 995, originalAmountCents: 1990, isFirstRechargeOffer: true, firstRechargeDiscountPercent: 50, promotionType: "first_recharge_half_price", }), ]); const coinViews = toCoinsOfferPlanViews([ makePlan({ planId: "coin_1000", orderType: "coins_1000", vipDays: null, dolAmount: 1000, amountCents: 495, originalAmountCents: 990, isFirstRechargeOffer: true, firstRechargeDiscountPercent: 50, promotionType: "first_recharge_half_price", }), ]); expect(vipViews[0]).toMatchObject({ price: "9.95", originalPrice: "19.9", isFirstRechargeOffer: true, firstRechargeDiscountPercent: 50, }); expect(coinViews[0]).toMatchObject({ price: "4.95", originalPrice: "9.9", isFirstRechargeOffer: true, firstRechargeDiscountPercent: 50, }); expect( getFirstRechargeOfferView({ isFirstRecharge: true, subscriptionType: "vip", vipPlans: vipViews, coinPlans: coinViews, }), ).toMatchObject({ badgeText: "50% OFF", title: "First Recharge Offer", renewalNotice: "First month 50% off. Renews at the regular price from the second month.", }); expect( getFirstRechargeOfferView({ isFirstRecharge: true, subscriptionType: "topup", vipPlans: vipViews, coinPlans: coinViews, }), ).toMatchObject({ badgeText: "50% OFF", title: "First Recharge Offer", renewalNotice: null, }); expect( getFirstRechargeOfferView({ isFirstRecharge: false, subscriptionType: "vip", vipPlans: vipViews, coinPlans: coinViews, }), ).toBeNull(); }); it("maps the backend most popular flag to VIP and coin views", () => { const popularVip = toVipOfferPlanViews([ makePlan({ planId: "vip_monthly", mostPopular: true }), ]); const popularCoins = toCoinsOfferPlanViews([ makePlan({ planId: "coin_1000", orderType: "coins_1000", vipDays: null, dolAmount: 1000, mostPopular: true, }), ]); expect(popularVip[0]?.mostPopular).toBe(true); expect(popularCoins[0]?.mostPopular).toBe(true); }); it("maps normal VIP original price outside first recharge activity", () => { expect( toVipOfferPlanViews([ makePlan({ planId: "vip_monthly", amountCents: 1990, originalAmountCents: 2499, isFirstRechargeOffer: false, }), ]), ).toMatchObject([ { id: "vip_monthly", price: "19.9", originalPrice: "24.99", isFirstRechargeOffer: false, }, ]); }); it("selects the first VIP plan by default when VIP can be purchased", () => { expect( getDefaultSubscriptionPlanId({ canSubscribeVip: true, selectedPlanId: "", status: "ready", isLoadingPlans: false, selectedPlan: null, vipPlans: [ { id: "vip_monthly", title: "Monthly", price: "19.90", currency: "usd", originalPrice: "", }, ], coinPlans: [], }), ).toBe("vip_monthly"); }); it("selects the first coin plan by default in top-up-only mode", () => { expect( getDefaultSubscriptionPlanId({ canSubscribeVip: false, selectedPlanId: "", status: "ready", isLoadingPlans: false, selectedPlan: null, vipPlans: [], coinPlans: [ { id: "coin_1000", coins: 1000, price: "9.9", currency: "US$", }, ], }), ).toBe("coin_1000"); }); it("does not override an existing selected plan", () => { expect( getDefaultSubscriptionPlanId({ canSubscribeVip: false, selectedPlanId: "coin_1000", status: "ready", isLoadingPlans: false, selectedPlan: { id: "coin_1000", coins: 1000, price: "9.9", currency: "US$", }, vipPlans: [], coinPlans: [ { id: "coin_1000", coins: 1000, price: "9.9", currency: "US$", }, ], }), ).toBeNull(); }); it("requires confirmation for each unconfirmed VIP plan", () => { const vipPlans = [ { id: "vip_monthly", title: "Monthly", price: "19.90", currency: "usd", originalPrice: "", }, { id: "vip_quarterly", title: "Quarterly", price: "49.90", currency: "usd", originalPrice: "", }, ]; expect( requiresVipPlanConfirmation({ planId: "vip_monthly", vipPlans, confirmedVipPlanIds: new Set(), }), ).toBe(true); expect( requiresVipPlanConfirmation({ planId: "vip_monthly", vipPlans, confirmedVipPlanIds: new Set(["vip_monthly"]), }), ).toBe(false); expect( requiresVipPlanConfirmation({ planId: "coin_1000", vipPlans, confirmedVipPlanIds: new Set(), }), ).toBe(false); }); it("allows checkout only after the selected VIP plan is confirmed", () => { const vipPlans = [ { id: "vip_monthly", title: "Monthly", price: "19.90", currency: "usd", originalPrice: "", }, ]; expect( canCheckoutSubscriptionPlan({ selectedPlanId: "vip_monthly", vipPlans, confirmedVipPlanIds: new Set(), }), ).toBe(false); expect( canCheckoutSubscriptionPlan({ selectedPlanId: "vip_monthly", vipPlans, confirmedVipPlanIds: new Set(["vip_monthly"]), }), ).toBe(true); expect( canCheckoutSubscriptionPlan({ selectedPlanId: "coin_1000", vipPlans, confirmedVipPlanIds: new Set(), }), ).toBe(true); expect( canCheckoutSubscriptionPlan({ selectedPlanId: "", vipPlans, confirmedVipPlanIds: new Set(), }), ).toBe(false); }); });