feat: Wabenhain Honig-Shop Anwendung

Vollstaendige Next.js/Prisma-E-Commerce-Anwendung fuer eine Imkerei:
Shop, Warenkorb, Stripe-Checkout, Kundenkonto mit 2FA, Admin-Bereich
(Produkte, Ernten, Chargen, Bestellungen, Gutscheine, admin-editierbare
Website-Inhalte), i18n (DE/EN), Rate-Limiting/CSP/Audit-Log-Haertung,
PostgreSQL- und MySQL-Unterstuetzung ueber austauschbare Prisma-
Treiber-Adapter, Unit-/Komponenten-/E2E-Tests.
This commit is contained in:
Nick Szaunig committed 2026-08-17 14:30:28 +02:00
1 parent 5c76fcc266
commit c7927f2883
240 files changed
+26096 -137

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
import { describe, test, expect } from "vitest";
import { resolveShippingCostCents, getNextShippingTier, FALLBACK_SHIPPING_CENTS } from "./shipping-calc";
const tiers = [
{ minQuantity: 0, maxQuantity: 3, priceCents: 700 },
{ minQuantity: 4, maxQuantity: 9, priceCents: 850 },
{ minQuantity: 10, maxQuantity: null, priceCents: 1100 },
];
describe("resolveShippingCostCents", () => {
test("returns 0 when the cart is empty", () => {
expect(resolveShippingCostCents(tiers, 0)).toBe(0);
});
test("falls back to a fixed price when no tiers are configured", () => {
expect(resolveShippingCostCents([], 5)).toBe(FALLBACK_SHIPPING_CENTS);
});
test("picks the lowest tier for a small quantity", () => {
expect(resolveShippingCostCents(tiers, 2)).toBe(700);
});
test("picks the middle tier at its lower boundary", () => {
expect(resolveShippingCostCents(tiers, 4)).toBe(850);
});
test("picks the middle tier at its upper boundary", () => {
expect(resolveShippingCostCents(tiers, 9)).toBe(850);
});
test("applies the open-ended top tier for large quantities", () => {
expect(resolveShippingCostCents(tiers, 500)).toBe(1100);
});
test("uses the topmost tier when the quantity exceeds every defined tier", () => {
const closedTiers = [{ minQuantity: 0, maxQuantity: 3, priceCents: 700 }];
expect(resolveShippingCostCents(closedTiers, 50)).toBe(700);
});
test("is unaffected by tier input order", () => {
const shuffled = [...tiers].reverse();
expect(resolveShippingCostCents(shuffled, 4)).toBe(850);
});
});
describe("getNextShippingTier", () => {
test("returns null for an empty cart", () => {
expect(getNextShippingTier(tiers, 0)).toBeNull();
});
test("returns null when no tiers are configured", () => {
expect(getNextShippingTier([], 2)).toBeNull();
});
test("returns null when already in the topmost open-ended tier", () => {
expect(getNextShippingTier(tiers, 15)).toBeNull();
});
test("reports units and price of the next tier", () => {
expect(getNextShippingTier(tiers, 2)).toEqual({ unitsUntilNext: 2, priceCents: 850 });
});
test("reports 1 unit remaining right below a boundary", () => {
expect(getNextShippingTier(tiers, 3)).toEqual({ unitsUntilNext: 1, priceCents: 850 });
});
test("is unaffected by tier input order", () => {
const shuffled = [...tiers].reverse();
expect(getNextShippingTier(shuffled, 9)).toEqual({ unitsUntilNext: 1, priceCents: 1100 });
});
});