Docker-Images bauen und veroeffentlichen / build-and-push (push) Failing after 1m32s
66 lines
3.0 KiB
TypeScript
66 lines
3.0 KiB
TypeScript
import { describe, expect, test } from "vitest";
|
|
import { buildSchedule, splitIntoInstallments } from "@/lib/payment-plan";
|
|
import { calculatePrice } from "@/lib/pricing";
|
|
|
|
describe("Exakte Zahlungsplaene laut Vorgabe", () => {
|
|
test.each([
|
|
["Early Bird", "EARLY_BIRD", false, [[220_000], [110_000, 110_000], [80_000, 70_000, 70_000]]],
|
|
["Early Bird Stammmodel", "EARLY_BIRD", true, [[198_000], [99_000, 99_000], [66_000, 66_000, 66_000]]],
|
|
["Regulaer", "REGULAR", false, [[275_000], [137_500, 137_500], [95_000, 90_000, 90_000]]],
|
|
["Regulaer Stammmodel", "REGULAR", true, [[247_500], [123_750, 123_750], [82_500, 82_500, 82_500]]],
|
|
] as const)("%s", (_label, phase, code, expected) => {
|
|
const total = calculatePrice(phase, code).totalCents;
|
|
for (const [index, plan] of expected.entries()) {
|
|
const split = splitIntoInstallments(total, index + 1);
|
|
expect(split).toEqual(plan);
|
|
expect(split.reduce((a, b) => a + b, 0)).toBe(total);
|
|
}
|
|
});
|
|
|
|
test("1.237,50 € je Rate bleibt centgenau", () => {
|
|
expect(splitIntoInstallments(247_500, 2)).toEqual([123_750, 123_750]);
|
|
});
|
|
|
|
test("mehr als drei Raten sind ausgeschlossen", () => {
|
|
expect(() => splitIntoInstallments(220_000, 4)).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("Faelligkeiten", () => {
|
|
const base = {
|
|
totalCents: 220_000,
|
|
campStartDate: "2027-06-05",
|
|
finalInstallmentLeadDays: 30,
|
|
minInstallmentGapDays: 14,
|
|
};
|
|
|
|
test("letzte Rate 30 Tage vor Anreise, zweite in der Mitte, Einzug 09:00 Berlin", () => {
|
|
const result = buildSchedule({ ...base, planType: "THREE_INSTALLMENTS", now: new Date("2026-11-15T10:00:00Z") });
|
|
expect(result.ok).toBe(true);
|
|
if (!result.ok) return;
|
|
// 172 Tage bis zur Frist -> zweite Rate nach 86 Tagen.
|
|
expect(result.installments.map((i) => i.dueDate)).toEqual([null, "2027-02-09", "2027-05-06"]);
|
|
// 06.05.2027 09:00 Sommerzeit = 07:00 UTC
|
|
expect(result.installments[2]!.dueAt!.toISOString()).toBe("2027-05-06T07:00:00.000Z");
|
|
expect(result.installments[0]!.amountCents).toBe(80_000);
|
|
});
|
|
|
|
test("ohne Camp-Termin keine Ratenzahlung, Einmalzahlung bleibt moeglich", () => {
|
|
const now = new Date("2026-11-15T10:00:00Z");
|
|
expect(buildSchedule({ ...base, campStartDate: null, planType: "TWO_INSTALLMENTS", now })).toEqual({
|
|
ok: false,
|
|
reason: "CAMP_DATE_MISSING",
|
|
});
|
|
expect(buildSchedule({ ...base, campStartDate: null, planType: "FULL", now }).ok).toBe(true);
|
|
});
|
|
|
|
test("zu knapp vor der Frist wird die Variante serverseitig deaktiviert", () => {
|
|
// Frist 06.05.2027; 20 Tage vorher reichen fuer zwei, nicht fuer drei Raten.
|
|
const now = new Date("2027-04-16T10:00:00Z");
|
|
expect(buildSchedule({ ...base, planType: "TWO_INSTALLMENTS", now }).ok).toBe(true);
|
|
expect(buildSchedule({ ...base, planType: "THREE_INSTALLMENTS", now })).toEqual({ ok: false, reason: "TOO_LATE" });
|
|
const later = new Date("2027-04-30T10:00:00Z");
|
|
expect(buildSchedule({ ...base, planType: "TWO_INSTALLMENTS", now: later })).toEqual({ ok: false, reason: "TOO_LATE" });
|
|
});
|
|
});
|