66 lines
4.1 KiB
TypeScript
66 lines
4.1 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { validateVoucher, formatEuro, formatWert, formatMindestbestellwert, euroToCents, parseShopUrl, parseVoucherFields, VOUCHER_SOON_DAYS, isExpiringSoon } from "../lib/vouchers";
|
|
describe("validateVoucher", () => {
|
|
it("lehnt negativen Rest und Rest über Wert ab", () => {
|
|
const base = { name: "X", anbieter: "Y", wertCents: 5000, restCents: 6000, ablaufdatum: null };
|
|
expect(validateVoucher(base)).toContain("restCents");
|
|
expect(validateVoucher({ ...base, restCents: -1 })).toContain("restCents");
|
|
});
|
|
it("prozent: 1-100 gültig, Rest entfällt, Mindest optional", () => {
|
|
const base = { name: "X", anbieter: "Y", wertTyp: "prozent", wertCents: 0, restCents: 0, prozentWert: 20, ablaufdatum: null };
|
|
expect(validateVoucher(base)).toEqual([]);
|
|
expect(validateVoucher({ ...base, prozentWert: 0 })).toContain("prozentWert");
|
|
expect(validateVoucher({ ...base, prozentWert: 101 })).toContain("prozentWert");
|
|
expect(validateVoucher({ ...base, prozentWert: 12.5 })).toContain("prozentWert");
|
|
expect(validateVoucher({ ...base, mindestbestellwertCents: 5000 })).toEqual([]);
|
|
expect(validateVoucher({ ...base, mindestbestellwertCents: -1 })).toContain("mindestbestellwertCents");
|
|
expect(validateVoucher({ ...base, wertTyp: "falsch" })).toContain("wertTyp");
|
|
});
|
|
it("euroToCents versteht Komma- und Punkteingaben", () => {
|
|
expect(euroToCents("25,50")).toBe(2550);
|
|
expect(euroToCents("25.50")).toBe(2550);
|
|
expect(euroToCents("1.000,50")).toBe(100050);
|
|
expect(euroToCents("20")).toBe(2000);
|
|
expect(euroToCents("")).toBeNull();
|
|
expect(euroToCents(undefined)).toBeNull();
|
|
expect(Number.isNaN(euroToCents("abc") as number)).toBe(true);
|
|
});
|
|
it("parseVoucherFields teilt POST- und PATCH-Logik", () => {
|
|
const euro = parseVoucherFields({ name: "X", anbieter: "Y", wertCents: 1000, restCents: 500, shopUrl: "shop.de" });
|
|
expect(euro.errors).toEqual([]);
|
|
expect(euro.fields.wertTyp).toBe("euro");
|
|
expect(euro.fields.restCents).toBe(500);
|
|
expect(euro.fields.shopUrl).toBe("https://shop.de/");
|
|
const prozent = parseVoucherFields({ name: "X", anbieter: "Y", wertTyp: "prozent", prozentWert: 20, reminderDays: [] });
|
|
expect(prozent.errors).toEqual([]);
|
|
expect(prozent.fields.explicitNone).toBe(true);
|
|
expect(prozent.fields.reminderDays).toEqual([]);
|
|
expect(parseVoucherFields({ name: "X", anbieter: "Y", wertCents: 100, shopUrl: "javascript:alert(1)" }).errors).toEqual(["shopUrl"]);
|
|
expect(parseVoucherFields({ name: "X", anbieter: "Y", wertCents: 100, providerDomain: "keine domain" }).errors).toEqual(["providerDomain"]);
|
|
expect(parseVoucherFields({ name: "X", anbieter: "Y", wertCents: 100, reminderDays: "nonsens" }).errors).toEqual(["reminderDays"]);
|
|
});
|
|
it("parseShopUrl akzeptiert nur http(s)-Links", () => {
|
|
expect(parseShopUrl("")).toEqual({ url: null, error: false });
|
|
expect(parseShopUrl(null)).toEqual({ url: null, error: false });
|
|
expect(parseShopUrl("https://shop.de/gutschein")).toEqual({ url: "https://shop.de/gutschein", error: false });
|
|
expect(parseShopUrl("shop.de")).toEqual({ url: "https://shop.de/", error: false });
|
|
expect(parseShopUrl("javascript:alert(1)")).toEqual({ url: null, error: true });
|
|
expect(parseShopUrl("ftp://shop.de")).toEqual({ url: null, error: true });
|
|
expect(parseShopUrl("keine domain")).toEqual({ url: null, error: true });
|
|
});
|
|
it("formatWert zeigt Euro oder Prozent", () => {
|
|
expect(formatWert({ wertTyp: "euro", wertCents: 2550 })).toContain("25,50");
|
|
expect(formatWert({ wertTyp: "prozent", wertCents: 0, prozentWert: 20 })).toBe("20 % Rabatt");
|
|
expect(formatMindestbestellwert(null)).toBeNull();
|
|
expect(formatMindestbestellwert(10000)).toContain("100,00");
|
|
});
|
|
it("bald-Fenster = 30 Tage (Spec)", () => {
|
|
expect(VOUCHER_SOON_DAYS).toBe(30);
|
|
const now = new Date("2026-10-18T00:00:00Z").getTime();
|
|
const in20 = new Date(now + 20 * 24 * 3600 * 1000).toISOString();
|
|
const in40 = new Date(now + 40 * 24 * 3600 * 1000).toISOString();
|
|
expect(isExpiringSoon(in20, now)).toBe(true);
|
|
expect(isExpiringSoon(in40, now)).toBe(false);
|
|
});
|
|
});
|