119 lines
3.3 KiB
TypeScript
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" },
|
|
});
|
|
});
|
|
});
|