Files
cozsweet-frontend-nextjs/src/data/services/api/__tests__/payment_api.test.ts
T

119 lines
3.3 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const httpClientMock = vi.hoisted(() => vi.fn());
vi.mock("../http_client", () => ({
httpClient: httpClientMock,
}));
import { PaymentApi } from "../payment_api";
describe("PaymentApi", () => {
beforeEach(() => {
httpClientMock.mockReset();
});
it("loads the complete public gift catalog for a character", async () => {
httpClientMock.mockResolvedValue({
success: true,
data: {
characterId: "elio",
categories: [
{
category: "coffee",
name: "Coffee",
productCount: 1,
imageUrl: null,
},
],
plans: [
{
planId: "tip_coffee_usd_19_99",
planName: "Large Coffee",
orderType: "tip",
tipType: "coffee_large",
category: "coffee",
characterId: "elio",
description: "Buy Elio a large coffee",
imageUrl: null,
amountCents: 1999,
currency: "USD",
autoRenew: false,
isFirstRechargeOffer: false,
firstRechargeDiscountPercent: 0,
promotionType: null,
},
],
},
});
const response = await new PaymentApi().getGiftProducts("elio");
expect(httpClientMock).toHaveBeenCalledWith(
"/api/payment/gift-products",
{ query: { characterId: "elio" } },
);
expect(response.categories[0]?.category).toBe("coffee");
expect(response.plans[0]?.planId).toBe("tip_coffee_usd_19_99");
});
it("posts the paid order id when loading the Tip message", async () => {
httpClientMock.mockResolvedValue({
success: true,
data: {
orderId: "pay_xxx",
characterId: "elio",
planId: "tip_coffee_usd_19_99",
productName: "Large Coffee",
tipCount: 1,
poolIndex: 7,
message: "Thank you for the thoughtful gift.",
},
});
const response = await new PaymentApi().getTipMessage({
orderId: "pay_xxx",
});
expect(httpClientMock).toHaveBeenCalledWith("/api/payment/tip-message", {
method: "POST",
body: { orderId: "pay_xxx" },
});
expect(response.message).toBe("Thank you for the thoughtful gift.");
});
it("accepts a server-issued offer before opening the subscription page", async () => {
httpClientMock.mockResolvedValue({
success: true,
data: {
commercialOfferId: "offer-1",
planId: "vip_annual",
subscriptionType: "vip",
discountPercent: 30,
pricePercent: 70,
expiresAt: "2026-07-24T08:00:00+00:00",
message: "I got it for you.",
promotionType: "commercial_seven_discount",
},
});
const response = await new PaymentApi().acceptCommercialOffer("offer-1");
expect(httpClientMock).toHaveBeenCalledWith(
"/api/payment/commercial-offers/offer-1/accept",
{ method: "POST" },
);
expect(response.discountPercent).toBe(30);
});
it("requests an offer-scoped plan catalog without changing the public call", async () => {
httpClientMock.mockResolvedValue({ success: true, data: { plans: [] } });
await new PaymentApi().getPlans("offer-1");
expect(httpClientMock).toHaveBeenCalledWith("/api/payment/plans", {
query: { commercialOfferId: "offer-1" },
});
});
});