Files
cozsweet-frontend-nextjs/src/app/subscription/__tests__/subscription-screen.helpers.test.ts
T

282 lines
7.3 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { PaymentPlan } from "@/data/dto/payment";
import {
canChooseSubscriptionPayChannel,
findSelectedSubscriptionPlan,
getDefaultPayChannelForCountryCode,
getDefaultSubscriptionPlanId,
getFirstRechargeOfferView,
resolveSubscriptionPayChannel,
toCoinsOfferPlanViews,
toVipOfferPlanViews,
} from "../subscription-screen.helpers";
function makePlan(
overrides: Partial<Parameters<typeof PaymentPlan.from>[0]>,
): PaymentPlan {
return PaymentPlan.from({
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("defaults Philippines users to Ezpay and other countries to Stripe", () => {
expect(getDefaultPayChannelForCountryCode("PH")).toBe("ezpay");
expect(getDefaultPayChannelForCountryCode("ph")).toBe("ezpay");
expect(getDefaultPayChannelForCountryCode("HK")).toBe("stripe");
expect(getDefaultPayChannelForCountryCode("")).toBe("stripe");
expect(getDefaultPayChannelForCountryCode(null)).toBe("stripe");
});
it("only allows payment method switching for Philippines users", () => {
expect(canChooseSubscriptionPayChannel("PH")).toBe(true);
expect(canChooseSubscriptionPayChannel("ph")).toBe(true);
expect(canChooseSubscriptionPayChannel("HK")).toBe(false);
expect(canChooseSubscriptionPayChannel(null)).toBe(false);
});
it("resolves subscription pay channel by country", () => {
expect(
resolveSubscriptionPayChannel({
countryCode: "PH",
requestedPayChannel: null,
}),
).toBe("ezpay");
expect(
resolveSubscriptionPayChannel({
countryCode: "PH",
requestedPayChannel: "stripe",
}),
).toBe("stripe");
expect(
resolveSubscriptionPayChannel({
countryCode: "HK",
requestedPayChannel: "ezpay",
}),
).toBe("stripe");
});
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,
vipPlans: vipViews,
coinPlans: coinViews,
}),
).toMatchObject({
badgeText: "50% OFF",
title: "First Recharge Offer",
});
expect(
getFirstRechargeOfferView({
isFirstRecharge: false,
vipPlans: vipViews,
coinPlans: coinViews,
}),
).toBeNull();
});
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();
});
});