import { describe, expect, it, vi } from "vitest"; import { sendCurrency } from "./send-currency"; function deps(delivered: boolean) { return { rcon: { giveCredits: vi.fn().mockResolvedValue(delivered), giveDuckets: vi.fn().mockResolvedValue(delivered), giveDiamonds: vi.fn().mockResolvedValue(delivered), givePointsGotw: vi.fn().mockResolvedValue(delivered), }, db: { user: { update: vi.fn().mockResolvedValue(undefined) }, usersCurrency: { upsert: vi.fn().mockResolvedValue(undefined) }, }, }; } describe("sendCurrency", () => { it("rejects non-positive amounts", async () => { const d = deps(true); expect(await sendCurrency(d, 1, "credits", 0)).toBe(false); expect(await sendCurrency(d, 1, "credits", null)).toBe(false); expect(d.rcon.giveCredits).not.toHaveBeenCalled(); }); it("delivers credits via RCON when connected (no DB write)", async () => { const d = deps(true); expect(await sendCurrency(d, 7, "credits", 100)).toBe(true); expect(d.rcon.giveCredits).toHaveBeenCalledWith(7, 100); expect(d.db.user.update).not.toHaveBeenCalled(); }); it("falls back to users.credits when RCON fails", async () => { const d = deps(false); await sendCurrency(d, 7, "credits", 100); expect(d.db.user.update).toHaveBeenCalledWith({ where: { id: 7 }, data: { credits: { increment: 100 } }, }); }); it("falls back to users_currency by type for diamonds", async () => { const d = deps(false); await sendCurrency(d, 7, "diamonds", 3); expect(d.db.usersCurrency.upsert).toHaveBeenCalledWith({ where: { userId_type: { userId: 7, type: 5 } }, update: { amount: { increment: 3 } }, create: { userId: 7, type: 5, amount: 3 }, }); }); it("uses the right type values (duckets=0, points=101)", async () => { const d = deps(false); await sendCurrency(d, 1, "duckets", 10); await sendCurrency(d, 1, "points", 20); expect(d.db.usersCurrency.upsert).toHaveBeenNthCalledWith( 1, expect.objectContaining({ create: { userId: 1, type: 0, amount: 10 } }), ); expect(d.db.usersCurrency.upsert).toHaveBeenNthCalledWith( 2, expect.objectContaining({ create: { userId: 1, type: 101, amount: 20 } }), ); }); });