Kuma/tests/api/stripe/checkout-pass.test.ts
2026-10-02 14:30:54 +02:00

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" });
});
});