mirror of
https://github.com/Since-3/Kuma.git
synced 2026-10-12 21:41:17 +00:00
96 lines
3.2 KiB
TypeScript
96 lines
3.2 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
|
vi.mock("@/src/lib/prisma", () => ({ prisma: { product: { findUnique: vi.fn() } } }));
|
|
vi.mock("@/src/lib/auth/getUser", () => ({
|
|
getUserData: vi.fn(),
|
|
isUser: (user: { role: string }) => user.role === "user",
|
|
}));
|
|
vi.mock("@/src/lib/stripe", () => ({ getPlatformFeeCents: () => 50 }));
|
|
vi.mock("@/src/lib/stripe-checkout", () => ({
|
|
createBrandedCheckoutSession: vi.fn(),
|
|
studioCheckoutBranding: () => ({}),
|
|
}));
|
|
|
|
import { POST } from "@/src/app/api/stripe/checkout/pass/route";
|
|
import { prisma } from "@/src/lib/prisma";
|
|
import { getUserData } from "@/src/lib/auth/getUser";
|
|
import { createBrandedCheckoutSession } from "@/src/lib/stripe-checkout";
|
|
|
|
const product = {
|
|
id: "prod-1",
|
|
name: "10er-Karte",
|
|
credits: 10,
|
|
priceCents: 12000,
|
|
validityMonths: 6,
|
|
isActive: true,
|
|
business: {
|
|
id: "biz-1",
|
|
name: "Studio",
|
|
slug: "studio",
|
|
isPublic: true,
|
|
branding: null,
|
|
stripeAccountId: "acct_studio",
|
|
stripeAccountStatus: "active",
|
|
},
|
|
};
|
|
|
|
function request(body: unknown) {
|
|
return new Request("http://localhost/api/stripe/checkout/pass", {
|
|
method: "POST",
|
|
body: JSON.stringify(body),
|
|
}) as never;
|
|
}
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(getUserData).mockResolvedValue({
|
|
id: "user-1",
|
|
email: "kunde@example.com",
|
|
role: "user",
|
|
} as never);
|
|
vi.mocked(prisma.product.findUnique).mockResolvedValue(product as never);
|
|
vi.mocked(createBrandedCheckoutSession).mockResolvedValue({ url: "https://stripe/x" } as never);
|
|
});
|
|
|
|
describe("POST /api/stripe/checkout/pass", () => {
|
|
it("schickt Gäste zum Login", async () => {
|
|
vi.mocked(getUserData).mockResolvedValue(null);
|
|
const res = await POST(request({ productId: "prod-1" }));
|
|
expect(res.status).toBe(401);
|
|
expect((await res.json()).loginRequired).toBe(true);
|
|
});
|
|
|
|
it("lässt Team-Accounts keine Karte kaufen", async () => {
|
|
vi.mocked(getUserData).mockResolvedValue({ id: "m1", role: "manager" } as never);
|
|
expect((await POST(request({ productId: "prod-1" }))).status).toBe(403);
|
|
});
|
|
|
|
it("verkauft keine Karte, die nicht im Verkauf ist", async () => {
|
|
vi.mocked(prisma.product.findUnique).mockResolvedValue({
|
|
...product,
|
|
isActive: false,
|
|
} as never);
|
|
expect((await POST(request({ productId: "prod-1" }))).status).toBe(404);
|
|
expect(createBrandedCheckoutSession).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("nimmt die Servicegebühr pro Einheit als application_fee auf dem Studio-Account", async () => {
|
|
const res = await POST(request({ productId: "prod-1" }));
|
|
|
|
expect(res.status).toBe(200);
|
|
const [params, , accountId] = vi.mocked(createBrandedCheckoutSession).mock.calls[0];
|
|
expect(accountId).toBe("acct_studio");
|
|
expect(params.payment_intent_data?.application_fee_amount).toBe(500);
|
|
expect(params.line_items).toEqual([
|
|
expect.objectContaining({
|
|
quantity: 1,
|
|
price_data: expect.objectContaining({ unit_amount: 12000 }),
|
|
}),
|
|
expect.objectContaining({
|
|
quantity: 10,
|
|
price_data: expect.objectContaining({ unit_amount: 50 }),
|
|
}),
|
|
]);
|
|
expect(params.metadata).toMatchObject({ kind: "pass", productId: "prod-1", userId: "user-1" });
|
|
});
|
|
});
|